From 7b0db3e7c81c36d2ec623849d17d9df4858abca1 Mon Sep 17 00:00:00 2001 From: marmeladema Date: Sun, 24 Apr 2022 00:17:33 +0200 Subject: [PATCH] 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. --- .../src/diagnostics/region_errors.rs | 1 + .../src/infer/error_reporting/mod.rs | 53 +++++++++---------- .../propagate-from-trait-match.stderr | 5 +- .../ty-outlives/impl-trait-outlives.stderr | 10 ++-- .../projection-implied-bounds.stderr | 4 +- .../projection-one-region-closure.stderr | 10 ++-- .../projection-where-clause-none.stderr | 5 +- ...ram-closure-approximate-lower-bound.stderr | 4 +- ...m-closure-outlives-from-return-type.stderr | 10 ++-- ...-closure-outlives-from-where-clause.stderr | 9 ++-- .../nll/ty-outlives/ty-param-fn-body.stderr | 4 +- .../ui/nll/ty-outlives/ty-param-fn.stderr | 10 ++-- ..._type_does_not_live_long_enough.nll.stderr | 4 +- 13 files changed, 69 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 5fd9ecf451366..be715505d8121 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -171,6 +171,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { None, type_test.generic_kind, lower_bound_region, + self.body.source.def_id().as_local(), )); } else { // FIXME. We should handle this case better. It diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index f2dd4f5d5cbca..f9273cc50b70a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -61,7 +61,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::{Item, ItemKind, Node}; use rustc_middle::dep_graph::DepContext; @@ -2285,7 +2285,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, ) { - self.construct_generic_bound_failure(span, origin, bound_kind, sub).emit(); + let owner = + self.in_progress_typeck_results.map(|typeck_results| typeck_results.borrow().hir_owner); + self.construct_generic_bound_failure(span, origin, bound_kind, sub, owner).emit(); } pub fn construct_generic_bound_failure( @@ -2294,31 +2296,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: Option>, bound_kind: GenericKind<'tcx>, sub: Region<'tcx>, + owner: Option, ) -> DiagnosticBuilder<'a, ErrorGuaranteed> { let hir = self.tcx.hir(); // Attempt to obtain the span of the parameter so we can // suggest adding an explicit lifetime bound to it. - let generics = self - .in_progress_typeck_results - .map(|typeck_results| typeck_results.borrow().hir_owner) - .map(|owner| { - let hir_id = hir.local_def_id_to_hir_id(owner); - let parent_id = hir.get_parent_item(hir_id); - ( - // Parent item could be a `mod`, so we check the HIR before calling: - if let Some(Node::Item(Item { - kind: ItemKind::Trait(..) | ItemKind::Impl { .. }, - .. - })) = hir.find_by_def_id(parent_id) - { - Some(self.tcx.generics_of(parent_id)) - } else { - None - }, - self.tcx.generics_of(owner.to_def_id()), - hir.span(hir_id), - ) - }); + let generics = owner.map(|owner| { + let hir_id = hir.local_def_id_to_hir_id(owner); + let parent_id = hir.get_parent_item(hir_id); + ( + // Parent item could be a `mod`, so we check the HIR before calling: + if let Some(Node::Item(Item { + kind: ItemKind::Trait(..) | ItemKind::Impl { .. }, + .. + })) = hir.find_by_def_id(parent_id) + { + Some(self.tcx.generics_of(parent_id)) + } else { + None + }, + self.tcx.generics_of(owner.to_def_id()), + hir.span(hir_id), + ) + }); let span = match generics { // 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> { None, ); if let Some(infer::RelateParamBound(_, t, _)) = origin { - let return_impl_trait = self - .in_progress_typeck_results - .map(|typeck_results| typeck_results.borrow().hir_owner) - .and_then(|owner| self.tcx.return_type_impl_trait(owner)) - .is_some(); + let return_impl_trait = + owner.and_then(|owner| self.tcx.return_type_impl_trait(owner)).is_some(); let t = self.resolve_vars_if_possible(t); match t.kind() { // We've got: diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr index 4b860a55057b6..5a382ded70b99 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -36,6 +36,9 @@ LL | | } error[E0309]: the parameter type `T` may not live long enough --> $DIR/propagate-from-trait-match.rs:32:36 | +LL | fn supply<'a, T>(value: T) + | - help: consider adding an explicit lifetime bound...: `T: 'a` +... LL | establish_relationships(value, |value| { | ____________________________________^ LL | | @@ -45,8 +48,6 @@ LL | | // This function call requires that LL | | require(value); LL | | }); | |_____^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr index 31ee540cce9f7..d303b8c84c1c0 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr @@ -1,18 +1,20 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/impl-trait-outlives.rs:11:5 | +LL | fn no_region<'a, T>(x: Box) -> impl Debug + 'a + | - help: consider adding an explicit lifetime bound...: `T: 'a` +... LL | x | ^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... error[E0309]: the parameter type `T` may not live long enough --> $DIR/impl-trait-outlives.rs:26:5 | +LL | fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a + | - help: consider adding an explicit lifetime bound...: `T: 'a` +... LL | x | ^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr index 9f0c60c1e1705..faa90e3e5646e 100644 --- a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr +++ b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr @@ -1,10 +1,10 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/projection-implied-bounds.rs:30:18 | +LL | fn generic2(value: T) { + | -- help: consider adding an explicit lifetime bound...: `T: 'static +` LL | twice(value, |value_ref, item| invoke2(value_ref, item)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: 'static`... error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index 2513b0bfccbf1..cec1c277e7f29 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -31,10 +31,11 @@ LL | | } error[E0309]: the parameter type `T` may not live long enough --> $DIR/projection-one-region-closure.rs:45:29 | +LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | - help: consider adding an explicit lifetime bound...: `T: 'a` +... LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... error: lifetime may not live long enough --> $DIR/projection-one-region-closure.rs:45:39 @@ -81,10 +82,11 @@ LL | | } error[E0309]: the parameter type `T` may not live long enough --> $DIR/projection-one-region-closure.rs:56:29 | +LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | - help: consider adding an explicit lifetime bound...: `T: 'a` +... LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... error: lifetime may not live long enough --> $DIR/projection-one-region-closure.rs:56:39 diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr index 8175c302155a5..ad2571e44f5f1 100644 --- a/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr +++ b/src/test/ui/nll/ty-outlives/projection-where-clause-none.stderr @@ -1,10 +1,11 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/projection-where-clause-none.rs:16:5 | +LL | fn foo<'a, T>() -> &'a () + | - help: consider adding an explicit lifetime bound...: `T: 'a` +... LL | bar::() | ^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index baf223b786b08..1f232f35043f6 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -52,10 +52,10 @@ LL | | } error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-approximate-lower-bound.rs:29:24 | +LL | fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) { + | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr index 88d73e7a729a9..7b1f8192cb621 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -29,18 +29,20 @@ LL | | } error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:23 | +LL | fn no_region<'a, T>(x: Box) -> Box + | - help: consider adding an explicit lifetime bound...: `T: 'a` +... LL | with_signature(x, |y| y) | ^^^^^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-outlives-from-return-type.rs:41:5 | +LL | fn wrong_region<'a, 'b, T>(x: Box) -> Box + | - help: consider adding an explicit lifetime bound...: `T: 'a` +... LL | x | ^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index 5b175aac1e1cb..eaa536ec3a424 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -37,6 +37,8 @@ LL | | } error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-outlives-from-where-clause.rs:27:26 | +LL | fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { + | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | with_signature(a, b, |x, y| { | __________________________^ LL | | @@ -46,8 +48,6 @@ LL | | // See `correct_region`, which explains the point of this LL | | require(&x, &y) LL | | }) | |_____^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... note: external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:43:26 @@ -121,6 +121,9 @@ LL | | } error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-closure-outlives-from-where-clause.rs:64:26 | +LL | fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) + | - help: consider adding an explicit lifetime bound...: `T: 'a` +... LL | with_signature(a, b, |x, y| { | __________________________^ LL | | @@ -128,8 +131,6 @@ LL | | // See `correct_region` LL | | require(&x, &y) LL | | }) | |_____^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... note: external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:77:26 diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr index 9a023a0e58e5f..3cfc23ffcfd66 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr @@ -1,10 +1,10 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-fn-body.rs:19:5 | +LL | fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) { + | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | outlives(cell, t) | ^^^^^^^^^^^^^^^^^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr index 8c8529620d57f..981d3d03b82b7 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr @@ -1,18 +1,20 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-fn.rs:11:5 | +LL | fn no_region<'a, T>(x: Box) -> Box + | - help: consider adding an explicit lifetime bound...: `T: 'a` +... LL | x | ^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... error[E0309]: the parameter type `T` may not live long enough --> $DIR/ty-param-fn.rs:26:5 | +LL | fn wrong_region<'a, 'b, T>(x: Box) -> Box + | - help: consider adding an explicit lifetime bound...: `T: 'a` +... LL | x | ^ - | - = help: consider adding an explicit lifetime bound `T: 'a`... error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr index db771d211322c..a0b955112d2b4 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.nll.stderr @@ -19,10 +19,10 @@ LL | type WrongGeneric = impl 'static; error[E0310]: the parameter type `T` may not live long enough --> $DIR/generic_type_does_not_live_long_enough.rs:18:5 | +LL | fn wrong_generic(t: T) -> WrongGeneric { + | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | t | ^ - | - = help: consider adding an explicit lifetime bound `T: 'static`... error: aborting due to 3 previous errors