Feed ErrorGuaranteed from late lifetime resolution to RBV

If late lifetime resolution fails for whatever reason, forward to RBV
the guarantee that an error was emitted - thereby eliminating the need
for a "hack" to suppress subsequent/superfluous error diagnostics.
This commit is contained in:
Alan Egerton 2026-02-03 23:34:42 +00:00
parent 47611e1604
commit c43a33eec7
No known key found for this signature in database
GPG key ID: 3D7EA7527916B438
17 changed files with 184 additions and 161 deletions

View file

@ -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,26 +1931,29 @@ 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 = if let Some(res) = self.resolver.get_lifetime_res(id) {
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);
}
}
} else {
hir::LifetimeKind::Error(self.dcx().span_delayed_bug(ident.span, "unresolved lifetime"))
};
debug!(?res);
@ -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 };

View file

@ -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 },
}

View file

@ -238,7 +238,7 @@ pub enum LifetimeKind {
/// Indicates an error during lowering (usually `'_` in wrong place)
/// that was already reported.
Error,
Error(ErrorGuaranteed),
/// User wrote an anonymous lifetime, either `'_` or nothing (which gets
/// converted to `'_`). The semantics of this lifetime should be inferred
@ -258,7 +258,7 @@ 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::Param(..) | LifetimeKind::Static => false,
}
}
}

View file

@ -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::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(..) => {}
}
}
hir::TyKind::Ref(lifetime_ref, ref mt) => {
@ -891,8 +891,10 @@ 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 => {}
// 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 => {}
}

View file

@ -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(span.shrink_to_hi())
}
RegionInferReason::ObjectLifetimeDefault(span.shrink_to_hi())
} else {
RegionInferReason::ExplicitObjectLifetime
};

View file

@ -9,13 +9,14 @@
use std::borrow::Cow;
use std::collections::hash_map::Entry;
use std::mem::{replace, swap, take};
use std::ops::ControlFlow;
use std::ops::{ControlFlow, Range};
use rustc_ast::visit::{
AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, try_visit, visit_opt, walk_list,
};
use rustc_ast::*;
use rustc_data_structures::debug_assert_matches;
use rustc_data_structures::either::Either;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::codes::*;
@ -746,7 +747,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<MissingLifetime>,
current_elision_failures:
Vec<(MissingLifetime, LifetimeElisionCandidate, Either<NodeId, Range<NodeId>>)>,
}
struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
@ -1782,19 +1784,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 +1814,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 +1884,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 +1916,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 +1946,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 +1971,11 @@ 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,
Either::Left(lifetime.id),
));
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,11 @@ 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,
Either::Right(node_ids),
));
break;
}
// `LifetimeRes::Error`, which would usually be used in the case of
@ -2278,14 +2289,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 +2341,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 +2385,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, nodes) in elision_failures {
match nodes {
Either::Left(node_id) => record_res(node_id, candidate),
Either::Right(node_ids) => {
for lifetime in node_ids {
record_res(lifetime, candidate)
}
}
}
}
}
});
}
@ -3025,9 +3053,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;
}
@ -3035,11 +3067,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,
@ -3068,22 +3100,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;
}

View file

@ -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<Ident>,
) {
) -> 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
@ -3512,18 +3514,18 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
param_kind: errors::ParamKindInNonTrivialAnonConst::Lifetime,
help: self.r.tcx.sess.is_nightly_build(),
})
.emit();
.emit()
}
}
}
pub(crate) fn report_missing_lifetime_specifiers(
pub(crate) fn report_missing_lifetime_specifiers<'a>(
&mut self,
lifetime_refs: Vec<MissingLifetime>,
lifetime_refs: impl Clone + IntoIterator<Item = &'a MissingLifetime>,
function_param_lifetimes: Option<(Vec<MissingLifetime>, Vec<ElisionFnParameter>)>,
) -> 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(),
@ -3540,13 +3542,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<MissingLifetime>,
lifetime_refs: impl Clone + IntoIterator<Item = &'a MissingLifetime>,
function_param_lifetimes: Option<(Vec<MissingLifetime>, Vec<ElisionFnParameter>)>,
) {
for &lt in &lifetime_refs {
for &lt in lifetime_refs.clone() {
err.span_label(
lt.span,
format!(
@ -3675,7 +3677,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
(lt.span.shrink_to_hi(), sugg)
}
};
for &lt in &lifetime_refs {
for &lt in lifetime_refs.clone() {
spans_suggs.push(build_sugg(lt));
}
debug!(?spans_suggs);
@ -3703,7 +3705,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"
@ -3728,7 +3732,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)
{
@ -4024,7 +4030,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,
@ -4034,7 +4044,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> {

View file

@ -14,5 +14,4 @@ fn main() {
let bad_addr = &unpinned as *const Cell<Option<&'a mut MyType<'a>>> as usize;
//~^ ERROR use of undeclared lifetime name `'a`
//~| ERROR use of undeclared lifetime name `'a`
//~| ERROR casting `&MyType<'_>` as `*const Cell<Option<&mut MyType<'_>>>` is invalid
}

View file

@ -58,13 +58,7 @@ help: provide the argument
LL | let mut unpinned = MyType(Cell::new(None), /* value */);
| +++++++++++++
error[E0606]: casting `&MyType<'_>` as `*const Cell<Option<&mut MyType<'_>>>` is invalid
--> $DIR/ice-cast-type-with-error-124848.rs:14:20
|
LL | let bad_addr = &unpinned as *const Cell<Option<&'a mut MyType<'a>>> as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 5 previous errors
error: aborting due to 6 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`.

View file

@ -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
}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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 3 previous errors
error: aborting due to 4 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`.

View file

@ -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() {}

View file

@ -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`.

View file

@ -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() {}

View file

@ -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 2 previous errors
error: aborting due to 3 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`.