From b9235ea57c460ef4c2f2b963d85f3040c7e09398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 12 Dec 2018 13:57:47 -0800 Subject: [PATCH] Account for `impl Trait` when suggesting lifetime --- src/librustc/infer/error_reporting/mod.rs | 31 ++++++++++++------- .../suggest-impl-trait-lifetime.fixed | 18 +++++++++++ .../suggest-impl-trait-lifetime.rs | 18 +++++++++++ .../suggest-impl-trait-lifetime.stderr | 19 ++++++++++++ 4 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed create mode 100644 src/test/ui/suggestions/suggest-impl-trait-lifetime.rs create mode 100644 src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 7d997a0154600..d213a5c561871 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1095,7 +1095,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let sp = hir.span(id); // `sp` only covers `T`, change it so that it covers // `T:` when appropriate - let sp = if has_bounds { + let is_impl_trait = bound_kind.to_string().starts_with("impl "); + let sp = if has_bounds && !is_impl_trait { sp.to(self.tcx .sess .source_map() @@ -1103,7 +1104,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } else { sp }; - (sp, has_bounds) + (sp, has_bounds, is_impl_trait) }) } else { None @@ -1136,25 +1137,33 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn binding_suggestion<'tcx, S: fmt::Display>( err: &mut DiagnosticBuilder<'tcx>, - type_param_span: Option<(Span, bool)>, + type_param_span: Option<(Span, bool, bool)>, bound_kind: GenericKind<'tcx>, sub: S, ) { - let consider = &format!( - "consider adding an explicit lifetime bound `{}: {}`...", - bound_kind, sub + let consider = format!( + "consider adding an explicit lifetime bound {}", + if type_param_span.map(|(_, _, is_impl_trait)| is_impl_trait).unwrap_or(false) { + format!(" `{}` to `{}`...", sub, bound_kind) + } else { + format!("`{}: {}`...", bound_kind, sub) + }, ); - if let Some((sp, has_lifetimes)) = type_param_span { - let tail = if has_lifetimes { " + " } else { "" }; - let suggestion = format!("{}: {}{}", bound_kind, sub, tail); + if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span { + let suggestion = if is_impl_trait { + format!("{} + {}", bound_kind, sub) + } else { + let tail = if has_lifetimes { " + " } else { "" }; + format!("{}: {}{}", bound_kind, sub, tail) + }; err.span_suggestion_short_with_applicability( sp, - consider, + &consider, suggestion, Applicability::MaybeIncorrect, // Issue #41966 ); } else { - err.help(consider); + err.help(&consider); } } diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed new file mode 100644 index 0000000000000..8592af1262e6f --- /dev/null +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed @@ -0,0 +1,18 @@ +// run-rustfix + +use std::fmt::Debug; + +fn foo(d: impl Debug + 'static) { +//~^ HELP consider adding an explicit lifetime bound `'static` to `impl Debug` + bar(d); +//~^ ERROR the parameter type `impl Debug` may not live long enough +//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds +} + +fn bar(d: impl Debug + 'static) { + println!("{:?}", d) +} + +fn main() { + foo("hi"); +} diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs new file mode 100644 index 0000000000000..c67d78ea4c73b --- /dev/null +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs @@ -0,0 +1,18 @@ +// run-rustfix + +use std::fmt::Debug; + +fn foo(d: impl Debug) { +//~^ HELP consider adding an explicit lifetime bound `'static` to `impl Debug` + bar(d); +//~^ ERROR the parameter type `impl Debug` may not live long enough +//~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds +} + +fn bar(d: impl Debug + 'static) { + println!("{:?}", d) +} + +fn main() { + foo("hi"); +} diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr new file mode 100644 index 0000000000000..cba231d0e86e5 --- /dev/null +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr @@ -0,0 +1,19 @@ +error[E0310]: the parameter type `impl Debug` may not live long enough + --> $DIR/suggest-impl-trait-lifetime.rs:7:5 + | +LL | bar(d); + | ^^^ + | +note: ...so that the type `impl Debug` will meet its required lifetime bounds + --> $DIR/suggest-impl-trait-lifetime.rs:7:5 + | +LL | bar(d); + | ^^^ +help: consider adding an explicit lifetime bound `'static` to `impl Debug`... + | +LL | fn foo(d: impl Debug + 'static) { + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0310`.