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:
parent
47611e1604
commit
c43a33eec7
17 changed files with 184 additions and 161 deletions
|
|
@ -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 };
|
||||
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 < in &lifetime_refs {
|
||||
for < 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 < in &lifetime_refs {
|
||||
for < 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> {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
7
tests/ui/object-lifetime/undeclared-object-lifetime.rs
Normal file
7
tests/ui/object-lifetime/undeclared-object-lifetime.rs
Normal 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() {}
|
||||
14
tests/ui/object-lifetime/undeclared-object-lifetime.stderr
Normal file
14
tests/ui/object-lifetime/undeclared-object-lifetime.stderr
Normal 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`.
|
||||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue