diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 7fb07a5d30c..e15866f3f0f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -64,11 +64,11 @@ codes::*, pluralize, struct_span_code_err, Applicability, Diag, DiagCtxt, DiagStyledString, ErrorGuaranteed, IntoDiagArg, StringPart, }; -use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; +use rustc_hir::{self as hir, ParamName}; use rustc_macros::extension; use rustc_middle::bug; use rustc_middle::dep_graph::DepContext; @@ -2429,7 +2429,8 @@ pub fn construct_generic_bound_failure( let (type_scope, type_param_sugg_span) = match bound_kind { GenericKind::Param(param) => { let generics = self.tcx.generics_of(generic_param_scope); - let def_id = generics.type_param(param, self.tcx).def_id.expect_local(); + let type_param = generics.type_param(param, self.tcx); + let def_id = type_param.def_id.expect_local(); let scope = self.tcx.local_def_id_to_hir_id(def_id).owner.def_id; // Get the `hir::Param` to verify whether it already has any bounds. // We do this to avoid suggesting code that ends up as `T: 'a'b`, @@ -2439,7 +2440,18 @@ pub fn construct_generic_bound_failure( Some((span, open_paren_sp)) => Some((span, true, open_paren_sp)), // If `param` corresponds to `Self`, no usable suggestion span. None if generics.has_self && param.index == 0 => None, - None => Some((self.tcx.def_span(def_id).shrink_to_hi(), false, None)), + None => { + let span = if let Some(param) = + hir_generics.params.iter().find(|param| param.def_id == def_id) + && let ParamName::Plain(ident) = param.name + { + ident.span.shrink_to_hi() + } else { + let span = self.tcx.def_span(def_id); + span.shrink_to_hi() + }; + Some((span, false, None)) + } }; (scope, sugg_span) } diff --git a/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.rs b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.rs new file mode 100644 index 00000000000..68879a0af29 --- /dev/null +++ b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.rs @@ -0,0 +1,26 @@ +//@ error-pattern: r#T: 'static +//@ error-pattern: r#K: 'static +//@ error-pattern: T: 'static= + +// https://github.com/rust-lang/rust/issues/124785 + +struct Foo(&'static T, &'static K); +//~^ ERROR: the parameter type `T` may not live long enough +//~| ERROR: the parameter type `K` may not live long enough + +struct Bar(&'static r#T, &'static r#K); +//~^ ERROR: the parameter type `T` may not live long enough +//~| ERROR: the parameter type `K` may not live long enough + +struct Boo(&'static T); +//~^ ERROR: the parameter type `T` may not live long enough + +struct Far(&'static T); +//~^ ERROR: the parameter type `T` may not live long enough + +struct S<'a, K: 'a = i32>(&'static K); +//~^ ERROR: lifetime parameter `'a` is never used +//~| ERROR: the parameter type `K` may not live long enough + +fn main() {} diff --git a/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr new file mode 100644 index 00000000000..7d985a9013f --- /dev/null +++ b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr @@ -0,0 +1,110 @@ +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/static-lifetime-tip-with-default-type.rs:7:24 + | +LL | struct Foo(&'static T, &'static K); + | ^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the reference type `&'static T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound + | +LL | struct Foo(&'static T, &'static K); + | +++++++++ + +error[E0310]: the parameter type `K` may not live long enough + --> $DIR/static-lifetime-tip-with-default-type.rs:7:36 + | +LL | struct Foo(&'static T, &'static K); + | ^^^^^^^^^^ + | | + | the parameter type `K` must be valid for the static lifetime... + | ...so that the reference type `&'static K` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound + | +LL | struct Foo(&'static T, &'static K); + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/static-lifetime-tip-with-default-type.rs:11:28 + | +LL | struct Bar(&'static r#T, &'static r#K); + | ^^^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the reference type `&'static T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound + | +LL | struct Bar(&'static r#T, &'static r#K); + | +++++++++ + +error[E0310]: the parameter type `K` may not live long enough + --> $DIR/static-lifetime-tip-with-default-type.rs:11:42 + | +LL | struct Bar(&'static r#T, &'static r#K); + | ^^^^^^^^^^^^ + | | + | the parameter type `K` must be valid for the static lifetime... + | ...so that the reference type `&'static K` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound + | +LL | struct Bar(&'static r#T, &'static r#K); + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/static-lifetime-tip-with-default-type.rs:15:20 + | +LL | struct Boo(&'static T); + | ^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the reference type `&'static T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound + | +LL | struct Boo(&'static T); + | +++++++++ + +error[E0310]: the parameter type `T` may not live long enough + --> $DIR/static-lifetime-tip-with-default-type.rs:19:8 + | +LL | = i32>(&'static T); + | ^^^^^^^^^^ + | | + | the parameter type `T` must be valid for the static lifetime... + | ...so that the reference type `&'static T` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound + | +LL | struct Far $DIR/static-lifetime-tip-with-default-type.rs:22:27 + | +LL | struct S<'a, K: 'a = i32>(&'static K); + | ^^^^^^^^^^ + | | + | the parameter type `K` must be valid for the static lifetime... + | ...so that the reference type `&'static K` does not outlive the data it points at + | +help: consider adding an explicit lifetime bound + | +LL | struct S<'a, K: 'a + 'static = i32>(&'static K); + | +++++++++ + +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/static-lifetime-tip-with-default-type.rs:22:10 + | +LL | struct S<'a, K: 'a = i32>(&'static K); + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0310, E0392. +For more information about an error, try `rustc --explain E0310`.