From 016626ab129f1ef25be66f12b0b66fcd1f093d60 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Mon, 5 Sep 2022 19:45:53 +0900 Subject: [PATCH] suggest introducing an explicit lifetime if it does not exist --- .../src/infer/error_reporting/mod.rs | 28 +++++++++++++------ ...introducing-and-adding-missing-lifetime.rs | 9 ++++++ ...oducing-and-adding-missing-lifetime.stderr | 23 +++++++++++++++ .../missing-lifetimes-in-signature-2.stderr | 4 +-- .../missing-lifetimes-in-signature.stderr | 18 ++++++------ 5 files changed, 63 insertions(+), 19 deletions(-) create mode 100644 src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs create mode 100644 src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 6dad9873d61..d9252d426d8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2395,19 +2395,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { type_param_span: Option<(Span, bool)>, bound_kind: GenericKind<'tcx>, sub: S, + add_lt_sugg: Option<(Span, String)>, ) { let msg = "consider adding an explicit lifetime bound"; if let Some((sp, has_lifetimes)) = type_param_span { let suggestion = if has_lifetimes { format!(" + {}", sub) } else { format!(": {}", sub) }; - err.span_suggestion_verbose( - sp, - &format!("{}...", msg), - suggestion, + let mut suggestions = vec![(sp, suggestion)]; + if let Some(add_lt_sugg) = add_lt_sugg { + suggestions.push(add_lt_sugg); + } + err.multipart_suggestion_verbose( + format!("{msg}..."), + suggestions, Applicability::MaybeIncorrect, // Issue #41966 ); } else { - let consider = format!("{} `{}: {}`...", msg, bound_kind, sub,); + let consider = format!("{} `{}: {}`...", msg, bound_kind, sub); err.help(&consider); } } @@ -2423,7 +2427,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; let mut sugg = vec![(sp, suggestion), (span.shrink_to_hi(), format!(" + {}", new_lt))]; - if let Some(lt) = add_lt_sugg { + if let Some(lt) = add_lt_sugg.clone() { sugg.push(lt); sugg.rotate_right(1); } @@ -2529,7 +2533,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // for the bound is not suitable for suggestions when `-Zverbose` is set because it // uses `Debug` output, so we handle it specially here so that suggestions are // always correct. - binding_suggestion(&mut err, type_param_span, bound_kind, name); + binding_suggestion(&mut err, type_param_span, bound_kind, name, None); err } @@ -2542,7 +2546,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "{} may not live long enough", labeled_user_string ); - binding_suggestion(&mut err, type_param_span, bound_kind, "'static"); + binding_suggestion(&mut err, type_param_span, bound_kind, "'static", None); err } @@ -2576,7 +2580,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { new_binding_suggestion(&mut err, type_param_span); } _ => { - binding_suggestion(&mut err, type_param_span, bound_kind, new_lt); + binding_suggestion( + &mut err, + type_param_span, + bound_kind, + new_lt, + add_lt_sugg, + ); } } } diff --git a/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs new file mode 100644 index 00000000000..645bc7db0dd --- /dev/null +++ b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.rs @@ -0,0 +1,9 @@ +fn no_restriction(x: &()) -> &() { + with_restriction::(x) //~ ERROR the parameter type `T` may not live long enough +} + +fn with_restriction<'b, T: 'b>(x: &'b ()) -> &'b () { + x +} + +fn main() {} diff --git a/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr new file mode 100644 index 00000000000..a8b0996d8b0 --- /dev/null +++ b/src/test/ui/lifetimes/suggest-introducing-and-adding-missing-lifetime.stderr @@ -0,0 +1,23 @@ +error[E0311]: the parameter type `T` may not live long enough + --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:2:5 + | +LL | with_restriction::(x) + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the parameter type `T` must be valid for the anonymous lifetime defined here... + --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:1:25 + | +LL | fn no_restriction(x: &()) -> &() { + | ^^^ +note: ...so that the type `T` will meet its required lifetime bounds + --> $DIR/suggest-introducing-and-adding-missing-lifetime.rs:2:5 + | +LL | with_restriction::(x) + | ^^^^^^^^^^^^^^^^^^^^^ +help: consider adding an explicit lifetime bound... + | +LL | fn no_restriction<'a, T: 'a>(x: &()) -> &() { + | +++ ++++ + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr index 0212c2d712c..e5d2ead6ad6 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature-2.stderr @@ -22,8 +22,8 @@ LL | | }); | |______^ help: consider adding an explicit lifetime bound... | -LL | fn func(foo: &Foo, t: T) { - | ++++ +LL | fn func<'a, T: Test + 'a>(foo: &Foo, t: T) { + | +++ ++++ error: aborting due to previous error diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr index 0d749f04bea..ed1b91676a2 100644 --- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr +++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr @@ -47,8 +47,10 @@ LL | | } | |_____^ help: consider adding an explicit lifetime bound... | -LL | G: Get + 'a, - | ++++ +LL ~ fn bar<'a, G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ +LL | where +LL ~ G: Get + 'a, + | error[E0311]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:52:5 @@ -74,8 +76,8 @@ LL | | } | |_____^ help: consider adding an explicit lifetime bound... | -LL | fn qux<'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ - | ++++ +LL | fn qux<'b, 'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + | +++ ++++ error[E0311]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:61:9 @@ -101,8 +103,8 @@ LL | | } | |_________^ help: consider adding an explicit lifetime bound... | -LL | fn qux<'b, G: Get + 'b + 'c, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { - | ++++ +LL | fn qux<'c, 'b, G: Get + 'b + 'c, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ { + | +++ ++++ error[E0311]: the parameter type `G` may not live long enough --> $DIR/missing-lifetimes-in-signature.rs:73:5 @@ -130,8 +132,8 @@ LL | | } | |_____^ help: consider adding an explicit lifetime bound... | -LL | fn bat<'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a - | ++++ +LL | fn bat<'b, 'a, G: 'a + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a + | +++ ++++ error[E0621]: explicit lifetime required in the type of `dest` --> $DIR/missing-lifetimes-in-signature.rs:73:5