diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index ba89b0987659e..c0b5a2326e91f 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -740,13 +740,12 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { return false; } if introduce_new { - let new_param_suggestion = if let Some(first) = - generics.params.iter().find(|p| !p.name.ident().span.is_empty()) - { - (first.span.shrink_to_lo(), format!("{suggestion_param_name}, ")) - } else { - (generics.span, format!("<{suggestion_param_name}>")) - }; + let new_param_suggestion = + if let Some(span) = generics.span_for_lifetime_suggestion() { + (span, format!("{suggestion_param_name}, ")) + } else { + (generics.span, format!("<{suggestion_param_name}>")) + }; visitor.suggestions.push(new_param_suggestion); } diff --git a/tests/ui/lifetimes/apit-not-targeted-by-lifetime-suggestion.rs b/tests/ui/lifetimes/apit-not-targeted-by-lifetime-suggestion.rs new file mode 100644 index 0000000000000..df0cb6b5eed0f --- /dev/null +++ b/tests/ui/lifetimes/apit-not-targeted-by-lifetime-suggestion.rs @@ -0,0 +1,24 @@ +// Regression test for #158954. +// +// The "introduce a named lifetime parameter" suggestion must introduce the +// lifetime into the function's own generic parameter list (`fn f<'a>(...)`) +// and must never insert it into an unrelated argument-position `impl Trait` +// parameter (which would produce invalid code like `_fun: 'a, impl Clone` or +// `_fun: &'a, impl Clone`). + +fn push_apit(vec: &mut Vec<&str>, s: &str, _fun: impl Clone) { + vec.push(s); + //~^ ERROR lifetime may not live long enough +} + +fn push_ref_apit(vec: &mut Vec<&str>, s: &str, _fun: &impl Clone) { + vec.push(s); + //~^ ERROR lifetime may not live long enough +} + +fn push_real_generic(vec: &mut Vec<&str>, s: &str, _fun: T) { + vec.push(s); + //~^ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/lifetimes/apit-not-targeted-by-lifetime-suggestion.stderr b/tests/ui/lifetimes/apit-not-targeted-by-lifetime-suggestion.stderr new file mode 100644 index 0000000000000..00855f1d9a9b7 --- /dev/null +++ b/tests/ui/lifetimes/apit-not-targeted-by-lifetime-suggestion.stderr @@ -0,0 +1,56 @@ +error: lifetime may not live long enough + --> $DIR/apit-not-targeted-by-lifetime-suggestion.rs:10:5 + | +LL | fn push_apit(vec: &mut Vec<&str>, s: &str, _fun: impl Clone) { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | vec.push(s); + | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + | + = note: requirement occurs because of a mutable reference to `Vec<&str>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance +help: consider introducing a named lifetime parameter + | +LL | fn push_apit<'a>(vec: &mut Vec<&'a str>, s: &'a str, _fun: impl Clone) { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/apit-not-targeted-by-lifetime-suggestion.rs:15:5 + | +LL | fn push_ref_apit(vec: &mut Vec<&str>, s: &str, _fun: &impl Clone) { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | vec.push(s); + | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + | + = note: requirement occurs because of a mutable reference to `Vec<&str>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance +help: consider introducing a named lifetime parameter + | +LL | fn push_ref_apit<'a>(vec: &mut Vec<&'a str>, s: &'a str, _fun: &impl Clone) { + | ++++ ++ ++ + +error: lifetime may not live long enough + --> $DIR/apit-not-targeted-by-lifetime-suggestion.rs:20:5 + | +LL | fn push_real_generic(vec: &mut Vec<&str>, s: &str, _fun: T) { + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | vec.push(s); + | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + | + = note: requirement occurs because of a mutable reference to `Vec<&str>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance +help: consider introducing a named lifetime parameter + | +LL | fn push_real_generic<'a, T>(vec: &mut Vec<&'a str>, s: &'a str, _fun: T) { + | +++ ++ ++ + +error: aborting due to 3 previous errors +