Skip to content

Commit 2b72ecb

Browse files
authored
Rollup merge of #94464 - kckeiks:lifetime-elision-mismatch-hint-for-traits, r=estebank
Suggest adding a new lifetime parameter when two elided lifetimes should match up for traits and impls. Suggest adding a new lifetime parameter when two elided lifetimes should match up for functions in traits and impls. Issue #94462
2 parents f0c4da4 + 1b08cba commit 2b72ecb

11 files changed

+264
-52
lines changed

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs

Lines changed: 54 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -166,59 +166,61 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
166166
if lifetime_sub.name.is_elided() && lifetime_sup.name.is_elided() {
167167
if let Some(anon_reg) = self.tcx().is_suitable_region(sub) {
168168
let hir_id = self.tcx().hir().local_def_id_to_hir_id(anon_reg.def_id);
169-
if let hir::Node::Item(&hir::Item {
170-
kind: hir::ItemKind::Fn(_, ref generics, ..),
171-
..
172-
}) = self.tcx().hir().get(hir_id)
173-
{
174-
let (suggestion_param_name, introduce_new) = generics
175-
.params
176-
.iter()
177-
.find(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
178-
.and_then(|p| self.tcx().sess.source_map().span_to_snippet(p.span).ok())
179-
.map(|name| (name, false))
180-
.unwrap_or_else(|| ("'a".to_string(), true));
181-
182-
let mut suggestions = vec![
183-
if let hir::LifetimeName::Underscore = lifetime_sub.name {
184-
(lifetime_sub.span, suggestion_param_name.clone())
185-
} else {
186-
(
187-
lifetime_sub.span.shrink_to_hi(),
188-
suggestion_param_name.clone() + " ",
189-
)
190-
},
191-
if let hir::LifetimeName::Underscore = lifetime_sup.name {
192-
(lifetime_sup.span, suggestion_param_name.clone())
193-
} else {
194-
(
195-
lifetime_sup.span.shrink_to_hi(),
196-
suggestion_param_name.clone() + " ",
197-
)
198-
},
199-
];
200-
201-
if introduce_new {
202-
let new_param_suggestion = match &generics.params {
203-
[] => (generics.span, format!("<{}>", suggestion_param_name)),
204-
[first, ..] => (
205-
first.span.shrink_to_lo(),
206-
format!("{}, ", suggestion_param_name),
207-
),
208-
};
209-
210-
suggestions.push(new_param_suggestion);
211-
}
212-
213-
err.multipart_suggestion(
214-
"consider introducing a named lifetime parameter",
215-
suggestions,
216-
Applicability::MaybeIncorrect,
217-
);
218-
err.note(
219-
"each elided lifetime in input position becomes a distinct lifetime",
220-
);
169+
170+
let node = self.tcx().hir().get(hir_id);
171+
let is_impl = matches!(&node, hir::Node::ImplItem(_));
172+
let generics = match node {
173+
hir::Node::Item(&hir::Item {
174+
kind: hir::ItemKind::Fn(_, ref generics, ..),
175+
..
176+
})
177+
| hir::Node::TraitItem(&hir::TraitItem { ref generics, .. })
178+
| hir::Node::ImplItem(&hir::ImplItem { ref generics, .. }) => generics,
179+
_ => return,
180+
};
181+
182+
let (suggestion_param_name, introduce_new) = generics
183+
.params
184+
.iter()
185+
.find(|p| matches!(p.kind, GenericParamKind::Lifetime { .. }))
186+
.and_then(|p| self.tcx().sess.source_map().span_to_snippet(p.span).ok())
187+
.map(|name| (name, false))
188+
.unwrap_or_else(|| ("'a".to_string(), true));
189+
190+
let mut suggestions = vec![
191+
if let hir::LifetimeName::Underscore = lifetime_sub.name {
192+
(lifetime_sub.span, suggestion_param_name.clone())
193+
} else {
194+
(lifetime_sub.span.shrink_to_hi(), suggestion_param_name.clone() + " ")
195+
},
196+
if let hir::LifetimeName::Underscore = lifetime_sup.name {
197+
(lifetime_sup.span, suggestion_param_name.clone())
198+
} else {
199+
(lifetime_sup.span.shrink_to_hi(), suggestion_param_name.clone() + " ")
200+
},
201+
];
202+
203+
if introduce_new {
204+
let new_param_suggestion = match &generics.params {
205+
[] => (generics.span, format!("<{}>", suggestion_param_name)),
206+
[first, ..] => {
207+
(first.span.shrink_to_lo(), format!("{}, ", suggestion_param_name))
208+
}
209+
};
210+
211+
suggestions.push(new_param_suggestion);
212+
}
213+
214+
let mut sugg = String::from("consider introducing a named lifetime parameter");
215+
if is_impl {
216+
sugg.push_str(" and update trait if needed");
221217
}
218+
err.multipart_suggestion(
219+
sugg.as_str(),
220+
suggestions,
221+
Applicability::MaybeIncorrect,
222+
);
223+
err.note("each elided lifetime in input position becomes a distinct lifetime");
222224
}
223225
}
224226
}

src/test/ui/issues/issue-17728.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ LL | fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&R
88
...
99
LL | Some(entry) => Ok(entry),
1010
| ^^^^^^^^^ ...but data from `room` is returned here
11+
|
12+
= note: each elided lifetime in input position becomes a distinct lifetime
13+
help: consider introducing a named lifetime parameter
14+
|
15+
LL | fn attemptTraverse<'a>(&'a self, room: &'a Room, directionStr: &str) -> Result<&Room, &str> {
16+
| ++++ ++ ++
1117

1218
error[E0308]: `match` arms have incompatible types
1319
--> $DIR/issue-17728.rs:109:14

src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ LL | fn foo<'a>(&self, x: &i32) -> &i32 {
77
| this parameter and the return type are declared with different lifetimes...
88
LL | x
99
| ^ ...but data from `x` is returned here
10+
|
11+
= note: each elided lifetime in input position becomes a distinct lifetime
12+
help: consider introducing a named lifetime parameter and update trait if needed
13+
|
14+
LL | fn foo<'a>(&'a self, x: &'a i32) -> &i32 {
15+
| ++ ++
1016

1117
error: aborting due to previous error
1218

src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ LL | fn foo<'a>(&self, x: &Foo) -> &Foo {
77
| this parameter and the return type are declared with different lifetimes...
88
LL | if true { x } else { self }
99
| ^ ...but data from `x` is returned here
10+
|
11+
= note: each elided lifetime in input position becomes a distinct lifetime
12+
help: consider introducing a named lifetime parameter and update trait if needed
13+
|
14+
LL | fn foo<'a>(&'a self, x: &'a Foo) -> &Foo {
15+
| ++ ++
1016

1117
error: aborting due to previous error
1218

src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ LL | fn foo(x: &mut Vec<&u8>, y: &u8) {
55
| --- --- these two types are declared with different lifetimes...
66
LL | x.push(y);
77
| ^ ...but data from `y` flows into `x` here
8+
|
9+
= note: each elided lifetime in input position becomes a distinct lifetime
10+
help: consider introducing a named lifetime parameter and update trait if needed
11+
|
12+
LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) {
13+
| ++++ ++ ++
814

915
error: aborting due to previous error
1016

src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.stderr

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ LL | fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f }
55
| ---- ---- ^ ...but data from `f` is returned here
66
| |
77
| this parameter and the return type are declared with different lifetimes...
8+
|
9+
= note: each elided lifetime in input position becomes a distinct lifetime
10+
help: consider introducing a named lifetime parameter and update trait if needed
11+
|
12+
LL | fn a<'a>(self: Pin<&'a Foo>, f: &'a Foo) -> &Foo { f }
13+
| ++++ ++ ++
814

915
error[E0623]: lifetime mismatch
1016
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:76
@@ -13,6 +19,12 @@ LL | fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self,
1319
| ---- ----------------- ^ ...but data from `f` is returned here
1420
| |
1521
| this parameter and the return type are declared with different lifetimes...
22+
|
23+
= note: each elided lifetime in input position becomes a distinct lifetime
24+
help: consider introducing a named lifetime parameter and update trait if needed
25+
|
26+
LL | fn c<'a>(self: Pin<&'a Self>, f: &'a Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) }
27+
| ++++ ++ ++
1628

1729
error[E0623]: lifetime mismatch
1830
--> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:13:58

src/test/ui/self/elision/lt-ref-self.stderr

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ LL | fn ref_self(&self, f: &u32) -> &u32 {
77
| this parameter and the return type are declared with different lifetimes...
88
LL | f
99
| ^ ...but data from `f` is returned here
10+
|
11+
= note: each elided lifetime in input position becomes a distinct lifetime
12+
help: consider introducing a named lifetime parameter and update trait if needed
13+
|
14+
LL | fn ref_self<'a>(&'a self, f: &'a u32) -> &u32 {
15+
| ++++ ++ ++
1016

1117
error[E0623]: lifetime mismatch
1218
--> $DIR/lt-ref-self.rs:17:9
@@ -17,6 +23,12 @@ LL | fn ref_Self(self: &Self, f: &u32) -> &u32 {
1723
| this parameter and the return type are declared with different lifetimes...
1824
LL | f
1925
| ^ ...but data from `f` is returned here
26+
|
27+
= note: each elided lifetime in input position becomes a distinct lifetime
28+
help: consider introducing a named lifetime parameter and update trait if needed
29+
|
30+
LL | fn ref_Self<'a>(self: &'a Self, f: &'a u32) -> &u32 {
31+
| ++++ ++ ++
2032

2133
error[E0623]: lifetime mismatch
2234
--> $DIR/lt-ref-self.rs:21:9
@@ -27,6 +39,12 @@ LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 {
2739
| this parameter and the return type are declared with different lifetimes...
2840
LL | f
2941
| ^ ...but data from `f` is returned here
42+
|
43+
= note: each elided lifetime in input position becomes a distinct lifetime
44+
help: consider introducing a named lifetime parameter and update trait if needed
45+
|
46+
LL | fn box_ref_Self<'a>(self: Box<&'a Self>, f: &'a u32) -> &u32 {
47+
| ++++ ++ ++
3048

3149
error[E0623]: lifetime mismatch
3250
--> $DIR/lt-ref-self.rs:25:9
@@ -37,6 +55,12 @@ LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 {
3755
| this parameter and the return type are declared with different lifetimes...
3856
LL | f
3957
| ^ ...but data from `f` is returned here
58+
|
59+
= note: each elided lifetime in input position becomes a distinct lifetime
60+
help: consider introducing a named lifetime parameter and update trait if needed
61+
|
62+
LL | fn pin_ref_Self<'a>(self: Pin<&'a Self>, f: &'a u32) -> &u32 {
63+
| ++++ ++ ++
4064

4165
error[E0623]: lifetime mismatch
4266
--> $DIR/lt-ref-self.rs:29:9
@@ -47,6 +71,12 @@ LL | fn box_box_ref_Self(self: Box<Box<&Self>>, f: &u32) -> &u32 {
4771
| this parameter and the return type are declared with different lifetimes...
4872
LL | f
4973
| ^ ...but data from `f` is returned here
74+
|
75+
= note: each elided lifetime in input position becomes a distinct lifetime
76+
help: consider introducing a named lifetime parameter and update trait if needed
77+
|
78+
LL | fn box_box_ref_Self<'a>(self: Box<Box<&'a Self>>, f: &'a u32) -> &u32 {
79+
| ++++ ++ ++
5080

5181
error[E0623]: lifetime mismatch
5282
--> $DIR/lt-ref-self.rs:33:9
@@ -57,6 +87,12 @@ LL | fn box_pin_Self(self: Box<Pin<&Self>>, f: &u32) -> &u32 {
5787
| this parameter and the return type are declared with different lifetimes...
5888
LL | f
5989
| ^ ...but data from `f` is returned here
90+
|
91+
= note: each elided lifetime in input position becomes a distinct lifetime
92+
help: consider introducing a named lifetime parameter and update trait if needed
93+
|
94+
LL | fn box_pin_Self<'a>(self: Box<Pin<&'a Self>>, f: &'a u32) -> &u32 {
95+
| ++++ ++ ++
6096

6197
error: aborting due to 6 previous errors
6298

src/test/ui/self/elision/ref-mut-self.stderr

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ LL | fn ref_self(&mut self, f: &u32) -> &u32 {
77
| this parameter and the return type are declared with different lifetimes...
88
LL | f
99
| ^ ...but data from `f` is returned here
10+
|
11+
= note: each elided lifetime in input position becomes a distinct lifetime
12+
help: consider introducing a named lifetime parameter and update trait if needed
13+
|
14+
LL | fn ref_self<'a>(&'a mut self, f: &'a u32) -> &u32 {
15+
| ++++ ++ ++
1016

1117
error[E0623]: lifetime mismatch
1218
--> $DIR/ref-mut-self.rs:17:9
@@ -17,6 +23,12 @@ LL | fn ref_Self(self: &mut Self, f: &u32) -> &u32 {
1723
| this parameter and the return type are declared with different lifetimes...
1824
LL | f
1925
| ^ ...but data from `f` is returned here
26+
|
27+
= note: each elided lifetime in input position becomes a distinct lifetime
28+
help: consider introducing a named lifetime parameter and update trait if needed
29+
|
30+
LL | fn ref_Self<'a>(self: &'a mut Self, f: &'a u32) -> &u32 {
31+
| ++++ ++ ++
2032

2133
error[E0623]: lifetime mismatch
2234
--> $DIR/ref-mut-self.rs:21:9
@@ -27,6 +39,12 @@ LL | fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 {
2739
| this parameter and the return type are declared with different lifetimes...
2840
LL | f
2941
| ^ ...but data from `f` is returned here
42+
|
43+
= note: each elided lifetime in input position becomes a distinct lifetime
44+
help: consider introducing a named lifetime parameter and update trait if needed
45+
|
46+
LL | fn box_ref_Self<'a>(self: Box<&'a mut Self>, f: &'a u32) -> &u32 {
47+
| ++++ ++ ++
3048

3149
error[E0623]: lifetime mismatch
3250
--> $DIR/ref-mut-self.rs:25:9
@@ -37,6 +55,12 @@ LL | fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 {
3755
| this parameter and the return type are declared with different lifetimes...
3856
LL | f
3957
| ^ ...but data from `f` is returned here
58+
|
59+
= note: each elided lifetime in input position becomes a distinct lifetime
60+
help: consider introducing a named lifetime parameter and update trait if needed
61+
|
62+
LL | fn pin_ref_Self<'a>(self: Pin<&'a mut Self>, f: &'a u32) -> &u32 {
63+
| ++++ ++ ++
4064

4165
error[E0623]: lifetime mismatch
4266
--> $DIR/ref-mut-self.rs:29:9
@@ -47,6 +71,12 @@ LL | fn box_box_ref_Self(self: Box<Box<&mut Self>>, f: &u32) -> &u32 {
4771
| this parameter and the return type are declared with different lifetimes...
4872
LL | f
4973
| ^ ...but data from `f` is returned here
74+
|
75+
= note: each elided lifetime in input position becomes a distinct lifetime
76+
help: consider introducing a named lifetime parameter and update trait if needed
77+
|
78+
LL | fn box_box_ref_Self<'a>(self: Box<Box<&'a mut Self>>, f: &'a u32) -> &u32 {
79+
| ++++ ++ ++
5080

5181
error[E0623]: lifetime mismatch
5282
--> $DIR/ref-mut-self.rs:33:9
@@ -57,6 +87,12 @@ LL | fn box_pin_ref_Self(self: Box<Pin<&mut Self>>, f: &u32) -> &u32 {
5787
| this parameter and the return type are declared with different lifetimes...
5888
LL | f
5989
| ^ ...but data from `f` is returned here
90+
|
91+
= note: each elided lifetime in input position becomes a distinct lifetime
92+
help: consider introducing a named lifetime parameter and update trait if needed
93+
|
94+
LL | fn box_pin_ref_Self<'a>(self: Box<Pin<&'a mut Self>>, f: &'a u32) -> &u32 {
95+
| ++++ ++ ++
6096

6197
error: aborting due to 6 previous errors
6298

0 commit comments

Comments
 (0)