diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2883299291e..c21afa26f4f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1353,12 +1353,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), ); - let (lifetimes_in_bounds, binders_to_ignore) = - lifetime_collector::lifetimes_in_bounds(bounds); + let lifetimes_in_bounds = + lifetime_collector::lifetimes_in_bounds(&lctx.resolver, bounds); debug!(?lifetimes_in_bounds); - debug!(?binders_to_ignore); - lctx.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore); + lctx.create_and_capture_lifetime_defs(&lifetimes_in_bounds); let ret = lctx.lower_param_bounds(bounds, itctx); @@ -1447,11 +1446,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item)) } - fn create_and_capture_lifetime_defs( - &mut self, - lifetimes_in_bounds: &[&Lifetime], - binders_to_ignore: &FxHashMap>, - ) { + fn create_and_capture_lifetime_defs(&mut self, lifetimes_in_bounds: &[&Lifetime]) { for lifetime in lifetimes_in_bounds { let ident = lifetime.ident; let span = ident.span; @@ -1461,53 +1456,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() { match res { - LifetimeRes::Param { param, binder } => { - if !binders_to_ignore - .get(&lifetime.id) - .unwrap_or(&Vec::new()) - .contains(&binder) - { - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(_) => {} - Entry::Vacant(v) => { - let node_id = self.next_node_id(); - let name = ParamName::Plain(ident); + LifetimeRes::Param { param, binder: _ } => { + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(_) => {} + Entry::Vacant(v) => { + let node_id = self.next_node_id(); + let name = ParamName::Plain(ident); - self.create_def( - captured_lifetimes.parent_def_id, - node_id, - DefPathData::LifetimeNs(name.ident().name), - ); + self.create_def( + captured_lifetimes.parent_def_id, + node_id, + DefPathData::LifetimeNs(name.ident().name), + ); - v.insert((span, node_id, name, res)); - } + v.insert((span, node_id, name, res)); } } } - LifetimeRes::Fresh { param, binder } => { + LifetimeRes::Fresh { param, binder: _ } => { debug_assert_eq!(ident.name, kw::UnderscoreLifetime); - if !binders_to_ignore - .get(&lifetime.id) - .unwrap_or(&Vec::new()) - .contains(&binder) - { - let param = self.local_def_id(param); - match captured_lifetimes.captures.entry(param) { - Entry::Occupied(_) => {} - Entry::Vacant(v) => { - let node_id = self.next_node_id(); + let param = self.local_def_id(param); + match captured_lifetimes.captures.entry(param) { + Entry::Occupied(_) => {} + Entry::Vacant(v) => { + let node_id = self.next_node_id(); - let name = ParamName::Fresh; + let name = ParamName::Fresh; - self.create_def( - captured_lifetimes.parent_def_id, - node_id, - DefPathData::LifetimeNs(kw::UnderscoreLifetime), - ); + self.create_def( + captured_lifetimes.parent_def_id, + node_id, + DefPathData::LifetimeNs(kw::UnderscoreLifetime), + ); - v.insert((span, node_id, name, res)); - } + v.insert((span, node_id, name, res)); } } } @@ -1758,12 +1741,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }), ); - let (lifetimes_in_bounds, binders_to_ignore) = - lifetime_collector::lifetimes_in_ret_ty(output); + let lifetimes_in_bounds = + lifetime_collector::lifetimes_in_ret_ty(&this.resolver, output); debug!(?lifetimes_in_bounds); - debug!(?binders_to_ignore); - this.create_and_capture_lifetime_defs(&lifetimes_in_bounds, &binders_to_ignore); + this.create_and_capture_lifetime_defs(&lifetimes_in_bounds); // We have to be careful to get elision right here. The // idea is that we create a lifetime parameter for each diff --git a/compiler/rustc_ast_lowering/src/lifetime_collector.rs b/compiler/rustc_ast_lowering/src/lifetime_collector.rs index 1dab8799ae5..f67cbd69e47 100644 --- a/compiler/rustc_ast_lowering/src/lifetime_collector.rs +++ b/compiler/rustc_ast_lowering/src/lifetime_collector.rs @@ -1,21 +1,32 @@ +use super::ResolverAstLoweringExt; use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor}; use rustc_ast::{ FnRetTy, GenericBounds, Lifetime, NodeId, PolyTraitRef, TraitBoundModifier, Ty, TyKind, }; -use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def::LifetimeRes; +use rustc_middle::ty::ResolverAstLowering; -struct LifetimeCollectVisitor<'ast> { +struct LifetimeCollectVisitor<'this, 'ast: 'this> { + resolver: &'this ResolverAstLowering, current_binders: Vec, - binders_to_ignore: FxHashMap>, collected_lifetimes: Vec<&'ast Lifetime>, } -impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { +impl<'this, 'ast: 'this> LifetimeCollectVisitor<'this, 'ast> { + fn new(resolver: &'this ResolverAstLowering) -> Self { + Self { resolver, current_binders: Vec::new(), collected_lifetimes: Vec::new() } + } +} + +impl<'this, 'ast: 'this> Visitor<'ast> for LifetimeCollectVisitor<'this, 'ast> { fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) { - if !self.collected_lifetimes.contains(&lifetime) { - self.collected_lifetimes.push(lifetime); + let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error); + + if res.binder().map_or(true, |b| !self.current_binders.contains(&b)) { + if !self.collected_lifetimes.contains(&lifetime) { + self.collected_lifetimes.push(lifetime); + } } - self.binders_to_ignore.insert(lifetime.id, self.current_binders.clone()); } fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { @@ -37,26 +48,22 @@ impl<'ast> Visitor<'ast> for LifetimeCollectVisitor<'ast> { } } -pub fn lifetimes_in_ret_ty(ret_ty: &FnRetTy) -> (Vec<&Lifetime>, FxHashMap>) { - let mut visitor = LifetimeCollectVisitor { - current_binders: Vec::new(), - binders_to_ignore: FxHashMap::default(), - collected_lifetimes: Vec::new(), - }; +pub fn lifetimes_in_ret_ty<'this, 'ast: 'this>( + resolver: &'this ResolverAstLowering, + ret_ty: &'ast FnRetTy, +) -> Vec<&'ast Lifetime> { + let mut visitor = LifetimeCollectVisitor::new(resolver); visitor.visit_fn_ret_ty(ret_ty); - (visitor.collected_lifetimes, visitor.binders_to_ignore) + visitor.collected_lifetimes } -pub fn lifetimes_in_bounds( - bounds: &GenericBounds, -) -> (Vec<&Lifetime>, FxHashMap>) { - let mut visitor = LifetimeCollectVisitor { - current_binders: Vec::new(), - binders_to_ignore: FxHashMap::default(), - collected_lifetimes: Vec::new(), - }; +pub fn lifetimes_in_bounds<'this, 'ast: 'this>( + resolver: &'this ResolverAstLowering, + bounds: &'ast GenericBounds, +) -> Vec<&'ast Lifetime> { + let mut visitor = LifetimeCollectVisitor::new(resolver); for bound in bounds { visitor.visit_param_bound(bound, BoundKind::Bound); } - (visitor.collected_lifetimes, visitor.binders_to_ignore) + visitor.collected_lifetimes } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index be5b7eccbaf..2a89947f927 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -747,3 +747,12 @@ pub enum LifetimeRes { /// HACK: This is used to recover the NodeId of an elided lifetime. ElidedAnchor { start: NodeId, end: NodeId }, } + +impl LifetimeRes { + pub fn binder(&self) -> Option { + match self { + LifetimeRes::Param { binder, .. } | LifetimeRes::Fresh { binder, .. } => Some(*binder), + _ => None, + } + } +}