From 887515af33f80d85b76b41ef175ea1ec0e208776 Mon Sep 17 00:00:00 2001 From: stoozy Date: Mon, 26 Sep 2022 13:10:24 -0400 Subject: [PATCH 1/6] Trying to suggest additional lifetime parameter --- compiler/rustc_resolve/src/late/lifetimes.rs | 40 ++++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 9fb1af20ac976..c69242f5d33a1 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -8,7 +8,7 @@ use rustc_ast::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_errors::struct_span_err; +use rustc_errors::{struct_span_err}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; @@ -24,6 +24,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use std::fmt; + trait RegionExt { fn early(hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region); @@ -1318,13 +1319,36 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id) && !self.tcx.features().anonymous_lifetime_in_impl_trait { - rustc_session::parse::feature_err( - &self.tcx.sess.parse_sess, - sym::anonymous_lifetime_in_impl_trait, - lifetime_ref.span, - "anonymous lifetimes in `impl Trait` are unstable", - ).emit(); - return; + + match self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.to_def_id().as_local().unwrap()) { + Some(generics) => { + for i in 0..generics.params.len() { + + if !generics.span.contains(generics.params[i].span) { + struct_span_err!( + self.tcx.sess, + lifetime_ref.span, + E0106, + "missing lifetime specifier" + ) + .span_label(lifetime_ref.span, "expected named lifetime parameter") + .span_help(generics.span, "consider introducing a named lifetime parameter") + .emit(); + return; + } + } + }, + None => { + rustc_session::parse::feature_err( + &self.tcx.sess.parse_sess, + sym::anonymous_lifetime_in_impl_trait, + lifetime_ref.span, + "anonymous lifetimes in `impl Trait` are unstable", + ).emit(); + return; + } + } + } scope = s; } From 365457bd2590029e0cdba5b401273169c0fa6a79 Mon Sep 17 00:00:00 2001 From: stoozy Date: Mon, 26 Sep 2022 22:17:47 -0400 Subject: [PATCH 2/6] Using multipart suggestion --- compiler/rustc_resolve/src/late/lifetimes.rs | 31 ++++++++++++-------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index c69242f5d33a1..991d8f8830741 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -8,7 +8,7 @@ use rustc_ast::walk_list; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_errors::{struct_span_err}; +use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; @@ -24,7 +24,6 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use std::fmt; - trait RegionExt { fn early(hir_map: Map<'_>, param: &GenericParam<'_>) -> (LocalDefId, Region); @@ -1320,21 +1319,29 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { && !self.tcx.features().anonymous_lifetime_in_impl_trait { - match self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.to_def_id().as_local().unwrap()) { + match self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id) { Some(generics) => { for i in 0..generics.params.len() { if !generics.span.contains(generics.params[i].span) { - struct_span_err!( - self.tcx.sess, + + let mut diag = rustc_session::parse::feature_err( + &self.tcx.sess.parse_sess, + sym::anonymous_lifetime_in_impl_trait, lifetime_ref.span, - E0106, - "missing lifetime specifier" - ) - .span_label(lifetime_ref.span, "expected named lifetime parameter") - .span_help(generics.span, "consider introducing a named lifetime parameter") - .emit(); - return; + "anonymous lifetimes in `impl Trait` are unstable", + ); + + diag.span_label(lifetime_ref.span, "expected named lifetime parameter"); + + diag.multipart_suggestion("consider introducing a named lifetime parameter", + vec![ + (lifetime_ref.span, "&'a ".to_owned()), + (generics.span, "<'a>".to_owned()) + ], rustc_errors::Applicability::MaybeIncorrect); + diag.emit(); + + return; } } }, From 24c8e27a1d1693786a5ec0ddffedefeb01ff4fb4 Mon Sep 17 00:00:00 2001 From: stoozy Date: Tue, 27 Sep 2022 11:06:51 -0400 Subject: [PATCH 3/6] Properly formatting the multipart suggestion --- compiler/rustc_resolve/src/late/lifetimes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 991d8f8830741..9b66c42651d7f 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1336,7 +1336,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { diag.multipart_suggestion("consider introducing a named lifetime parameter", vec![ - (lifetime_ref.span, "&'a ".to_owned()), + (lifetime_ref.span.shrink_to_hi(), "'a ".to_owned()), (generics.span, "<'a>".to_owned()) ], rustc_errors::Applicability::MaybeIncorrect); diag.emit(); From e7cb6ad8ce382ded99be31c95562c8d91a635b24 Mon Sep 17 00:00:00 2001 From: stoozy Date: Wed, 28 Sep 2022 00:33:52 -0400 Subject: [PATCH 4/6] Proper span for new generic param suggestion --- compiler/rustc_resolve/src/late/lifetimes.rs | 9 +++++++-- .../impl-trait-missing-lifetime-gated.stderr | 12 ++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 9b66c42651d7f..40d183bf1baca 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1333,11 +1333,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { ); diag.span_label(lifetime_ref.span, "expected named lifetime parameter"); - diag.multipart_suggestion("consider introducing a named lifetime parameter", vec![ (lifetime_ref.span.shrink_to_hi(), "'a ".to_owned()), - (generics.span, "<'a>".to_owned()) + match generics.span_for_param_suggestion() { + Some(_) => { + (self.tcx.sess.source_map().span_through_char(generics.span, '<').shrink_to_hi(), "'a, ".to_owned()) + } + None => (generics.span, "<'a>".to_owned()), + + } ], rustc_errors::Applicability::MaybeIncorrect); diag.emit(); diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr index e82a6f769e090..9833da13ffc2a 100644 --- a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr +++ b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.stderr @@ -26,17 +26,25 @@ error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:5:31 | LL | fn f(_: impl Iterator) {} - | ^^ + | ^^ expected named lifetime parameter | = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable +help: consider introducing a named lifetime parameter + | +LL | fn f<'a>(_: impl Iterator) {} + | ++++ ++ error[E0658]: anonymous lifetimes in `impl Trait` are unstable --> $DIR/impl-trait-missing-lifetime-gated.rs:8:31 | LL | fn g(x: impl Iterator) -> Option<&'_ ()> { x.next() } - | ^^ + | ^^ expected named lifetime parameter | = help: add `#![feature(anonymous_lifetime_in_impl_trait)]` to the crate attributes to enable +help: consider introducing a named lifetime parameter + | +LL | fn g<'a>(x: impl Iterator) -> Option<&'_ ()> { x.next() } + | ++++ ++ error: aborting due to 4 previous errors From ef930a220042e63910f33f7d10da317635fb21cb Mon Sep 17 00:00:00 2001 From: stoozy Date: Thu, 29 Sep 2022 04:06:02 -0400 Subject: [PATCH 5/6] Emitting error regardless of new param suggestion --- compiler/rustc_resolve/src/late/lifetimes.rs | 66 ++++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 40d183bf1baca..16a819504953f 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1319,48 +1319,48 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { && !self.tcx.features().anonymous_lifetime_in_impl_trait { + + let mut diag = rustc_session::parse::feature_err( + &self.tcx.sess.parse_sess, + sym::anonymous_lifetime_in_impl_trait, + lifetime_ref.span, + "anonymous lifetimes in `impl Trait` are unstable", + ); + match self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id) { Some(generics) => { - for i in 0..generics.params.len() { - if !generics.span.contains(generics.params[i].span) { + let mut new_param_sugg_tuple = None; - let mut diag = rustc_session::parse::feature_err( - &self.tcx.sess.parse_sess, - sym::anonymous_lifetime_in_impl_trait, - lifetime_ref.span, - "anonymous lifetimes in `impl Trait` are unstable", - ); - - diag.span_label(lifetime_ref.span, "expected named lifetime parameter"); - diag.multipart_suggestion("consider introducing a named lifetime parameter", - vec![ - (lifetime_ref.span.shrink_to_hi(), "'a ".to_owned()), - match generics.span_for_param_suggestion() { - Some(_) => { - (self.tcx.sess.source_map().span_through_char(generics.span, '<').shrink_to_hi(), "'a, ".to_owned()) - } - None => (generics.span, "<'a>".to_owned()), - - } - ], rustc_errors::Applicability::MaybeIncorrect); - diag.emit(); - - return; + for i in 0..generics.params.len() { + if !generics.span.contains(generics.params[i].span) { + new_param_sugg_tuple = match generics.span_for_param_suggestion() { + Some(_) => { + Some((self.tcx.sess.source_map().span_through_char(generics.span, '<').shrink_to_hi(), "'a, ".to_owned())) + }, + None => Some((generics.span, "<'a>".to_owned())) + } } } + + let mut multi_sugg_vec = vec![(lifetime_ref.span.shrink_to_hi(), "'a ".to_owned())]; + + if let Some(new_tuple) = new_param_sugg_tuple{ + multi_sugg_vec.push(new_tuple); + } + + diag.span_label(lifetime_ref.span, "expected named lifetime parameter"); + diag.multipart_suggestion("consider introducing a named lifetime parameter", + multi_sugg_vec, + rustc_errors::Applicability::MaybeIncorrect); + }, - None => { - rustc_session::parse::feature_err( - &self.tcx.sess.parse_sess, - sym::anonymous_lifetime_in_impl_trait, - lifetime_ref.span, - "anonymous lifetimes in `impl Trait` are unstable", - ).emit(); - return; - } + None => { continue; } } + diag.emit(); + return; + } scope = s; } From 2657f9d5da0a9bff0764df824e26f2169e2e398d Mon Sep 17 00:00:00 2001 From: stoozy Date: Sat, 1 Oct 2022 13:55:26 -0400 Subject: [PATCH 6/6] Removed unnecessary for loop --- compiler/rustc_resolve/src/late/lifetimes.rs | 25 +++++++------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 16a819504953f..cdb8797b4ffe8 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1318,8 +1318,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id) && !self.tcx.features().anonymous_lifetime_in_impl_trait { - - let mut diag = rustc_session::parse::feature_err( &self.tcx.sess.parse_sess, sym::anonymous_lifetime_in_impl_trait, @@ -1330,18 +1328,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { match self.tcx.hir().get_generics(lifetime_ref.hir_id.owner.def_id) { Some(generics) => { - let mut new_param_sugg_tuple = None; - - for i in 0..generics.params.len() { - if !generics.span.contains(generics.params[i].span) { - new_param_sugg_tuple = match generics.span_for_param_suggestion() { - Some(_) => { - Some((self.tcx.sess.source_map().span_through_char(generics.span, '<').shrink_to_hi(), "'a, ".to_owned())) - }, - None => Some((generics.span, "<'a>".to_owned())) - } - } - } + let new_param_sugg_tuple; + + new_param_sugg_tuple = match generics.span_for_param_suggestion() { + Some(_) => { + Some((self.tcx.sess.source_map().span_through_char(generics.span, '<').shrink_to_hi(), "'a, ".to_owned())) + }, + None => Some((generics.span, "<'a>".to_owned())) + }; let mut multi_sugg_vec = vec![(lifetime_ref.span.shrink_to_hi(), "'a ".to_owned())]; @@ -1355,12 +1349,11 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { rustc_errors::Applicability::MaybeIncorrect); }, - None => { continue; } + None => { } } diag.emit(); return; - } scope = s; }