Skip to content

Commit a22130e

Browse files
committed
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 386838d commit a22130e

File tree

1 file changed

+45
-19
lines changed

1 file changed

+45
-19
lines changed

compiler/rustc_resolve/src/late.rs

+45-19
Original file line numberDiff line numberDiff line change
@@ -2162,16 +2162,55 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
21622162

21632163
/// List all the lifetimes that appear in the provided type.
21642164
fn find_lifetime_for_self(&self, ty: &'ast Ty) -> Set1<LifetimeRes> {
2165-
struct SelfVisitor<'r, 'a, 'tcx> {
2165+
/// Visits a type to find all the &references, and determines the
2166+
/// set of lifetimes for all of those references where the referent
2167+
/// contains Self.
2168+
struct FindReferenceVisitor<'r, 'a, 'tcx> {
21662169
r: &'r Resolver<'a, 'tcx>,
21672170
impl_self: Option<Res>,
21682171
lifetime: Set1<LifetimeRes>,
2172+
}
2173+
2174+
impl<'a> Visitor<'a> for FindReferenceVisitor<'_, '_, '_> {
2175+
fn visit_ty(&mut self, ty: &'a Ty) {
2176+
trace!("FindReferenceVisitor considering ty={:?}", ty);
2177+
if let TyKind::Ref(lt, _) = ty.kind {
2178+
// See if anything inside the &thing contains Self
2179+
let mut visitor =
2180+
SelfVisitor { r: self.r, impl_self: self.impl_self, self_found: false };
2181+
visitor.visit_ty(ty);
2182+
trace!("FindReferenceVisitor: SelfVisitor self_found={:?}", visitor.self_found);
2183+
if visitor.self_found {
2184+
let lt_id = if let Some(lt) = lt {
2185+
lt.id
2186+
} else {
2187+
let res = self.r.lifetimes_res_map[&ty.id];
2188+
let LifetimeRes::ElidedAnchor { start, .. } = res else { bug!() };
2189+
start
2190+
};
2191+
let lt_res = self.r.lifetimes_res_map[&lt_id];
2192+
trace!("FindReferenceVisitor inserting res={:?}", lt_res);
2193+
self.lifetime.insert(lt_res);
2194+
}
2195+
}
2196+
visit::walk_ty(self, ty)
2197+
}
2198+
2199+
// A type may have an expression as a const generic argument.
2200+
// We do not want to recurse into those.
2201+
fn visit_expr(&mut self, _: &'a Expr) {}
2202+
}
2203+
2204+
/// Visitor which checks the referent of a &Thing to see if the
2205+
/// Thing contains Self
2206+
struct SelfVisitor<'r, 'a, 'tcx> {
2207+
r: &'r Resolver<'a, 'tcx>,
2208+
impl_self: Option<Res>,
21692209
self_found: bool,
21702210
}
21712211

21722212
impl SelfVisitor<'_, '_, '_> {
2173-
// Look for `self: &'a Self` - also desugared from `&'a self`,
2174-
// and if that matches, use it for elision and return early.
2213+
// Look for `self: &'a Self` - also desugared from `&'a self`
21752214
fn is_self_ty(&self, ty: &Ty) -> bool {
21762215
match ty.kind {
21772216
TyKind::ImplicitSelf => true,
@@ -2194,18 +2233,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
21942233
trace!("SelfVisitor found Self");
21952234
self.self_found = true;
21962235
}
2197-
if let TyKind::Ref(lt, _) = ty.kind {
2198-
let lt_id = if let Some(lt) = lt {
2199-
lt.id
2200-
} else {
2201-
let res = self.r.lifetimes_res_map[&ty.id];
2202-
let LifetimeRes::ElidedAnchor { start, .. } = res else { bug!() };
2203-
start
2204-
};
2205-
let lt_res = self.r.lifetimes_res_map[&lt_id];
2206-
trace!("SelfVisitor inserting res={:?}", lt_res);
2207-
self.lifetime.insert(lt_res);
2208-
}
22092236
visit::walk_ty(self, ty)
22102237
}
22112238

@@ -2235,11 +2262,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
22352262
Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum, _,) | Res::PrimTy(_)
22362263
)
22372264
});
2238-
let mut visitor =
2239-
SelfVisitor { r: self.r, impl_self, lifetime: Set1::Empty, self_found: false };
2265+
let mut visitor = FindReferenceVisitor { r: self.r, impl_self, lifetime: Set1::Empty };
22402266
visitor.visit_ty(ty);
2241-
trace!("SelfVisitor found={:?}, self_found={:?}", visitor.lifetime, visitor.self_found);
2242-
if visitor.self_found { visitor.lifetime } else { Set1::Empty }
2267+
trace!("FindReferenceVisitor found={:?}", visitor.lifetime);
2268+
visitor.lifetime
22432269
}
22442270

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

0 commit comments

Comments
 (0)