Lint elided lifetimes in path during lifetime resolution.
This commit is contained in:
parent
ac03470c3b
commit
5ea7ea8a57
13 changed files with 181 additions and 78 deletions
|
@ -1950,6 +1950,41 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
crate fn report_elided_lifetime_in_ty(&self, lifetime_refs: &[&hir::Lifetime]) {
|
||||
let missing_lifetimes = lifetime_refs
|
||||
.iter()
|
||||
.filter(|a| matches!(a, hir::Lifetime { name: hir::LifetimeName::ImplicitMissing, .. }))
|
||||
.count();
|
||||
|
||||
if missing_lifetimes > 0 {
|
||||
let mut spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect();
|
||||
spans.sort();
|
||||
let mut spans_dedup = spans.clone();
|
||||
spans_dedup.dedup();
|
||||
let spans_with_counts: Vec<_> = spans_dedup
|
||||
.into_iter()
|
||||
.map(|sp| (sp, spans.iter().filter(|nsp| *nsp == &sp).count()))
|
||||
.collect();
|
||||
|
||||
self.tcx.struct_span_lint_hir(
|
||||
rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
|
||||
hir::CRATE_HIR_ID,
|
||||
spans,
|
||||
|lint| {
|
||||
let mut db = lint.build("hidden lifetime parameters in types are deprecated");
|
||||
self.add_missing_lifetime_specifiers_label(
|
||||
&mut db,
|
||||
spans_with_counts,
|
||||
&FxHashSet::from_iter([kw::UnderscoreLifetime]),
|
||||
Vec::new(),
|
||||
&[],
|
||||
);
|
||||
db.emit()
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(const_generics): This patches over an ICE caused by non-'static lifetimes in const
|
||||
// generics. We are disallowing this until we can decide on how we want to handle non-'static
|
||||
// lifetimes in const generics. See issue #74052 for discussion.
|
||||
|
@ -2376,7 +2411,10 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
|
|||
);
|
||||
let is_allowed_lifetime = matches!(
|
||||
lifetime_ref.name,
|
||||
hir::LifetimeName::Implicit | hir::LifetimeName::Static | hir::LifetimeName::Underscore
|
||||
hir::LifetimeName::Implicit
|
||||
| hir::LifetimeName::ImplicitMissing
|
||||
| hir::LifetimeName::Static
|
||||
| hir::LifetimeName::Underscore
|
||||
);
|
||||
|
||||
if !self.tcx.lazy_normalization() && is_anon_const && !is_allowed_lifetime {
|
||||
|
|
|
@ -923,7 +923,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
}
|
||||
});
|
||||
match lifetime.name {
|
||||
LifetimeName::Implicit => {
|
||||
LifetimeName::Implicit | hir::LifetimeName::ImplicitMissing => {
|
||||
// For types like `dyn Foo`, we should
|
||||
// generate a special form of elided.
|
||||
span_bug!(ty.span, "object-lifetime-default expected, not implicit",);
|
||||
|
@ -3057,9 +3057,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
let error = loop {
|
||||
match *scope {
|
||||
// Do not assign any resolution, it will be inferred.
|
||||
Scope::Body { .. } => return,
|
||||
Scope::Body { .. } => break Ok(()),
|
||||
|
||||
Scope::Root => break None,
|
||||
Scope::Root => break Err(None),
|
||||
|
||||
Scope::Binder { s, ref lifetimes, scope_type, .. } => {
|
||||
// collect named lifetimes for suggestions
|
||||
|
@ -3086,7 +3086,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
|
||||
self.insert_lifetime(lifetime_ref, lifetime);
|
||||
}
|
||||
return;
|
||||
break Ok(());
|
||||
}
|
||||
|
||||
Scope::Elision { elide: Elide::Exact(l), .. } => {
|
||||
|
@ -3094,7 +3094,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
for lifetime_ref in lifetime_refs {
|
||||
self.insert_lifetime(lifetime_ref, lifetime);
|
||||
}
|
||||
return;
|
||||
break Ok(());
|
||||
}
|
||||
|
||||
Scope::Elision { elide: Elide::Error(ref e), ref s, .. } => {
|
||||
|
@ -3119,10 +3119,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
_ => break,
|
||||
}
|
||||
}
|
||||
break Some(&e[..]);
|
||||
break Err(Some(&e[..]));
|
||||
}
|
||||
|
||||
Scope::Elision { elide: Elide::Forbid, .. } => break None,
|
||||
Scope::Elision { elide: Elide::Forbid, .. } => break Err(None),
|
||||
|
||||
Scope::ObjectLifetimeDefault { s, .. }
|
||||
| Scope::Supertrait { s, .. }
|
||||
|
@ -3132,6 +3132,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
let error = match error {
|
||||
Ok(()) => {
|
||||
self.report_elided_lifetime_in_ty(lifetime_refs);
|
||||
return;
|
||||
}
|
||||
Err(error) => error,
|
||||
};
|
||||
|
||||
// If we specifically need the `scope_for_path` map, then we're in the
|
||||
// diagnostic pass and we don't want to emit more errors.
|
||||
if self.map.scope_for_path.is_some() {
|
||||
|
@ -3274,7 +3282,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
))
|
||||
.emit();
|
||||
}
|
||||
hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => {
|
||||
hir::LifetimeName::Param(_)
|
||||
| hir::LifetimeName::Implicit
|
||||
| hir::LifetimeName::ImplicitMissing => {
|
||||
self.resolve_lifetime_ref(lt);
|
||||
}
|
||||
hir::LifetimeName::ImplicitObjectLifetimeDefault => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue