diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e4f431fd2431c..11baca246b8f0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -878,7 +878,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Fresh, hir::LifetimeParamKind::Elided(kind)) } - LifetimeRes::Static { .. } | LifetimeRes::Error => return None, + LifetimeRes::Static { .. } | LifetimeRes::Error(..) => return None, res => panic!( "Unexpected lifetime resolution {:?} for {:?} at {:?}", res, ident, ident.span @@ -1931,27 +1931,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { source: LifetimeSource, syntax: LifetimeSyntax, ) -> &'hir hir::Lifetime { - let res = self.resolver.get_lifetime_res(id).unwrap_or(LifetimeRes::Error); - let res = match res { - LifetimeRes::Param { param, .. } => hir::LifetimeKind::Param(param), - LifetimeRes::Fresh { param, .. } => { - assert_eq!(ident.name, kw::UnderscoreLifetime); - let param = self.local_def_id(param); - hir::LifetimeKind::Param(param) - } - LifetimeRes::Infer => { - assert_eq!(ident.name, kw::UnderscoreLifetime); - hir::LifetimeKind::Infer - } - LifetimeRes::Static { .. } => { - assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime)); - hir::LifetimeKind::Static - } - LifetimeRes::Error => hir::LifetimeKind::Error, - LifetimeRes::ElidedAnchor { .. } => { - panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span); - } - }; + let res = + self.resolver.get_lifetime_res(id).map_or( + hir::LifetimeKind::NotFound, + |res| match res { + LifetimeRes::Param { param, .. } => hir::LifetimeKind::Param(param), + LifetimeRes::Fresh { param, .. } => { + assert_eq!(ident.name, kw::UnderscoreLifetime); + let param = self.local_def_id(param); + hir::LifetimeKind::Param(param) + } + LifetimeRes::Infer => { + assert_eq!(ident.name, kw::UnderscoreLifetime); + hir::LifetimeKind::Infer + } + LifetimeRes::Static { .. } => { + assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime)); + hir::LifetimeKind::Static + } + LifetimeRes::Error(guar) => hir::LifetimeKind::Error(guar), + LifetimeRes::ElidedAnchor { .. } => { + panic!("Unexpected `ElidedAnchar` {:?} at {:?}", ident, ident.span); + } + }, + ); debug!(?res); self.arena.alloc(hir::Lifetime::new( @@ -2014,12 +2017,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // AST resolution emitted an error on those parameters, so we lower them using // `ParamName::Error`. let ident = self.lower_ident(param.ident); - let param_name = - if let Some(LifetimeRes::Error) = self.resolver.get_lifetime_res(param.id) { - ParamName::Error(ident) - } else { - ParamName::Plain(ident) - }; + let param_name = if let Some(LifetimeRes::Error(..)) = + self.resolver.get_lifetime_res(param.id) + { + ParamName::Error(ident) + } else { + ParamName::Plain(ident) + }; let kind = hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit }; diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index e93deaa84944e..dd2cd4939432b 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -990,7 +990,7 @@ pub enum LifetimeRes { /// `'static` lifetime. Static, /// Resolution failure. - Error, + Error(rustc_span::ErrorGuaranteed), /// HACK: This is used to recover the NodeId of an elided lifetime. ElidedAnchor { start: NodeId, end: NodeId }, } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index b117fa8327296..474ae725ff493 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -238,7 +238,8 @@ pub enum LifetimeKind { /// Indicates an error during lowering (usually `'_` in wrong place) /// that was already reported. - Error, + Error(ErrorGuaranteed), + NotFound, /// User wrote an anonymous lifetime, either `'_` or nothing (which gets /// converted to `'_`). The semantics of this lifetime should be inferred @@ -258,7 +259,10 @@ impl LifetimeKind { // -- but this is because, as far as the code in the compiler is // concerned -- `Fresh` variants act equivalently to "some fresh name". // They correspond to early-bound regions on an impl, in other words. - LifetimeKind::Error | LifetimeKind::Param(..) | LifetimeKind::Static => false, + LifetimeKind::Error(..) + | LifetimeKind::NotFound + | LifetimeKind::Param(..) + | LifetimeKind::Static => false, } } } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 26f79d374075b..995d6433964f7 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -663,7 +663,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { LifetimeKind::Param(def_id) => { self.resolve_lifetime_ref(def_id, lt); } - LifetimeKind::Error => {} + LifetimeKind::Error(..) | LifetimeKind::NotFound => {} LifetimeKind::ImplicitObjectLifetimeDefault | LifetimeKind::Infer | LifetimeKind::Static => { @@ -804,7 +804,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { // If the user wrote an explicit name, use that. self.visit_lifetime(&*lifetime); } - LifetimeKind::Error => {} + LifetimeKind::Error(..) | LifetimeKind::NotFound => {} } } hir::TyKind::Ref(lifetime_ref, ref mt) => { @@ -891,8 +891,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { hir::LifetimeKind::Param(param_def_id) => { self.resolve_lifetime_ref(param_def_id, lifetime_ref) } - // If we've already reported an error, just ignore `lifetime_ref`. - hir::LifetimeKind::Error => {} + // Just ignore `lifetime_ref` if it couldn't be resolved + hir::LifetimeKind::NotFound => {} + // Keep track of lifetimes about which errors have already been reported + hir::LifetimeKind::Error(guar) => { + self.insert_lifetime(lifetime_ref, ResolvedArg::Error(guar)) + } // Those will be resolved by typechecking. hir::LifetimeKind::ImplicitObjectLifetimeDefault | hir::LifetimeKind::Infer => {} } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 57defac577d8a..b3e6b9623bd27 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -451,17 +451,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else { let reason = if let hir::LifetimeKind::ImplicitObjectLifetimeDefault = lifetime.kind { - if let hir::Node::Ty(hir::Ty { - kind: hir::TyKind::Ref(parent_lifetime, _), - .. - }) = tcx.parent_hir_node(hir_id) - && tcx.named_bound_var(parent_lifetime.hir_id).is_none() - { - // Parent lifetime must have failed to resolve. Don't emit a redundant error. - RegionInferReason::ExplicitObjectLifetime - } else { - RegionInferReason::ObjectLifetimeDefault - } + RegionInferReason::ObjectLifetimeDefault } else { RegionInferReason::ExplicitObjectLifetime }; diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 4faf7715de6eb..3303936f490d2 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -746,7 +746,8 @@ pub(crate) struct DiagMetadata<'ast> { /// Accumulate the errors due to missed lifetime elision, /// and report them all at once for each function. - current_elision_failures: Vec, + current_elision_failures: + Vec<(MissingLifetime, LifetimeElisionCandidate, NodeId, Option)>, } struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { @@ -1782,19 +1783,19 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { match rib.kind { LifetimeRibKind::Item => break, LifetimeRibKind::ConstParamTy => { - self.emit_non_static_lt_in_const_param_ty_error(lifetime); + let guar = self.emit_non_static_lt_in_const_param_ty_error(lifetime); self.record_lifetime_res( lifetime.id, - LifetimeRes::Error, + LifetimeRes::Error(guar), LifetimeElisionCandidate::Ignore, ); return; } LifetimeRibKind::ConcreteAnonConst(cause) => { - self.emit_forbidden_non_static_lifetime_error(cause, lifetime); + let guar = self.emit_forbidden_non_static_lifetime_error(cause, lifetime); self.record_lifetime_res( lifetime.id, - LifetimeRes::Error, + LifetimeRes::Error(guar), LifetimeElisionCandidate::Ignore, ); return; @@ -1812,8 +1813,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let outer_res = lifetime_rib_iter .find_map(|rib| rib.bindings.get_key_value(&normalized_ident).map(|(&outer, _)| outer)); - self.emit_undeclared_lifetime_error(lifetime, outer_res); - self.record_lifetime_res(lifetime.id, LifetimeRes::Error, LifetimeElisionCandidate::Named); + let guar = self.emit_undeclared_lifetime_error(lifetime, outer_res); + self.record_lifetime_res( + lifetime.id, + LifetimeRes::Error(guar), + LifetimeElisionCandidate::Named, + ); } #[instrument(level = "debug", skip(self))] @@ -1878,7 +1883,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } LifetimeRibKind::AnonymousReportError => { - if elided { + let guar = if elided { let suggestion = self.lifetime_ribs[i..].iter().rev().find_map(|rib| { if let LifetimeRibKind::Generics { span, @@ -1910,7 +1915,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.r.dcx().emit_err(errors::LendingIteratorReportError { lifetime: lifetime.ident.span, ty: ty.span, - }); + }) } else { let decl = if !trait_id.is_local() && let Some(assoc) = self.diag_metadata.current_impl_item @@ -1940,20 +1945,24 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }, ); self.point_at_impl_lifetimes(&mut err, i, lifetime.ident.span); - err.emit(); + err.emit() } } else { self.r.dcx().emit_err(errors::ElidedAnonymousLifetimeReportError { span: lifetime.ident.span, suggestion, - }); + }) } } else { self.r.dcx().emit_err(errors::ExplicitAnonymousLifetimeReportError { span: lifetime.ident.span, - }); + }) }; - self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); + self.record_lifetime_res( + lifetime.id, + LifetimeRes::Error(guar), + elision_candidate, + ); return; } LifetimeRibKind::Elided(res) => { @@ -1961,8 +1970,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { return; } LifetimeRibKind::ElisionFailure => { - self.diag_metadata.current_elision_failures.push(missing_lifetime); - self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); + self.diag_metadata.current_elision_failures.push(( + missing_lifetime, + elision_candidate, + lifetime.id, + None, + )); return; } LifetimeRibKind::Item => break, @@ -1973,8 +1986,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } } } - self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); - self.report_missing_lifetime_specifiers(vec![missing_lifetime], None); + let guar = self.report_missing_lifetime_specifiers([&missing_lifetime], None); + self.record_lifetime_res(lifetime.id, LifetimeRes::Error(guar), elision_candidate); } fn point_at_impl_lifetimes(&mut self, err: &mut Diag<'_>, i: usize, lifetime: Span) { @@ -2222,16 +2235,17 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { !segment.has_generic_args, elided_lifetime_span, ); - self.r.dcx().emit_err(errors::ImplicitElidedLifetimeNotAllowedHere { - span: path_span, - subdiag, - }); + let guar = + self.r.dcx().emit_err(errors::ImplicitElidedLifetimeNotAllowedHere { + span: path_span, + subdiag, + }); should_lint = false; for id in node_ids { self.record_lifetime_res( id, - LifetimeRes::Error, + LifetimeRes::Error(guar), LifetimeElisionCandidate::Named, ); } @@ -2263,14 +2277,12 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { break; } LifetimeRibKind::ElisionFailure => { - self.diag_metadata.current_elision_failures.push(missing_lifetime); - for id in node_ids { - self.record_lifetime_res( - id, - LifetimeRes::Error, - LifetimeElisionCandidate::Ignore, - ); - } + self.diag_metadata.current_elision_failures.push(( + missing_lifetime, + LifetimeElisionCandidate::Ignore, + node_ids.start, + Some(node_ids.end), + )); break; } // `LifetimeRes::Error`, which would usually be used in the case of @@ -2278,14 +2290,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // we simply resolve to an implicit lifetime, which will be checked later, at // which point a suitable error will be emitted. LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => { + let guar = + self.report_missing_lifetime_specifiers([&missing_lifetime], None); for id in node_ids { self.record_lifetime_res( id, - LifetimeRes::Error, + LifetimeRes::Error(guar), LifetimeElisionCandidate::Ignore, ); } - self.report_missing_lifetime_specifiers(vec![missing_lifetime], None); break; } LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {} @@ -2329,7 +2342,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { candidates.push((res, candidate)); } } - LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {} + LifetimeRes::Infer | LifetimeRes::Error(..) | LifetimeRes::ElidedAnchor { .. } => {} } } @@ -2373,7 +2386,23 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { replace(&mut this.diag_metadata.current_elision_failures, outer_failures); if !elision_failures.is_empty() { let Err(failure_info) = elision_lifetime else { bug!() }; - this.report_missing_lifetime_specifiers(elision_failures, Some(failure_info)); + let guar = this.report_missing_lifetime_specifiers( + elision_failures.iter().map(|(missing_lifetime, ..)| missing_lifetime), + Some(failure_info), + ); + let mut record_res = |lifetime, candidate| { + this.record_lifetime_res(lifetime, LifetimeRes::Error(guar), candidate) + }; + for (_, candidate, start, end) in elision_failures { + match end { + Some(end) => { + for lifetime in start..end { + record_res(lifetime, candidate) + } + } + None => record_res(start, candidate), + } + } } }); } @@ -3028,9 +3057,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { if let GenericParamKind::Lifetime = param.kind && let Some(&original) = seen_lifetimes.get(&ident) { - diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident); + let guar = diagnostics::signal_lifetime_shadowing( + self.r.tcx.sess, + original, + param.ident, + ); // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error); + self.record_lifetime_param(param.id, LifetimeRes::Error(guar)); continue; } @@ -3038,11 +3071,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { Entry::Occupied(entry) => { let span = *entry.get(); let err = ResolutionError::NameAlreadyUsedInParameterList(ident, span); - self.report_error(param.ident.span, err); + let guar = self.r.report_error(param.ident.span, err); let rib = match param.kind { GenericParamKind::Lifetime => { // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error); + self.record_lifetime_param(param.id, LifetimeRes::Error(guar)); continue; } GenericParamKind::Type { .. } => &mut function_type_rib, @@ -3071,22 +3104,23 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { .iter() .any(|span| span == param.span()); - self.r + let guar = self + .r .dcx() .create_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span }) .emit_unless_delay(is_raw_underscore_lifetime); // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error); + self.record_lifetime_param(param.id, LifetimeRes::Error(guar)); continue; } if param.ident.name == kw::StaticLifetime { - self.r.dcx().emit_err(errors::StaticLifetimeIsReserved { + let guar = self.r.dcx().emit_err(errors::StaticLifetimeIsReserved { span: param.ident.span, lifetime: param.ident, }); // Record lifetime res, so lowering knows there is something fishy. - self.record_lifetime_param(param.id, LifetimeRes::Error); + self.record_lifetime_param(param.id, LifetimeRes::Error(guar)); continue; } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 8794c4ff8b025..c89591649da5f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -131,7 +131,7 @@ pub(super) struct ElisionFnParameter { /// Description of lifetimes that appear as candidates for elision. /// This is used to suggest introducing an explicit lifetime. -#[derive(Debug)] +#[derive(Clone, Copy, Debug)] pub(super) enum LifetimeElisionCandidate { /// This is not a real lifetime. Ignore, @@ -3274,7 +3274,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &self, lifetime_ref: &ast::Lifetime, outer_lifetime_ref: Option, - ) { + ) -> ErrorGuaranteed { debug_assert_ne!(lifetime_ref.ident.name, kw::UnderscoreLifetime); let mut err = if let Some(outer) = outer_lifetime_ref { struct_span_code_err!( @@ -3319,7 +3319,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ); } - err.emit(); + err.emit() } fn suggest_introducing_lifetime( @@ -3473,14 +3473,17 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } - pub(crate) fn emit_non_static_lt_in_const_param_ty_error(&self, lifetime_ref: &ast::Lifetime) { + pub(crate) fn emit_non_static_lt_in_const_param_ty_error( + &self, + lifetime_ref: &ast::Lifetime, + ) -> ErrorGuaranteed { self.r .dcx() .create_err(errors::ParamInTyOfConstParam { span: lifetime_ref.ident.span, name: lifetime_ref.ident.name, }) - .emit(); + .emit() } /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`. @@ -3490,18 +3493,17 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &self, cause: NoConstantGenericsReason, lifetime_ref: &ast::Lifetime, - ) { + ) -> ErrorGuaranteed { match cause { - NoConstantGenericsReason::IsEnumDiscriminant => { - self.r - .dcx() - .create_err(errors::ParamInEnumDiscriminant { - span: lifetime_ref.ident.span, - name: lifetime_ref.ident.name, - param_kind: errors::ParamKindInEnumDiscriminant::Lifetime, - }) - .emit(); - } + NoConstantGenericsReason::IsEnumDiscriminant => self + .r + .dcx() + .create_err(errors::ParamInEnumDiscriminant { + span: lifetime_ref.ident.span, + name: lifetime_ref.ident.name, + param_kind: errors::ParamKindInEnumDiscriminant::Lifetime, + }) + .emit(), NoConstantGenericsReason::NonTrivialConstArg => { assert!(!self.r.tcx.features().generic_const_exprs()); self.r @@ -3517,18 +3519,18 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .is_nightly_build() .then_some(errors::ParamInNonTrivialAnonConstHelp), }) - .emit(); + .emit() } } } - pub(crate) fn report_missing_lifetime_specifiers( + pub(crate) fn report_missing_lifetime_specifiers<'a>( &mut self, - lifetime_refs: Vec, + lifetime_refs: impl Clone + IntoIterator, function_param_lifetimes: Option<(Vec, Vec)>, ) -> ErrorGuaranteed { - let num_lifetimes: usize = lifetime_refs.iter().map(|lt| lt.count).sum(); - let spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect(); + let num_lifetimes: usize = lifetime_refs.clone().into_iter().map(|lt| lt.count).sum(); + let spans: Vec<_> = lifetime_refs.clone().into_iter().map(|lt| lt.span).collect(); let mut err = struct_span_code_err!( self.r.dcx(), @@ -3545,13 +3547,13 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.emit() } - fn add_missing_lifetime_specifiers_label( + fn add_missing_lifetime_specifiers_label<'a>( &mut self, err: &mut Diag<'_>, - lifetime_refs: Vec, + lifetime_refs: impl Clone + IntoIterator, function_param_lifetimes: Option<(Vec, Vec)>, ) { - for < in &lifetime_refs { + for < in lifetime_refs.clone() { err.span_label( lt.span, format!( @@ -3680,7 +3682,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { (lt.span.shrink_to_hi(), sugg) } }; - for < in &lifetime_refs { + for < in lifetime_refs.clone() { spans_suggs.push(build_sugg(lt)); } debug!(?spans_suggs); @@ -3708,7 +3710,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } 1 => { let post = if maybe_static { - let owned = if let [lt] = &lifetime_refs[..] + let mut lifetime_refs = lifetime_refs.clone().into_iter(); + let owned = if let Some(lt) = lifetime_refs.next() + && lifetime_refs.next().is_none() && lt.kind != MissingLifetimeKind::Ampersand { ", or if you will only have owned values" @@ -3733,7 +3737,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // we identified that the return expression references only one argument, we // would suggest borrowing only that argument, and we'd skip the prior // "use `'static`" suggestion entirely. - if let [lt] = &lifetime_refs[..] + let mut lifetime_refs = lifetime_refs.clone().into_iter(); + if let Some(lt) = lifetime_refs.next() + && lifetime_refs.next().is_none() && (lt.kind == MissingLifetimeKind::Ampersand || lt.kind == MissingLifetimeKind::Underscore) { @@ -4029,7 +4035,11 @@ fn mk_where_bound_predicate( } /// Report lifetime/lifetime shadowing as an error. -pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) { +pub(super) fn signal_lifetime_shadowing( + sess: &Session, + orig: Ident, + shadower: Ident, +) -> ErrorGuaranteed { struct_span_code_err!( sess.dcx(), shadower.span, @@ -4039,7 +4049,7 @@ pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: I ) .with_span_label(orig.span, "first declared here") .with_span_label(shadower.span, format!("lifetime `{}` already in scope", orig.name)) - .emit(); + .emit() } struct LifetimeFinder<'ast> { diff --git a/tests/ui/cast/ice-cast-type-with-error-124848.rs b/tests/ui/cast/ice-cast-type-with-error-124848.rs index 9b3732b02db43..0c623de8050b0 100644 --- a/tests/ui/cast/ice-cast-type-with-error-124848.rs +++ b/tests/ui/cast/ice-cast-type-with-error-124848.rs @@ -14,5 +14,4 @@ fn main() { let bad_addr = &unpinned as *const Cell>> as usize; //~^ ERROR use of undeclared lifetime name `'a` //~| ERROR use of undeclared lifetime name `'a` - //~| ERROR casting `&MyType<'_>` as `*const Cell>>` is invalid } diff --git a/tests/ui/cast/ice-cast-type-with-error-124848.stderr b/tests/ui/cast/ice-cast-type-with-error-124848.stderr index dff2277273248..665b0e0a0dd49 100644 --- a/tests/ui/cast/ice-cast-type-with-error-124848.stderr +++ b/tests/ui/cast/ice-cast-type-with-error-124848.stderr @@ -58,13 +58,7 @@ help: provide the argument LL | let mut unpinned = MyType(Cell::new(None), /* value */); | +++++++++++++ -error[E0606]: casting `&MyType<'_>` as `*const Cell>>` is invalid - --> $DIR/ice-cast-type-with-error-124848.rs:14:20 - | -LL | let bad_addr = &unpinned as *const Cell>> as usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0061, E0261, E0425, E0606. +Some errors have detailed explanations: E0061, E0261, E0425. For more information about an error, try `rustc --explain E0061`. diff --git a/tests/ui/closures/binder/implicit-stuff.rs b/tests/ui/closures/binder/implicit-stuff.rs index c976c200b0c8e..09e4c747afee8 100644 --- a/tests/ui/closures/binder/implicit-stuff.rs +++ b/tests/ui/closures/binder/implicit-stuff.rs @@ -24,5 +24,4 @@ fn main() { //~| ERROR `'_` cannot be used here let _ = for<'a> |x: &()| -> &'a () { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here let _ = for<'a> |x: &'a ()| -> &() { x }; //~ ERROR `&` without an explicit lifetime name cannot be used here - //~^ ERROR: lifetime may not live long enough } diff --git a/tests/ui/closures/binder/implicit-stuff.stderr b/tests/ui/closures/binder/implicit-stuff.stderr index 330a05a79bae3..cec2a60ba28c8 100644 --- a/tests/ui/closures/binder/implicit-stuff.stderr +++ b/tests/ui/closures/binder/implicit-stuff.stderr @@ -102,15 +102,6 @@ LL | let _ = for<'a> |x: &'a _, y, z: _| -> &'a _ { | | | `for<...>` is here -error: lifetime may not live long enough - --> $DIR/implicit-stuff.rs:26:42 - | -LL | let _ = for<'a> |x: &'a ()| -> &() { x }; - | -- - ^ returning this value requires that `'a` must outlive `'1` - | | | - | | let's call the lifetime of this reference `'1` - | lifetime `'a` defined here - -error: aborting due to 16 previous errors +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0637`. diff --git a/tests/ui/delegation/ice-line-bounds-issue-148732.rs b/tests/ui/delegation/ice-line-bounds-issue-148732.rs index e44c784760216..699e7d86f2581 100644 --- a/tests/ui/delegation/ice-line-bounds-issue-148732.rs +++ b/tests/ui/delegation/ice-line-bounds-issue-148732.rs @@ -3,7 +3,6 @@ reuse a as b { //~| ERROR functions delegation is not yet fully implemented dbg!(b); //~^ ERROR missing lifetime specifier - //~| ERROR `fn() {b}` doesn't implement `Debug` } fn main() {} diff --git a/tests/ui/delegation/ice-line-bounds-issue-148732.stderr b/tests/ui/delegation/ice-line-bounds-issue-148732.stderr index 83cc238b5e0c4..c4f261181b109 100644 --- a/tests/ui/delegation/ice-line-bounds-issue-148732.stderr +++ b/tests/ui/delegation/ice-line-bounds-issue-148732.stderr @@ -17,7 +17,7 @@ LL | / reuse a as b { LL | | LL | | LL | | dbg!(b); -... | +LL | | LL | | } | |_^ | @@ -25,18 +25,7 @@ LL | | } = help: add `#![feature(fn_delegation)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0277]: `fn() {b}` doesn't implement `Debug` - --> $DIR/ice-line-bounds-issue-148732.rs:4:5 - | -LL | reuse a as b { - | - consider calling this function -... -LL | dbg!(b); - | ^^^^^^^ the trait `Debug` is not implemented for fn item `fn() {b}` - | - = help: use parentheses to call this function: `b()` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0106, E0277, E0425, E0658. +Some errors have detailed explanations: E0106, E0425, E0658. For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/object-lifetime/undeclared-object-lifetime.rs b/tests/ui/object-lifetime/undeclared-object-lifetime.rs new file mode 100644 index 0000000000000..7c0e1100fe7bb --- /dev/null +++ b/tests/ui/object-lifetime/undeclared-object-lifetime.rs @@ -0,0 +1,7 @@ +//! E0228 (lifetime bound for trait object cannot be deduced from context) should not be emitted +//! when an undeclared lifetime bound has been specified. +//! +//! Regression test for https://github.com/rust-lang/rust/issues/152014 + +fn f(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {} //~ ERROR use of undeclared lifetime name `'undefined` +fn main() {} diff --git a/tests/ui/object-lifetime/undeclared-object-lifetime.stderr b/tests/ui/object-lifetime/undeclared-object-lifetime.stderr new file mode 100644 index 0000000000000..b6646a05420b3 --- /dev/null +++ b/tests/ui/object-lifetime/undeclared-object-lifetime.stderr @@ -0,0 +1,14 @@ +error[E0261]: use of undeclared lifetime name `'undefined` + --> $DIR/undeclared-object-lifetime.rs:6:24 + | +LL | fn f(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {} + | ^^^^^^^^^^ undeclared lifetime + | +help: consider introducing lifetime `'undefined` here + | +LL | fn f<'undefined>(_: std::cell::Ref<'undefined, dyn std::fmt::Debug>) {} + | ++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0261`. diff --git a/tests/ui/rfcs/rfc-1623-static/rfc1623-3.rs b/tests/ui/rfcs/rfc-1623-static/rfc1623-3.rs index 26fa6fdb57f95..35a2ef10c2e3c 100644 --- a/tests/ui/rfcs/rfc-1623-static/rfc1623-3.rs +++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-3.rs @@ -9,6 +9,5 @@ static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = //~^ ERROR missing lifetime specifier [E0106] &(non_elidable as fn(&u8, &u8) -> &u8); //~^ ERROR missing lifetime specifier [E0106] - //~| ERROR non-primitive cast fn main() {} diff --git a/tests/ui/rfcs/rfc-1623-static/rfc1623-3.stderr b/tests/ui/rfcs/rfc-1623-static/rfc1623-3.stderr index 77fc3f0412ebf..05ea6e44486fd 100644 --- a/tests/ui/rfcs/rfc-1623-static/rfc1623-3.stderr +++ b/tests/ui/rfcs/rfc-1623-static/rfc1623-3.stderr @@ -23,13 +23,6 @@ help: consider making the type lifetime-generic with a new `'a` lifetime LL | &(non_elidable as for<'a> fn(&'a u8, &'a u8) -> &'a u8); | +++++++ ++ ++ ++ -error[E0605]: non-primitive cast: `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8 {non_elidable}` as `for<'a, 'b> fn(&'a u8, &'b u8) -> &u8` - --> $DIR/rfc1623-3.rs:10:6 - | -LL | &(non_elidable as fn(&u8, &u8) -> &u8); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0106, E0605. -For more information about an error, try `rustc --explain E0106`. +For more information about this error, try `rustc --explain E0106`.