Auto merge of #121587 - ShoyuVanilla:fix-issue-121267, r=TaKO8Ki
Fix bad span for explicit lifetime suggestions
Fixes #121267
Current explicit lifetime suggestions are not showing correct spans for some lifetimes - e.g. elided lifetime generic parameters;
This should be done correctly regarding elided lifetime kind like the following code
43fdd4916d/compiler/rustc_resolve/src/late/diagnostics.rs (L3015-L3044)
This commit is contained in:
commit
6e1f7b538a
11 changed files with 167 additions and 83 deletions
|
@ -22,7 +22,7 @@ use rustc_errors::{
|
|||
use rustc_hir::def::Namespace::{self, *};
|
||||
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
|
||||
use rustc_hir::{PrimTy, TraitCandidate};
|
||||
use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
|
||||
use rustc_middle::middle::resolve_bound_vars::Set1;
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::config::{CrateType, ResolveDocLinks};
|
||||
|
@ -44,9 +44,7 @@ type Res = def::Res<NodeId>;
|
|||
|
||||
type IdentMap<T> = FxHashMap<Ident, T>;
|
||||
|
||||
use diagnostics::{
|
||||
ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime, MissingLifetimeKind,
|
||||
};
|
||||
use diagnostics::{ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct BindingInfo {
|
||||
|
@ -1637,22 +1635,16 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
fn resolve_anonymous_lifetime(&mut self, lifetime: &Lifetime, elided: bool) {
|
||||
debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);
|
||||
|
||||
let missing_lifetime = MissingLifetime {
|
||||
id: lifetime.id,
|
||||
span: lifetime.ident.span,
|
||||
kind: if elided {
|
||||
MissingLifetimeKind::Ampersand
|
||||
} else {
|
||||
MissingLifetimeKind::Underscore
|
||||
},
|
||||
count: 1,
|
||||
};
|
||||
let kind =
|
||||
if elided { MissingLifetimeKind::Ampersand } else { MissingLifetimeKind::Underscore };
|
||||
let missing_lifetime =
|
||||
MissingLifetime { id: lifetime.id, span: lifetime.ident.span, kind, count: 1 };
|
||||
let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
|
||||
for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() {
|
||||
debug!(?rib.kind);
|
||||
match rib.kind {
|
||||
LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
|
||||
let res = self.create_fresh_lifetime(lifetime.ident, binder);
|
||||
let res = self.create_fresh_lifetime(lifetime.ident, binder, kind);
|
||||
self.record_lifetime_res(lifetime.id, res, elision_candidate);
|
||||
return;
|
||||
}
|
||||
|
@ -1744,13 +1736,18 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self))]
|
||||
fn create_fresh_lifetime(&mut self, ident: Ident, binder: NodeId) -> LifetimeRes {
|
||||
fn create_fresh_lifetime(
|
||||
&mut self,
|
||||
ident: Ident,
|
||||
binder: NodeId,
|
||||
kind: MissingLifetimeKind,
|
||||
) -> LifetimeRes {
|
||||
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
|
||||
debug!(?ident.span);
|
||||
|
||||
// Leave the responsibility to create the `LocalDefId` to lowering.
|
||||
let param = self.r.next_node_id();
|
||||
let res = LifetimeRes::Fresh { param, binder };
|
||||
let res = LifetimeRes::Fresh { param, binder, kind };
|
||||
self.record_lifetime_param(param, res);
|
||||
|
||||
// Record the created lifetime parameter so lowering can pick it up and add it to HIR.
|
||||
|
@ -1844,14 +1841,15 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
};
|
||||
let ident = Ident::new(kw::UnderscoreLifetime, elided_lifetime_span);
|
||||
|
||||
let kind = if segment.has_generic_args {
|
||||
MissingLifetimeKind::Comma
|
||||
} else {
|
||||
MissingLifetimeKind::Brackets
|
||||
};
|
||||
let missing_lifetime = MissingLifetime {
|
||||
id: node_ids.start,
|
||||
span: elided_lifetime_span,
|
||||
kind: if segment.has_generic_args {
|
||||
MissingLifetimeKind::Comma
|
||||
} else {
|
||||
MissingLifetimeKind::Brackets
|
||||
},
|
||||
kind,
|
||||
count: expected_lifetimes,
|
||||
};
|
||||
let mut should_lint = true;
|
||||
|
@ -1897,7 +1895,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
|||
// Group all suggestions into the first record.
|
||||
let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
|
||||
for id in node_ids {
|
||||
let res = self.create_fresh_lifetime(ident, binder);
|
||||
let res = self.create_fresh_lifetime(ident, binder, kind);
|
||||
self.record_lifetime_res(
|
||||
id,
|
||||
res,
|
||||
|
|
|
@ -24,7 +24,7 @@ use rustc_errors::{
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
|
||||
use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
|
||||
use rustc_hir::PrimTy;
|
||||
use rustc_hir::{MissingLifetimeKind, PrimTy};
|
||||
use rustc_session::lint;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::edit_distance::find_best_match_for_name;
|
||||
|
@ -109,18 +109,6 @@ pub(super) struct MissingLifetime {
|
|||
pub count: usize,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
pub(super) enum MissingLifetimeKind {
|
||||
/// An explicit `'_`.
|
||||
Underscore,
|
||||
/// An elided lifetime `&' ty`.
|
||||
Ampersand,
|
||||
/// An elided lifetime in brackets with written brackets.
|
||||
Comma,
|
||||
/// An elided lifetime with elided brackets.
|
||||
Brackets,
|
||||
}
|
||||
|
||||
/// Description of the lifetimes appearing in a function parameter.
|
||||
/// This is used to provide a literal explanation to the elision failure.
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue