Skip to content

Commit aef9eb5

Browse files
authored
Rollup merge of #96352 - marmeladema:fix-nll-lifetime-bound-suggestions, r=jackh726
Improve span for `consider adding an explicit lifetime bound` suggestions under NLL Because NLL borrowck is run after typeck, `in_progress_typeck_results` was always `None` which was preventing the retrieval of the span to which the suggestion is suppose to add the lifetime bound. We now manually pass the `LocalDefId` owner to `construct_generic_bound_failure` so that under NLL, we give the owner id of the current body. This helps with #96332
2 parents 7daa1c9 + 8d561d2 commit aef9eb5

32 files changed

+231
-143
lines changed

compiler/rustc_borrowck/src/diagnostics/region_errors.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed
44
use rustc_infer::infer::{
55
error_reporting::nice_region_error::NiceRegionError,
66
error_reporting::unexpected_hidden_region_diagnostic, NllRegionVariableOrigin,
7+
RelateParamBound,
78
};
89
use rustc_middle::hir::place::PlaceBase;
910
use rustc_middle::mir::{ConstraintCategory, ReturnConstraint};
@@ -166,11 +167,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
166167
let type_test_span = type_test.locations.span(&self.body);
167168

168169
if let Some(lower_bound_region) = lower_bound_region {
170+
let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
171+
let origin = RelateParamBound(type_test_span, generic_ty, None);
169172
self.buffer_error(self.infcx.construct_generic_bound_failure(
170173
type_test_span,
171-
None,
174+
Some(origin),
172175
type_test.generic_kind,
173176
lower_bound_region,
177+
self.body.source.def_id().as_local(),
174178
));
175179
} else {
176180
// FIXME. We should handle this case better. It

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

+25-28
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6161
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed};
6262
use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan};
6363
use rustc_hir as hir;
64-
use rustc_hir::def_id::DefId;
64+
use rustc_hir::def_id::{DefId, LocalDefId};
6565
use rustc_hir::lang_items::LangItem;
6666
use rustc_hir::{Item, ItemKind, Node};
6767
use rustc_middle::dep_graph::DepContext;
@@ -2285,7 +2285,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
22852285
bound_kind: GenericKind<'tcx>,
22862286
sub: Region<'tcx>,
22872287
) {
2288-
self.construct_generic_bound_failure(span, origin, bound_kind, sub).emit();
2288+
let owner =
2289+
self.in_progress_typeck_results.map(|typeck_results| typeck_results.borrow().hir_owner);
2290+
self.construct_generic_bound_failure(span, origin, bound_kind, sub, owner).emit();
22892291
}
22902292

22912293
pub fn construct_generic_bound_failure(
@@ -2294,31 +2296,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
22942296
origin: Option<SubregionOrigin<'tcx>>,
22952297
bound_kind: GenericKind<'tcx>,
22962298
sub: Region<'tcx>,
2299+
owner: Option<LocalDefId>,
22972300
) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
22982301
let hir = self.tcx.hir();
22992302
// Attempt to obtain the span of the parameter so we can
23002303
// suggest adding an explicit lifetime bound to it.
2301-
let generics = self
2302-
.in_progress_typeck_results
2303-
.map(|typeck_results| typeck_results.borrow().hir_owner)
2304-
.map(|owner| {
2305-
let hir_id = hir.local_def_id_to_hir_id(owner);
2306-
let parent_id = hir.get_parent_item(hir_id);
2307-
(
2308-
// Parent item could be a `mod`, so we check the HIR before calling:
2309-
if let Some(Node::Item(Item {
2310-
kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
2311-
..
2312-
})) = hir.find_by_def_id(parent_id)
2313-
{
2314-
Some(self.tcx.generics_of(parent_id))
2315-
} else {
2316-
None
2317-
},
2318-
self.tcx.generics_of(owner.to_def_id()),
2319-
hir.span(hir_id),
2320-
)
2321-
});
2304+
let generics = owner.map(|owner| {
2305+
let hir_id = hir.local_def_id_to_hir_id(owner);
2306+
let parent_id = hir.get_parent_item(hir_id);
2307+
(
2308+
// Parent item could be a `mod`, so we check the HIR before calling:
2309+
if let Some(Node::Item(Item {
2310+
kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
2311+
..
2312+
})) = hir.find_by_def_id(parent_id)
2313+
{
2314+
Some(self.tcx.generics_of(parent_id))
2315+
} else {
2316+
None
2317+
},
2318+
self.tcx.generics_of(owner.to_def_id()),
2319+
hir.span(hir_id),
2320+
)
2321+
});
23222322

23232323
let span = match generics {
23242324
// This is to get around the trait identity obligation, that has a `DUMMY_SP` as signal
@@ -2606,11 +2606,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
26062606
None,
26072607
);
26082608
if let Some(infer::RelateParamBound(_, t, _)) = origin {
2609-
let return_impl_trait = self
2610-
.in_progress_typeck_results
2611-
.map(|typeck_results| typeck_results.borrow().hir_owner)
2612-
.and_then(|owner| self.tcx.return_type_impl_trait(owner))
2613-
.is_some();
2609+
let return_impl_trait =
2610+
owner.and_then(|owner| self.tcx.return_type_impl_trait(owner)).is_some();
26142611
let t = self.resolve_vars_if_possible(t);
26152612
match t.kind() {
26162613
// We've got:

src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,11 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
8282
error[E0310]: the parameter type `T` may not live long enough
8383
--> $DIR/must_outlive_least_region_or_bound.rs:41:5
8484
|
85+
LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
86+
| -- help: consider adding an explicit lifetime bound...: `T: 'static +`
87+
...
8588
LL | x
86-
| ^
87-
|
88-
= help: consider adding an explicit lifetime bound `T: 'static`...
89+
| ^ ...so that the type `T` will meet its required lifetime bounds
8990

9091
error: aborting due to 9 previous errors
9192

src/test/ui/impl-trait/type_parameters_captured.nll.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
error[E0310]: the parameter type `T` may not live long enough
22
--> $DIR/type_parameters_captured.rs:10:5
33
|
4+
LL | fn foo<T>(x: T) -> impl Any + 'static {
5+
| - help: consider adding an explicit lifetime bound...: `T: 'static`
6+
...
47
LL | x
5-
| ^
6-
|
7-
= help: consider adding an explicit lifetime bound `T: 'static`...
8+
| ^ ...so that the type `T` will meet its required lifetime bounds
89

910
error: aborting due to previous error
1011

src/test/ui/lifetimes/lifetime-errors/issue_74400.nll.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
error[E0310]: the parameter type `T` may not live long enough
22
--> $DIR/issue_74400.rs:12:5
33
|
4+
LL | fn g<T>(data: &[T]) {
5+
| - help: consider adding an explicit lifetime bound...: `T: 'static`
46
LL | f(data, identity)
5-
| ^^^^^^^^^^^^^^^^^
6-
|
7-
= help: consider adding an explicit lifetime bound `T: 'static`...
7+
| ^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
88

99
error[E0308]: mismatched types
1010
--> $DIR/issue_74400.rs:12:5

src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ LL | | }
3636
error[E0309]: the parameter type `T` may not live long enough
3737
--> $DIR/propagate-from-trait-match.rs:32:36
3838
|
39+
LL | fn supply<'a, T>(value: T)
40+
| - help: consider adding an explicit lifetime bound...: `T: 'a`
41+
...
3942
LL | establish_relationships(value, |value| {
4043
| ____________________________________^
4144
LL | |
@@ -44,9 +47,7 @@ LL | | // This function call requires that
4447
... |
4548
LL | | require(value);
4649
LL | | });
47-
| |_____^
48-
|
49-
= help: consider adding an explicit lifetime bound `T: 'a`...
50+
| |_____^ ...so that the type `T` will meet its required lifetime bounds
5051

5152
error: aborting due to previous error
5253

src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
error[E0309]: the parameter type `T` may not live long enough
22
--> $DIR/impl-trait-outlives.rs:11:5
33
|
4+
LL | fn no_region<'a, T>(x: Box<T>) -> impl Debug + 'a
5+
| - help: consider adding an explicit lifetime bound...: `T: 'a`
6+
...
47
LL | x
5-
| ^
6-
|
7-
= help: consider adding an explicit lifetime bound `T: 'a`...
8+
| ^ ...so that the type `T` will meet its required lifetime bounds
89

910
error[E0309]: the parameter type `T` may not live long enough
1011
--> $DIR/impl-trait-outlives.rs:26:5
1112
|
13+
LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> impl Debug + 'a
14+
| - help: consider adding an explicit lifetime bound...: `T: 'a`
15+
...
1216
LL | x
13-
| ^
14-
|
15-
= help: consider adding an explicit lifetime bound `T: 'a`...
17+
| ^ ...so that the type `T` will meet its required lifetime bounds
1618

1719
error: aborting due to 2 previous errors
1820

src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
error[E0310]: the parameter type `T` may not live long enough
22
--> $DIR/projection-implied-bounds.rs:30:18
33
|
4+
LL | fn generic2<T: Iterator>(value: T) {
5+
| -- help: consider adding an explicit lifetime bound...: `T: 'static +`
46
LL | twice(value, |value_ref, item| invoke2(value_ref, item));
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6-
|
7-
= help: consider adding an explicit lifetime bound `T: 'static`...
7+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
88

99
error: aborting due to previous error
1010

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

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ LL | with_signature(x, |mut y| Box::new(y.next()))
3333
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
3434
|
3535
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
36+
= note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
3637

3738
note: external requirements
3839
--> $DIR/projection-no-regions-closure.rs:34:23
@@ -96,6 +97,7 @@ LL | with_signature(x, |mut y| Box::new(y.next()))
9697
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
9798
|
9899
= help: consider adding an explicit lifetime bound `<T as Iterator>::Item: 'a`...
100+
= note: ...so that the type `<T as Iterator>::Item` will meet its required lifetime bounds
99101

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

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

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ LL | Box::new(x.next())
55
| ^^^^^^^^^^^^^^^^^^
66
|
77
= 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
89

910
error[E0309]: the associated type `<T as Iterator>::Item` may not live long enough
1011
--> $DIR/projection-no-regions-fn.rs:28:5
@@ -13,6 +14,7 @@ LL | Box::new(x.next())
1314
| ^^^^^^^^^^^^^^^^^^
1415
|
1516
= 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
1618

1719
error: aborting due to 2 previous errors
1820

src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr

+8-6
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ LL | | }
3131
error[E0309]: the parameter type `T` may not live long enough
3232
--> $DIR/projection-one-region-closure.rs:45:29
3333
|
34+
LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
35+
| - help: consider adding an explicit lifetime bound...: `T: 'a`
36+
...
3437
LL | with_signature(cell, t, |cell, t| require(cell, t));
35-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
36-
|
37-
= help: consider adding an explicit lifetime bound `T: 'a`...
38+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
3839

3940
error: lifetime may not live long enough
4041
--> $DIR/projection-one-region-closure.rs:45:39
@@ -81,10 +82,11 @@ LL | | }
8182
error[E0309]: the parameter type `T` may not live long enough
8283
--> $DIR/projection-one-region-closure.rs:56:29
8384
|
85+
LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
86+
| - help: consider adding an explicit lifetime bound...: `T: 'a`
87+
...
8488
LL | with_signature(cell, t, |cell, t| require(cell, t));
85-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
86-
|
87-
= help: consider adding an explicit lifetime bound `T: 'a`...
89+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
8890

8991
error: lifetime may not live long enough
9092
--> $DIR/projection-one-region-closure.rs:56:39

src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
3434
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
3535
|
3636
= help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType: 'a`...
37+
= note: ...so that the type `<T as Anything<ReEarlyBound(0, 'b), ReEarlyBound(1, 'c)>>::AssocType` will meet its required lifetime bounds
3738

3839
note: external requirements
3940
--> $DIR/projection-two-region-trait-bound-closure.rs:48:29
@@ -70,6 +71,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t));
7071
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
7172
|
7273
= help: consider adding an explicit lifetime bound `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType: 'a`...
74+
= note: ...so that the type `<T as Anything<ReEarlyBound(1, 'b), ReEarlyBound(2, 'c)>>::AssocType` will meet its required lifetime bounds
7375

7476
note: external requirements
7577
--> $DIR/projection-two-region-trait-bound-closure.rs:61:29

src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.nll.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ LL | bar::<T::Output>()
55
| ^^^^^^^^^^^^^^^^
66
|
77
= help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
8+
= note: ...so that the type `<T as MyTrait<'_>>::Output` will meet its required lifetime bounds
89

910
error: aborting due to previous error
1011

src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.nll.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ LL | bar::<<T as MyTrait<'a>>::Output>()
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= help: consider adding an explicit lifetime bound `<T as MyTrait<'_>>::Output: 'a`...
8+
= note: ...so that the type `<T as MyTrait<'_>>::Output` will meet its required lifetime bounds
89

910
error: aborting due to previous error
1011

src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
error[E0309]: the parameter type `T` may not live long enough
22
--> $DIR/projection-where-clause-none.rs:16:5
33
|
4+
LL | fn foo<'a, T>() -> &'a ()
5+
| - help: consider adding an explicit lifetime bound...: `T: 'a`
6+
...
47
LL | bar::<T::Output>()
5-
| ^^^^^^^^^^^^^^^^
6-
|
7-
= help: consider adding an explicit lifetime bound `T: 'a`...
8+
| ^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
89

910
error: aborting due to previous error
1011

src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ LL | | }
5252
error[E0309]: the parameter type `T` may not live long enough
5353
--> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24
5454
|
55+
LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) {
56+
| - help: consider adding an explicit lifetime bound...: `T: 'a`
5557
LL | twice(cell, value, |a, b| invoke(a, b));
56-
| ^^^^^^^^^^^^^^^^^^^
57-
|
58-
= help: consider adding an explicit lifetime bound `T: 'a`...
58+
| ^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
5959

6060
error: aborting due to previous error
6161

src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr

+8-6
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,20 @@ LL | | }
2929
error[E0309]: the parameter type `T` may not live long enough
3030
--> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23
3131
|
32+
LL | fn no_region<'a, T>(x: Box<T>) -> Box<dyn Debug + 'a>
33+
| - help: consider adding an explicit lifetime bound...: `T: 'a`
34+
...
3235
LL | with_signature(x, |y| y)
33-
| ^^^^^
34-
|
35-
= help: consider adding an explicit lifetime bound `T: 'a`...
36+
| ^^^^^ ...so that the type `T` will meet its required lifetime bounds
3637

3738
error[E0309]: the parameter type `T` may not live long enough
3839
--> $DIR/ty-param-closure-outlives-from-return-type.rs:41:5
3940
|
41+
LL | fn wrong_region<'a, 'b, T>(x: Box<T>) -> Box<Debug + 'a>
42+
| - help: consider adding an explicit lifetime bound...: `T: 'a`
43+
...
4044
LL | x
41-
| ^
42-
|
43-
= help: consider adding an explicit lifetime bound `T: 'a`...
45+
| ^ ...so that the type `T` will meet its required lifetime bounds
4446

4547
error: aborting due to 2 previous errors
4648

0 commit comments

Comments
 (0)