Skip to content

Commit ee7e3a8

Browse files
committed
improve the suggestion of generic_bound_failure
1 parent 1e746d7 commit ee7e3a8

28 files changed

+696
-384
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+201-299
Large diffs are not rendered by default.

compiler/rustc_middle/src/ty/context.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -1052,24 +1052,29 @@ impl<'tcx> TyCtxt<'tcx> {
10521052
}
10531053

10541054
/// Returns the `DefId` and the `BoundRegionKind` corresponding to the given region.
1055-
pub fn is_suitable_region(self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
1056-
let (suitable_region_binding_scope, bound_region) = match *region {
1057-
ty::ReFree(ref free_region) => {
1058-
(free_region.scope.expect_local(), free_region.bound_region)
1055+
pub fn is_suitable_region(self, mut region: Region<'tcx>) -> Option<FreeRegionInfo> {
1056+
let (suitable_region_binding_scope, bound_region) = loop {
1057+
let def_id = match region.kind() {
1058+
ty::ReFree(fr) => fr.bound_region.get_id()?.as_local()?,
1059+
ty::ReEarlyBound(ebr) => ebr.def_id.expect_local(),
1060+
_ => return None, // not a free region
1061+
};
1062+
let scope = self.local_parent(def_id);
1063+
if self.def_kind(scope) == DefKind::OpaqueTy {
1064+
// Lifetime params of opaque types are synthetic and thus irrelevant to
1065+
// diagnostics. Map them back to their origin!
1066+
region = self.map_rpit_lifetime_to_fn_lifetime(def_id);
1067+
continue;
10591068
}
1060-
ty::ReEarlyBound(ref ebr) => (
1061-
self.local_parent(ebr.def_id.expect_local()),
1062-
ty::BoundRegionKind::BrNamed(ebr.def_id, ebr.name),
1063-
),
1064-
_ => return None, // not a free region
1069+
break (scope, ty::BrNamed(def_id.into(), self.item_name(def_id.into())));
10651070
};
10661071

10671072
let is_impl_item = match self.hir().find_by_def_id(suitable_region_binding_scope) {
10681073
Some(Node::Item(..) | Node::TraitItem(..)) => false,
10691074
Some(Node::ImplItem(..)) => {
10701075
self.is_bound_region_in_impl_item(suitable_region_binding_scope)
10711076
}
1072-
_ => return None,
1077+
_ => false,
10731078
};
10741079

10751080
Some(FreeRegionInfo {

tests/ui/associated-inherent-types/regionck-1.stderr

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ error[E0309]: the parameter type `T` may not live long enough
22
--> $DIR/regionck-1.rs:9:30
33
|
44
LL | type NoTyOutliv<'a, T> = &'a T;
5-
| ^^^^^- help: consider adding a where clause: `where T: 'a`
6-
| |
7-
| ...so that the reference type `&'a T` does not outlive the data it points at
5+
| ^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
6+
|
7+
help: consider adding an explicit lifetime bound...
8+
|
9+
LL | type NoTyOutliv<'a, T: 'a> = &'a T;
10+
| ++++
811

912
error[E0491]: in type `&'a &'b ()`, reference has a longer lifetime than the data it references
1013
--> $DIR/regionck-1.rs:10:31

tests/ui/async-await/in-trait/async-generics-and-bounds.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ note: ...so that the reference type `&(T, U)` does not outlive the data it point
1414
|
1515
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
1616
| ^^^^^^^
17+
help: consider adding an explicit lifetime bound...
18+
|
19+
LL | async fn foo<'a>(&'a self) -> &'a (T, U) where T: Debug + Sized, U: Hash, U: 'a;
20+
| ++++ ++ ++ +++++++
1721

1822
error[E0311]: the parameter type `T` may not live long enough
1923
--> $DIR/async-generics-and-bounds.rs:12:28
@@ -31,6 +35,10 @@ note: ...so that the reference type `&(T, U)` does not outlive the data it point
3135
|
3236
LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
3337
| ^^^^^^^
38+
help: consider adding an explicit lifetime bound...
39+
|
40+
LL | async fn foo<'a>(&'a self) -> &'a (T, U) where T: Debug + Sized, U: Hash, T: 'a;
41+
| ++++ ++ ++ +++++++
3442

3543
error: aborting due to 2 previous errors
3644

tests/ui/async-await/in-trait/async-generics.stderr

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ note: ...so that the reference type `&(T, U)` does not outlive the data it point
1414
|
1515
LL | async fn foo(&self) -> &(T, U);
1616
| ^^^^^^^
17+
help: consider adding an explicit lifetime bound...
18+
|
19+
LL | async fn foo<'a>(&'a self) -> &'a (T, U) where U: 'a;
20+
| ++++ ++ ++ +++++++++++
1721

1822
error[E0311]: the parameter type `T` may not live long enough
1923
--> $DIR/async-generics.rs:9:28
@@ -31,6 +35,10 @@ note: ...so that the reference type `&(T, U)` does not outlive the data it point
3135
|
3236
LL | async fn foo(&self) -> &(T, U);
3337
| ^^^^^^^
38+
help: consider adding an explicit lifetime bound...
39+
|
40+
LL | async fn foo<'a>(&'a self) -> &'a (T, U) where T: 'a;
41+
| ++++ ++ ++ +++++++++++
3442

3543
error: aborting due to 2 previous errors
3644

tests/ui/error-codes/E0311.fixed

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#![allow(warnings)]
44

5-
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() {
5+
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
66
with_restriction::<T>(x) //~ ERROR E0311
77
}
88

tests/ui/error-codes/E0311.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ LL | with_restriction::<T>(x)
1616
| ^^^^^^^^^^^^^^^^^^^^^
1717
help: consider adding an explicit lifetime bound...
1818
|
19-
LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() {
20-
| +++ ++++ ++
19+
LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
20+
| +++ ++++ ++ ++
2121

2222
error: aborting due to previous error
2323

tests/ui/generic-associated-types/issue-84931.stderr

+6-3
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ error[E0309]: the parameter type `T` may not live long enough
22
--> $DIR/issue-84931.rs:14:21
33
|
44
LL | type Item<'a> = &'a mut T;
5-
| ^^^^^^^^^- help: consider adding a where clause: `where T: 'a`
6-
| |
7-
| ...so that the reference type `&'a mut T` does not outlive the data it points at
5+
| ^^^^^^^^^ ...so that the reference type `&'a mut T` does not outlive the data it points at
6+
|
7+
help: consider adding an explicit lifetime bound...
8+
|
9+
LL | type Item<'a> = &'a mut T where T: 'a;
10+
| +++++++++++
811

912
error: aborting due to previous error
1013

tests/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr

+9-7
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ LL | fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
1717
|
1818
help: consider adding an explicit lifetime bound...
1919
|
20-
LL | impl<K: 'a> Nested<K> {
21-
| ++++
20+
LL | fn generic_in_parent<'a, L: X<&'a Nested<K>>>() where K: 'a {
21+
| +++++++++++
2222

2323
error[E0309]: the parameter type `M` may not live long enough
2424
--> $DIR/lifetime-doesnt-live-long-enough.rs:44:36
@@ -39,17 +39,19 @@ LL | fn foo<'a, L: X<&'a Nested<K>>>();
3939
|
4040
help: consider adding an explicit lifetime bound...
4141
|
42-
LL | trait X<K: 'a>: Sized {
43-
| ++++
42+
LL | fn foo<'a, L: X<&'a Nested<K>>>() where K: 'a;
43+
| +++++++++++
4444

4545
error[E0309]: the parameter type `Self` may not live long enough
4646
--> $DIR/lifetime-doesnt-live-long-enough.rs:28:19
4747
|
4848
LL | fn bar<'a, L: X<&'a Nested<Self>>>();
49-
| ^^^^^^^^^^^^^^^^^^^
49+
| ^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<Self>` does not outlive the data it points at
5050
|
51-
= help: consider adding an explicit lifetime bound `Self: 'a`...
52-
= note: ...so that the reference type `&'a Nested<Self>` does not outlive the data it points at
51+
help: consider adding an explicit lifetime bound...
52+
|
53+
LL | fn bar<'a, L: X<&'a Nested<Self>>>() where Self: 'a;
54+
| ++++++++++++++
5355

5456
error[E0309]: the parameter type `L` may not live long enough
5557
--> $DIR/lifetime-doesnt-live-long-enough.rs:32:22

tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.fixed

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#![allow(warnings)]
44

5-
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() {
5+
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
66
with_restriction::<T>(x) //~ ERROR the parameter type `T` may not live long enough
77
}
88

tests/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ LL | with_restriction::<T>(x)
1616
| ^^^^^^^^^^^^^^^^^^^^^
1717
help: consider adding an explicit lifetime bound...
1818
|
19-
LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &() {
20-
| +++ ++++ ++
19+
LL | fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
20+
| +++ ++++ ++ ++
2121

2222
error: aborting due to previous error
2323

tests/ui/nll/ty-outlives/projection-no-regions-closure.stderr

+10-6
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@ error[E0309]: the associated type `<T as Iterator>::Item` may not live long enou
2626
--> $DIR/projection-no-regions-closure.rs:25:31
2727
|
2828
LL | with_signature(x, |mut y| Box::new(y.next()))
29-
| ^^^^^^^^^^^^^^^^^^
29+
| ^^^^^^^^^^^^^^^^^^ ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
3030
|
31-
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
32-
= note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
31+
help: consider adding an explicit lifetime bound...
32+
|
33+
LL | T: Iterator, <T as Iterator>::Item: 'a
34+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
3335

3436
note: external requirements
3537
--> $DIR/projection-no-regions-closure.rs:34:23
@@ -83,10 +85,12 @@ error[E0309]: the associated type `<T as Iterator>::Item` may not live long enou
8385
--> $DIR/projection-no-regions-closure.rs:42:31
8486
|
8587
LL | with_signature(x, |mut y| Box::new(y.next()))
86-
| ^^^^^^^^^^^^^^^^^^
88+
| ^^^^^^^^^^^^^^^^^^ ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
89+
|
90+
help: consider adding an explicit lifetime bound...
8791
|
88-
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
89-
= note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
92+
LL | T: 'b + Iterator, <T as Iterator>::Item: 'a
93+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
9094

9195
note: external requirements
9296
--> $DIR/projection-no-regions-closure.rs:52:23

tests/ui/nll/ty-outlives/projection-no-regions-fn.stderr

+10-6
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,23 @@ error[E0309]: the associated type `<T as Iterator>::Item` may not live long enou
22
--> $DIR/projection-no-regions-fn.rs:13:5
33
|
44
LL | Box::new(x.next())
5-
| ^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^ ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
66
|
7-
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
8-
= note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
7+
help: consider adding an explicit lifetime bound...
8+
|
9+
LL | T: Iterator, <T as Iterator>::Item: 'a
10+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
911

1012
error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough
1113
--> $DIR/projection-no-regions-fn.rs:28:5
1214
|
1315
LL | Box::new(x.next())
14-
| ^^^^^^^^^^^^^^^^^^
16+
| ^^^^^^^^^^^^^^^^^^ ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
17+
|
18+
help: consider adding an explicit lifetime bound...
1519
|
16-
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
17-
= note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
20+
LL | T: 'b + Iterator, <T as Iterator>::Item: 'a
21+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1822

1923
error: aborting due to 2 previous errors
2024

tests/ui/regions/regions-close-associated-type-into-object.stderr

+20-12
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,45 @@ error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
22
--> $DIR/regions-close-associated-type-into-object.rs:15:5
33
|
44
LL | Box::new(item)
5-
| ^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^ ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
66
|
7-
= help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
8-
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
7+
help: consider adding an explicit lifetime bound...
8+
|
9+
LL | fn bad1<T: Iter>(v: T) -> Box<dyn X + 'static> where <T as Iter>::Item: 'static
10+
| ++++++++++++++++++++++++++++++++
911

1012
error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
1113
--> $DIR/regions-close-associated-type-into-object.rs:22:5
1214
|
1315
LL | Box::new(item)
14-
| ^^^^^^^^^^^^^^
16+
| ^^^^^^^^^^^^^^ ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
17+
|
18+
help: consider adding an explicit lifetime bound...
1519
|
16-
= help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
17-
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
20+
LL | where Box<T::Item> : X, <T as Iter>::Item: 'static
21+
| ++++++++++++++++++++++++++++
1822

1923
error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
2024
--> $DIR/regions-close-associated-type-into-object.rs:28:5
2125
|
2226
LL | Box::new(item)
23-
| ^^^^^^^^^^^^^^
27+
| ^^^^^^^^^^^^^^ ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
2428
|
25-
= help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
26-
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
29+
help: consider adding an explicit lifetime bound...
30+
|
31+
LL | fn bad3<'a, T: Iter>(v: T) -> Box<dyn X + 'a> where <T as Iter>::Item: 'a
32+
| +++++++++++++++++++++++++++
2733

2834
error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
2935
--> $DIR/regions-close-associated-type-into-object.rs:35:5
3036
|
3137
LL | Box::new(item)
32-
| ^^^^^^^^^^^^^^
38+
| ^^^^^^^^^^^^^^ ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
39+
|
40+
help: consider adding an explicit lifetime bound...
3341
|
34-
= help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
35-
= note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
42+
LL | where Box<T::Item> : X, <T as Iter>::Item: 'a
43+
| +++++++++++++++++++++++
3644

3745
error: aborting due to 4 previous errors
3846

tests/ui/regions/regions-infer-bound-from-trait-self.stderr

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ error[E0309]: the parameter type `Self` may not live long enough
22
--> $DIR/regions-infer-bound-from-trait-self.rs:46:9
33
|
44
LL | check_bound(x, self)
5-
| ^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^ ...so that the type `Self` will meet its required lifetime bounds
66
|
7-
= help: consider adding an explicit lifetime bound `Self: 'a`...
8-
= note: ...so that the type `Self` will meet its required lifetime bounds
7+
help: consider adding an explicit lifetime bound...
8+
|
9+
LL | trait InheritsFromNothing<'a> : Sized where Self: 'a {
10+
| ++++++++++++++
911

1012
error: aborting due to previous error
1113

tests/ui/suggestions/lifetimes/issue-105544.fixed

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#![allow(warnings)]
44

5-
fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized` must be valid for the anonymous lifetime defined here...
5+
fn foo<'a>(d: impl Sized + 'a, p: &'a mut ()) -> impl Sized + 'a { //~ NOTE the parameter type `impl Sized` must be valid for the anonymous lifetime defined here...
66
//~^ HELP consider adding an explicit lifetime bound
77
(d, p)
88
//~^ ERROR the parameter type `impl Sized` may not live long enough
@@ -15,14 +15,14 @@ fn foo1<'b>(d: impl Sized + 'b, p: &'b mut ()) -> impl Sized + '_ {
1515
//~^ ERROR the parameter type `impl Sized` may not live long enough
1616
}
1717

18-
fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here...
18+
fn foo2<'b, 'a>(d: impl Sized + 'a + 'b, p: &'b mut ()) -> impl Sized + 'b { //~ NOTE the parameter type `impl Sized + 'a` must be valid for the anonymous lifetime defined here...
1919
//~^ HELP consider adding an explicit lifetime bound
2020
(d, p)
2121
//~^ ERROR the parameter type `impl Sized + 'a` may not live long enough
2222
//~| NOTE ...so that the type `impl Sized + 'a` will meet its required lifetime bounds
2323
}
2424

25-
fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
25+
fn bar<'a, T : Sized + 'a>(d: T, p: &'a mut ()) -> impl Sized + 'a { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
2626
//~^ HELP consider adding an explicit lifetime bound
2727
(d, p)
2828
//~^ ERROR the parameter type `T` may not live long enough
@@ -35,7 +35,7 @@ fn bar1<'b, T : Sized + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ {
3535
//~^ ERROR the parameter type `T` may not live long enough
3636
}
3737

38-
fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + '_ { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
38+
fn bar2<'b, 'a, T : Sized + 'a + 'b>(d: T, p: &'b mut ()) -> impl Sized + 'b { //~ NOTE the parameter type `T` must be valid for the anonymous lifetime defined here...
3939
//~^ HELP consider adding an explicit lifetime bound
4040
(d, p)
4141
//~^ ERROR the parameter type `T` may not live long enough

0 commit comments

Comments
 (0)