lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`
- let path = P(hir::Path {
- span: exist_ty_span,
- def: Def::Existential(DefId::local(exist_ty_def_index)),
- segments: hir_vec![hir::PathSegment {
- infer_types: false,
- ident: Ident::new(keywords::Invalid.name(), exist_ty_span),
- args: Some(P(hir::GenericArgs {
- parenthesized: false,
- bindings: HirVec::new(),
- args: lifetimes,
- }))
- }],
- });
- hir::TyKind::Path(hir::QPath::Resolved(None, path))
+ hir::TyKind::Def(hir::ItemId { id: exist_ty_id.node_id }, lifetimes)
})
}
}
}
- /// Lowers `impl Trait` items for a function and appends them to the list
- fn lower_fn_impl_trait_ids(
- &mut self,
- decl: &FnDecl,
- header: &FnHeader,
- ids: &mut SmallVec<[hir::ItemId; 1]>,
- ) {
- if let Some(id) = header.asyncness.opt_return_id() {
- ids.push(hir::ItemId { id });
- }
- let mut visitor = ImplTraitTypeIdVisitor { ids };
- match decl.output {
- FunctionRetTy::Default(_) => {},
- FunctionRetTy::Ty(ref ty) => visitor.visit_ty(ty),
- }
- }
-
fn lower_item_id(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
match i.node {
ItemKind::Use(ref use_tree) => {
vec
}
ItemKind::MacroDef(..) => SmallVec::new(),
- ItemKind::Fn(ref decl, ref header, ..) => {
- let mut ids = smallvec![hir::ItemId { id: i.id }];
- self.lower_fn_impl_trait_ids(decl, header, &mut ids);
- ids
- },
- ItemKind::Impl(.., None, _, ref items) => {
- let mut ids = smallvec![hir::ItemId { id: i.id }];
- for item in items {
- if let ImplItemKind::Method(ref sig, _) = item.node {
- self.lower_fn_impl_trait_ids(&sig.decl, &sig.header, &mut ids);
- }
- }
- ids
- },
+ ItemKind::Fn(..) |
+ ItemKind::Impl(.., None, _, _) => smallvec![hir::ItemId { id: i.id }],
ItemKind::Static(ref ty, ..) => {
let mut ids = smallvec![hir::ItemId { id: i.id }];
if self.sess.features_untracked().impl_trait_in_bindings {
};
self.with(scope, |_, this| this.visit_ty(&mt.ty));
}
- hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
- if let Def::Existential(exist_ty_did) = path.def {
- let id = self.tcx.hir.as_local_node_id(exist_ty_did).unwrap();
-
- // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
- // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
- // `abstract type MyAnonTy<'b>: MyTrait<'b>;`
- // ^ ^ this gets resolved in the scope of
- // the exist_ty generics
- let (generics, bounds) = match self.tcx.hir.expect_item(id).node {
- // named existential types don't need these hacks
- hir::ItemKind::Existential(hir::ExistTy{ impl_trait_fn: None, .. }) => {
- intravisit::walk_ty(self, ty);
- return;
- },
- hir::ItemKind::Existential(hir::ExistTy{
- ref generics,
- ref bounds,
- ..
- }) => (
- generics,
- bounds,
- ),
- ref i => bug!("impl Trait pointed to non-existential type?? {:#?}", i),
- };
+ hir::TyKind::Def(item_id, ref lifetimes) => {
+ // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
+ // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
+ // `abstract type MyAnonTy<'b>: MyTrait<'b>;`
+ // ^ ^ this gets resolved in the scope of
+ // the exist_ty generics
+ let (generics, bounds) = match self.tcx.hir.expect_item(item_id.id).node {
+ // named existential types are reached via TyKind::Path
+ // this arm is for `impl Trait` in the types of statics, constants and locals
+ hir::ItemKind::Existential(hir::ExistTy{ impl_trait_fn: None, .. }) => {
+ intravisit::walk_ty(self, ty);
+ return;
+ },
+ // RPIT (return position impl trait)
+ hir::ItemKind::Existential(hir::ExistTy{
+ ref generics,
+ ref bounds,
+ ..
+ }) => (
+ generics,
+ bounds,
+ ),
+ ref i => bug!("impl Trait pointed to non-existential type?? {:#?}", i),
+ };
+
+ // Resolve the lifetimes that are applied to the existential type.
+ // These are resolved in the current scope.
+ // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
+ // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
+ // ^ ^this gets resolved in the current scope
+ for lifetime in lifetimes {
+ if let hir::GenericArg::Lifetime(lifetime) = lifetime {
+ self.visit_lifetime(lifetime);
- assert!(exist_ty_did.is_local());
- // Resolve the lifetimes that are applied to the existential type.
- // These are resolved in the current scope.
- // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
- // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
- // ^ ^this gets resolved in the current scope
- for lifetime in &path.segments[0].args.as_ref().unwrap().args {
- if let hir::GenericArg::Lifetime(lifetime) = lifetime {
- self.visit_lifetime(lifetime);
-
- // Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
- // and ban them. Type variables instantiated inside binders aren't
- // well-supported at the moment, so this doesn't work.
- // In the future, this should be fixed and this error should be removed.
- let def = self.map.defs.get(&lifetime.id).cloned();
- if let Some(Region::LateBound(_, def_id, _)) = def {
- if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
- // Ensure that the parent of the def is an item, not HRTB
- let parent_id = self.tcx.hir.get_parent_node(node_id);
- let parent_impl_id = hir::ImplItemId { node_id: parent_id };
- let parent_trait_id = hir::TraitItemId { node_id: parent_id };
- let krate = self.tcx.hir.forest.krate();
- if !(krate.items.contains_key(&parent_id)
- || krate.impl_items.contains_key(&parent_impl_id)
- || krate.trait_items.contains_key(&parent_trait_id))
- {
- span_err!(
- self.tcx.sess,
- lifetime.span,
- E0657,
- "`impl Trait` can only capture lifetimes \
- bound at the fn or impl level"
- );
- self.uninsert_lifetime_on_error(lifetime, def.unwrap());
- }
+ // Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
+ // and ban them. Type variables instantiated inside binders aren't
+ // well-supported at the moment, so this doesn't work.
+ // In the future, this should be fixed and this error should be removed.
+ let def = self.map.defs.get(&lifetime.id).cloned();
+ if let Some(Region::LateBound(_, def_id, _)) = def {
+ if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
+ // Ensure that the parent of the def is an item, not HRTB
+ let parent_id = self.tcx.hir.get_parent_node(node_id);
+ let parent_impl_id = hir::ImplItemId { node_id: parent_id };
+ let parent_trait_id = hir::TraitItemId { node_id: parent_id };
+ let krate = self.tcx.hir.forest.krate();
+ if !(krate.items.contains_key(&parent_id)
+ || krate.impl_items.contains_key(&parent_impl_id)
+ || krate.trait_items.contains_key(&parent_trait_id))
+ {
+ span_err!(
+ self.tcx.sess,
+ lifetime.span,
+ E0657,
+ "`impl Trait` can only capture lifetimes \
+ bound at the fn or impl level"
+ );
+ self.uninsert_lifetime_on_error(lifetime, def.unwrap());
}
}
}
}
+ }
- // We want to start our early-bound indices at the end of the parent scope,
- // not including any parent `impl Trait`s.
- let mut index = self.next_early_index_for_abstract_type();
- debug!("visit_ty: index = {}", index);
+ // We want to start our early-bound indices at the end of the parent scope,
+ // not including any parent `impl Trait`s.
+ let mut index = self.next_early_index_for_abstract_type();
+ debug!("visit_ty: index = {}", index);
- let mut elision = None;
- let mut lifetimes = FxHashMap();
- let mut type_count = 0;
- for param in &generics.params {
- match param.kind {
- GenericParamKind::Lifetime { .. } => {
- let (name, reg) = Region::early(&self.tcx.hir, &mut index, ¶m);
- if let hir::ParamName::Plain(param_name) = name {
- if param_name.name == keywords::UnderscoreLifetime.name() {
- // Pick the elided lifetime "definition" if one exists
- // and use it to make an elision scope.
- elision = Some(reg);
- } else {
- lifetimes.insert(name, reg);
- }
+ let mut elision = None;
+ let mut lifetimes = FxHashMap();
+ let mut type_count = 0;
+ for param in &generics.params {
+ match param.kind {
+ GenericParamKind::Lifetime { .. } => {
+ let (name, reg) = Region::early(&self.tcx.hir, &mut index, ¶m);
+ if let hir::ParamName::Plain(param_name) = name {
+ if param_name.name == keywords::UnderscoreLifetime.name() {
+ // Pick the elided lifetime "definition" if one exists
+ // and use it to make an elision scope.
+ elision = Some(reg);
} else {
lifetimes.insert(name, reg);
}
- }
- GenericParamKind::Type { .. } => {
- type_count += 1;
+ } else {
+ lifetimes.insert(name, reg);
}
}
+ GenericParamKind::Type { .. } => {
+ type_count += 1;
+ }
}
- let next_early_index = index + type_count;
+ }
+ let next_early_index = index + type_count;
- if let Some(elision_region) = elision {
- let scope = Scope::Elision {
- elide: Elide::Exact(elision_region),
- s: self.scope,
- };
- self.with(scope, |_old_scope, this| {
- let scope = Scope::Binder {
- lifetimes,
- next_early_index,
- s: this.scope,
- track_lifetime_uses: true,
- abstract_type_parent: false,
- };
- this.with(scope, |_old_scope, this| {
- this.visit_generics(generics);
- for bound in bounds {
- this.visit_param_bound(bound);
- }
- });
- });
- } else {
+ if let Some(elision_region) = elision {
+ let scope = Scope::Elision {
+ elide: Elide::Exact(elision_region),
+ s: self.scope,
+ };
+ self.with(scope, |_old_scope, this| {
let scope = Scope::Binder {
lifetimes,
next_early_index,
- s: self.scope,
+ s: this.scope,
track_lifetime_uses: true,
abstract_type_parent: false,
};
- self.with(scope, |_old_scope, this| {
+ this.with(scope, |_old_scope, this| {
this.visit_generics(generics);
for bound in bounds {
this.visit_param_bound(bound);
}
});
- }
+ });
} else {
- intravisit::walk_ty(self, ty)
+ let scope = Scope::Binder {
+ lifetimes,
+ next_early_index,
+ s: self.scope,
+ track_lifetime_uses: true,
+ abstract_type_parent: false,
+ };
+ self.with(scope, |_old_scope, this| {
+ this.visit_generics(generics);
+ for bound in bounds {
+ this.visit_param_bound(bound);
+ }
+ });
}
}
_ => intravisit::walk_ty(self, ty),