Skip lifetimes in binders when visiting
This commit is contained in:
parent
4f334f2b97
commit
05b989e16e
3 changed files with 71 additions and 73 deletions
|
@ -1353,12 +1353,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
let (lifetimes_in_bounds, binders_to_ignore) =
|
let lifetimes_in_bounds =
|
||||||
lifetime_collector::lifetimes_in_bounds(bounds);
|
lifetime_collector::lifetimes_in_bounds(&lctx.resolver, bounds);
|
||||||
debug!(?lifetimes_in_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);
|
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))
|
hir::OwnerNode::Item(self.arena.alloc(opaque_ty_item))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_and_capture_lifetime_defs(
|
fn create_and_capture_lifetime_defs(&mut self, lifetimes_in_bounds: &[&Lifetime]) {
|
||||||
&mut self,
|
|
||||||
lifetimes_in_bounds: &[&Lifetime],
|
|
||||||
binders_to_ignore: &FxHashMap<NodeId, Vec<NodeId>>,
|
|
||||||
) {
|
|
||||||
for lifetime in lifetimes_in_bounds {
|
for lifetime in lifetimes_in_bounds {
|
||||||
let ident = lifetime.ident;
|
let ident = lifetime.ident;
|
||||||
let span = ident.span;
|
let span = ident.span;
|
||||||
|
@ -1461,53 +1456,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
|
|
||||||
if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() {
|
if let Some(mut captured_lifetimes) = self.captured_lifetimes.take() {
|
||||||
match res {
|
match res {
|
||||||
LifetimeRes::Param { param, binder } => {
|
LifetimeRes::Param { param, binder: _ } => {
|
||||||
if !binders_to_ignore
|
match captured_lifetimes.captures.entry(param) {
|
||||||
.get(&lifetime.id)
|
Entry::Occupied(_) => {}
|
||||||
.unwrap_or(&Vec::new())
|
Entry::Vacant(v) => {
|
||||||
.contains(&binder)
|
let node_id = self.next_node_id();
|
||||||
{
|
let name = ParamName::Plain(ident);
|
||||||
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(
|
self.create_def(
|
||||||
captured_lifetimes.parent_def_id,
|
captured_lifetimes.parent_def_id,
|
||||||
node_id,
|
node_id,
|
||||||
DefPathData::LifetimeNs(name.ident().name),
|
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);
|
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
|
||||||
if !binders_to_ignore
|
let param = self.local_def_id(param);
|
||||||
.get(&lifetime.id)
|
match captured_lifetimes.captures.entry(param) {
|
||||||
.unwrap_or(&Vec::new())
|
Entry::Occupied(_) => {}
|
||||||
.contains(&binder)
|
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(
|
self.create_def(
|
||||||
captured_lifetimes.parent_def_id,
|
captured_lifetimes.parent_def_id,
|
||||||
node_id,
|
node_id,
|
||||||
DefPathData::LifetimeNs(kw::UnderscoreLifetime),
|
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) =
|
let lifetimes_in_bounds =
|
||||||
lifetime_collector::lifetimes_in_ret_ty(output);
|
lifetime_collector::lifetimes_in_ret_ty(&this.resolver, output);
|
||||||
debug!(?lifetimes_in_bounds);
|
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
|
// We have to be careful to get elision right here. The
|
||||||
// idea is that we create a lifetime parameter for each
|
// idea is that we create a lifetime parameter for each
|
||||||
|
|
|
@ -1,21 +1,32 @@
|
||||||
|
use super::ResolverAstLoweringExt;
|
||||||
use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor};
|
use rustc_ast::visit::{self, BoundKind, LifetimeCtxt, Visitor};
|
||||||
use rustc_ast::{
|
use rustc_ast::{
|
||||||
FnRetTy, GenericBounds, Lifetime, NodeId, PolyTraitRef, TraitBoundModifier, Ty, TyKind,
|
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<NodeId>,
|
current_binders: Vec<NodeId>,
|
||||||
binders_to_ignore: FxHashMap<NodeId, Vec<NodeId>>,
|
|
||||||
collected_lifetimes: Vec<&'ast Lifetime>,
|
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) {
|
fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, _: LifetimeCtxt) {
|
||||||
if !self.collected_lifetimes.contains(&lifetime) {
|
let res = self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error);
|
||||||
self.collected_lifetimes.push(lifetime);
|
|
||||||
|
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) {
|
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<NodeId, Vec<NodeId>>) {
|
pub fn lifetimes_in_ret_ty<'this, 'ast: 'this>(
|
||||||
let mut visitor = LifetimeCollectVisitor {
|
resolver: &'this ResolverAstLowering,
|
||||||
current_binders: Vec::new(),
|
ret_ty: &'ast FnRetTy,
|
||||||
binders_to_ignore: FxHashMap::default(),
|
) -> Vec<&'ast Lifetime> {
|
||||||
collected_lifetimes: Vec::new(),
|
let mut visitor = LifetimeCollectVisitor::new(resolver);
|
||||||
};
|
|
||||||
visitor.visit_fn_ret_ty(ret_ty);
|
visitor.visit_fn_ret_ty(ret_ty);
|
||||||
(visitor.collected_lifetimes, visitor.binders_to_ignore)
|
visitor.collected_lifetimes
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lifetimes_in_bounds(
|
pub fn lifetimes_in_bounds<'this, 'ast: 'this>(
|
||||||
bounds: &GenericBounds,
|
resolver: &'this ResolverAstLowering,
|
||||||
) -> (Vec<&Lifetime>, FxHashMap<NodeId, Vec<NodeId>>) {
|
bounds: &'ast GenericBounds,
|
||||||
let mut visitor = LifetimeCollectVisitor {
|
) -> Vec<&'ast Lifetime> {
|
||||||
current_binders: Vec::new(),
|
let mut visitor = LifetimeCollectVisitor::new(resolver);
|
||||||
binders_to_ignore: FxHashMap::default(),
|
|
||||||
collected_lifetimes: Vec::new(),
|
|
||||||
};
|
|
||||||
for bound in bounds {
|
for bound in bounds {
|
||||||
visitor.visit_param_bound(bound, BoundKind::Bound);
|
visitor.visit_param_bound(bound, BoundKind::Bound);
|
||||||
}
|
}
|
||||||
(visitor.collected_lifetimes, visitor.binders_to_ignore)
|
visitor.collected_lifetimes
|
||||||
}
|
}
|
||||||
|
|
|
@ -747,3 +747,12 @@ pub enum LifetimeRes {
|
||||||
/// HACK: This is used to recover the NodeId of an elided lifetime.
|
/// HACK: This is used to recover the NodeId of an elided lifetime.
|
||||||
ElidedAnchor { start: NodeId, end: NodeId },
|
ElidedAnchor { start: NodeId, end: NodeId },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl LifetimeRes {
|
||||||
|
pub fn binder(&self) -> Option<NodeId> {
|
||||||
|
match self {
|
||||||
|
LifetimeRes::Param { binder, .. } | LifetimeRes::Fresh { binder, .. } => Some(*binder),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue