Skip to content

Commit 4564971

Browse files
adetaylorx420
authored andcommitted
Elision: consider lifetimes from &T iff T has Self
Change the algorithm which determines whether a self lifetime can be used for return type lifetime elision, such that we consider lifetimes attached to any reference in the self type, so long as Self can be found anywhere inside the type of that reference.
1 parent 5039ae8 commit 4564971

File tree

1 file changed

+45
-19
lines changed

1 file changed

+45
-19
lines changed

compiler/rustc_resolve/src/late.rs

Lines changed: 45 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2205,16 +2205,55 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
22052205

22062206
/// List all the lifetimes that appear in the provided type.
22072207
fn find_lifetime_for_self(&self, ty: &'ast Ty) -> Set1<LifetimeRes> {
2208-
struct SelfVisitor<'r, 'a, 'tcx> {
2208+
/// Visits a type to find all the &references, and determines the
2209+
/// set of lifetimes for all of those references where the referent
2210+
/// contains Self.
2211+
struct FindReferenceVisitor<'r, 'a, 'tcx> {
22092212
r: &'r Resolver<'a, 'tcx>,
22102213
impl_self: Option<Res>,
22112214
lifetime: Set1<LifetimeRes>,
2215+
}
2216+
2217+
impl<'a> Visitor<'a> for FindReferenceVisitor<'_, '_, '_> {
2218+
fn visit_ty(&mut self, ty: &'a Ty) {
2219+
trace!("FindReferenceVisitor considering ty={:?}", ty);
2220+
if let TyKind::Ref(lt, _) = ty.kind {
2221+
// See if anything inside the &thing contains Self
2222+
let mut visitor =
2223+
SelfVisitor { r: self.r, impl_self: self.impl_self, self_found: false };
2224+
visitor.visit_ty(ty);
2225+
trace!("FindReferenceVisitor: SelfVisitor self_found={:?}", visitor.self_found);
2226+
if visitor.self_found {
2227+
let lt_id = if let Some(lt) = lt {
2228+
lt.id
2229+
} else {
2230+
let res = self.r.lifetimes_res_map[&ty.id];
2231+
let LifetimeRes::ElidedAnchor { start, .. } = res else { bug!() };
2232+
start
2233+
};
2234+
let lt_res = self.r.lifetimes_res_map[&lt_id];
2235+
trace!("FindReferenceVisitor inserting res={:?}", lt_res);
2236+
self.lifetime.insert(lt_res);
2237+
}
2238+
}
2239+
visit::walk_ty(self, ty)
2240+
}
2241+
2242+
// A type may have an expression as a const generic argument.
2243+
// We do not want to recurse into those.
2244+
fn visit_expr(&mut self, _: &'a Expr) {}
2245+
}
2246+
2247+
/// Visitor which checks the referent of a &Thing to see if the
2248+
/// Thing contains Self
2249+
struct SelfVisitor<'r, 'a, 'tcx> {
2250+
r: &'r Resolver<'a, 'tcx>,
2251+
impl_self: Option<Res>,
22122252
self_found: bool,
22132253
}
22142254

22152255
impl SelfVisitor<'_, '_, '_> {
2216-
// Look for `self: &'a Self` - also desugared from `&'a self`,
2217-
// and if that matches, use it for elision and return early.
2256+
// Look for `self: &'a Self` - also desugared from `&'a self`
22182257
fn is_self_ty(&self, ty: &Ty) -> bool {
22192258
match ty.kind {
22202259
TyKind::ImplicitSelf => true,
@@ -2237,18 +2276,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
22372276
trace!("SelfVisitor found Self");
22382277
self.self_found = true;
22392278
}
2240-
if let TyKind::Ref(lt, _) = ty.kind {
2241-
let lt_id = if let Some(lt) = lt {
2242-
lt.id
2243-
} else {
2244-
let res = self.r.lifetimes_res_map[&ty.id];
2245-
let LifetimeRes::ElidedAnchor { start, .. } = res else { bug!() };
2246-
start
2247-
};
2248-
let lt_res = self.r.lifetimes_res_map[&lt_id];
2249-
trace!("SelfVisitor inserting res={:?}", lt_res);
2250-
self.lifetime.insert(lt_res);
2251-
}
22522279
visit::walk_ty(self, ty)
22532280
}
22542281

@@ -2278,11 +2305,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
22782305
Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum, _,) | Res::PrimTy(_)
22792306
)
22802307
});
2281-
let mut visitor =
2282-
SelfVisitor { r: self.r, impl_self, lifetime: Set1::Empty, self_found: false };
2308+
let mut visitor = FindReferenceVisitor { r: self.r, impl_self, lifetime: Set1::Empty };
22832309
visitor.visit_ty(ty);
2284-
trace!("SelfVisitor found={:?}, self_found={:?}", visitor.lifetime, visitor.self_found);
2285-
if visitor.self_found { visitor.lifetime } else { Set1::Empty }
2310+
trace!("FindReferenceVisitor found={:?}", visitor.lifetime);
2311+
visitor.lifetime
22862312
}
22872313

22882314
/// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved

0 commit comments

Comments
 (0)