diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 2a351d99841ff..e06563f90e008 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -607,9 +607,11 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { } visitor.visit_lifetime(lifetime); } - TyImplTraitExistential(item_id, def_id, ref lifetimes) => { + TyImplTraitExistential(_, def_id, ref lifetimes) => { + // we are not recursing into the `existential` item, because it is already being visited + // as part of the surrounding module. The `NodeId` just exists so we don't have to look + // it up everywhere else in the compiler visitor.visit_def_mention(Def::Existential(def_id)); - visitor.visit_nested_item(item_id); walk_list!(visitor, visit_lifetime, lifetimes); } TyTypeof(ref expression) => { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 110ebf6b215a1..792f67b5ef5a0 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -863,7 +863,7 @@ impl<'a> LoweringContext<'a> { let capture_clause = self.lower_capture_clause(capture_clause); let closure_hir_id = self.lower_node_id(closure_node_id).hir_id; - let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, false); + let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, None); let generator = hir::Expr { id: closure_node_id, hir_id: closure_hir_id, @@ -1106,7 +1106,7 @@ impl<'a> LoweringContext<'a> { ), unsafety: this.lower_unsafety(f.unsafety), abi: f.abi, - decl: this.lower_fn_decl(&f.decl, None, false, false), + decl: this.lower_fn_decl(&f.decl, None, false, None), arg_names: this.lower_fn_args_to_names(&f.decl), })) }, @@ -1167,25 +1167,23 @@ impl<'a> LoweringContext<'a> { } hir::TyTraitObject(bounds, lifetime_bound) } - TyKind::ImplTrait(ref bounds) => { + TyKind::ImplTrait(def_node_id, ref bounds) => { let span = t.span; match itctx { ImplTraitContext::Existential(fn_def_id) => { self.lower_existential_impl_trait( - span, fn_def_id, |this| this.lower_param_bounds(bounds, itctx)) + span, fn_def_id, def_node_id, + |this| this.lower_param_bounds(bounds, itctx), + ) } - ImplTraitContext::Universal(def_id) => { - let def_node_id = self.next_id().node_id; - + ImplTraitContext::Universal(_def_id) => { + self.lower_node_id(def_node_id); // Add a definition for the in-band TyParam - let def_index = self.resolver.definitions().create_def_with_parent( - def_id.index, - def_node_id, - DefPathData::UniversalImplTrait, - DefIndexAddressSpace::High, - Mark::root(), - span, - ); + let def_index = self + .resolver + .definitions() + .opt_def_index(def_node_id) + .unwrap(); let hir_bounds = self.lower_param_bounds(bounds, itctx); // Set the name to `impl Bound1 + Bound2` @@ -1240,13 +1238,9 @@ impl<'a> LoweringContext<'a> { &mut self, span: Span, fn_def_id: DefId, + exist_ty_node_id: NodeId, lower_bounds: impl FnOnce(&mut LoweringContext) -> hir::GenericBounds, ) -> hir::Ty_ { - // We need to manually repeat the code of `next_id` because the lowering - // needs to happen while the owner_id is pointing to the item itself, - // because items are their own owners - let exist_ty_node_id = self.sess.next_node_id(); - // Make sure we know that some funky desugaring has been going on here. // This is a first: there is code in other places like for loop // desugaring that explicitly states that we don't want to track that. @@ -1257,18 +1251,12 @@ impl<'a> LoweringContext<'a> { span, ); - // Pull a new definition from the ether let exist_ty_def_index = self .resolver .definitions() - .create_def_with_parent( - fn_def_id.index, - exist_ty_node_id, - DefPathData::ExistentialImplTrait, - DefIndexAddressSpace::High, - Mark::root(), - exist_ty_span, - ); + .opt_def_index(exist_ty_node_id) + .unwrap(); + self.allocate_hir_id_counter(exist_ty_node_id, &"existential impl trait"); @@ -1365,7 +1353,7 @@ impl<'a> LoweringContext<'a> { fn visit_ty(&mut self, t: &'v hir::Ty) { // Don't collect elided lifetimes used inside of `fn()` syntax - if let &hir::Ty_::TyBareFn(_) = &t.node { + if let hir::Ty_::TyBareFn(_) = t.node { let old_collect_elided_lifetimes = self.collect_elided_lifetimes; self.collect_elided_lifetimes = false; @@ -1377,7 +1365,7 @@ impl<'a> LoweringContext<'a> { self.collect_elided_lifetimes = old_collect_elided_lifetimes; } else { - hir::intravisit::walk_ty(self, t); + hir::intravisit::walk_ty(self, t) } } @@ -1877,18 +1865,19 @@ impl<'a> LoweringContext<'a> { // decl: the unlowered (ast) function declaration. // fn_def_id: if `Some`, impl Trait arguments are lowered into generic parameters on the // given DefId, otherwise impl Trait is disallowed. Must be `Some` if - // make_ret_async is true. + // make_ret_async is also `Some`. // impl_trait_return_allow: determines whether impl Trait can be used in return position. // This guards against trait declarations and implementations where impl Trait is // disallowed. - // make_ret_async: if enabled, converts `-> T` into `-> impl Future` in the - // return type. This is used for `async fn` declarations. + // make_ret_async: if `Some`, converts `-> T` into `-> impl Future` in the + // return type. This is used for `async fn` declarations. The `NodeId` is the id of the + // return type impl Trait item. fn lower_fn_decl( &mut self, decl: &FnDecl, fn_def_id: Option, impl_trait_return_allow: bool, - make_ret_async: bool, + make_ret_async: Option, ) -> P { let inputs = decl.inputs .iter() @@ -1901,9 +1890,9 @@ impl<'a> LoweringContext<'a> { }) .collect::>(); - let output = if make_ret_async { + let output = if let Some(ret_id) = make_ret_async { self.lower_async_fn_ret_ty( - &inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id")) + &inputs, &decl.output, fn_def_id.expect("make_ret_async but no fn_def_id"), ret_id) } else { match decl.output { FunctionRetTy::Ty(ref ty) => match fn_def_id { @@ -1939,6 +1928,7 @@ impl<'a> LoweringContext<'a> { inputs: &[P], output: &FunctionRetTy, fn_def_id: DefId, + return_impl_trait_id: NodeId, ) -> hir::FunctionRetTy { // Get lifetimes used in the input arguments to the function. Our output type must also // have the same lifetime. FIXME(cramertj) multiple different lifetimes are not allowed @@ -2090,7 +2080,7 @@ impl<'a> LoweringContext<'a> { }; let impl_trait_ty = self.lower_existential_impl_trait( - span, fn_def_id, |this| { + span, fn_def_id, return_impl_trait_id, |this| { let output_ty = match output { FunctionRetTy::Ty(ty) => this.lower_ty(ty, ImplTraitContext::Existential(fn_def_id)), @@ -2575,9 +2565,9 @@ impl<'a> LoweringContext<'a> { // only cares about the input argument patterns in the function // declaration (decl), not the return types. let body_id = this.lower_body(Some(decl), |this| { - if let IsAsync::Async(async_node_id) = header.asyncness { + if let IsAsync::Async { closure_id, .. } = header.asyncness { let async_expr = this.make_async_expr( - CaptureBy::Value, async_node_id, None, + CaptureBy::Value, closure_id, None, |this| { let body = this.lower_block(body, false); this.expr_block(body, ThinVec::new()) @@ -2594,7 +2584,7 @@ impl<'a> LoweringContext<'a> { fn_def_id, AnonymousLifetimeMode::PassThrough, |this| this.lower_fn_decl( - decl, Some(fn_def_id), true, header.asyncness.is_async()) + decl, Some(fn_def_id), true, header.asyncness.opt_return_id()) ); hir::ItemFn( @@ -2917,7 +2907,7 @@ impl<'a> LoweringContext<'a> { AnonymousLifetimeMode::PassThrough, |this| { hir::TraitItemKind::Method( - this.lower_method_sig(sig, trait_item_def_id, false, false), + this.lower_method_sig(sig, trait_item_def_id, false, None), hir::TraitMethod::Required(names), ) }, @@ -2935,7 +2925,7 @@ impl<'a> LoweringContext<'a> { AnonymousLifetimeMode::PassThrough, |this| { hir::TraitItemKind::Method( - this.lower_method_sig(sig, trait_item_def_id, false, false), + this.lower_method_sig(sig, trait_item_def_id, false, None), hir::TraitMethod::Provided(body_id), ) }, @@ -3006,9 +2996,9 @@ impl<'a> LoweringContext<'a> { } ImplItemKind::Method(ref sig, ref body) => { let body_id = self.lower_body(Some(&sig.decl), |this| { - if let IsAsync::Async(async_node_id) = sig.header.asyncness { + if let IsAsync::Async { closure_id, .. } = sig.header.asyncness { let async_expr = this.make_async_expr( - CaptureBy::Value, async_node_id, None, + CaptureBy::Value, closure_id, None, |this| { let body = this.lower_block(body, false); this.expr_block(body, ThinVec::new()) @@ -3031,7 +3021,7 @@ impl<'a> LoweringContext<'a> { sig, impl_item_def_id, impl_trait_return_allow, - sig.header.asyncness.is_async(), + sig.header.asyncness.opt_return_id(), ), body_id, ) @@ -3087,17 +3077,73 @@ impl<'a> LoweringContext<'a> { } } + /// Lowers `impl Trait` items and appends them to the list + fn lower_impl_trait_ids( + &mut self, + decl: &FnDecl, + header: &FnHeader, + ids: &mut SmallVector, + ) { + if let Some(id) = header.asyncness.opt_return_id() { + ids.push(hir::ItemId { id }); + } + struct IdVisitor<'a> { ids: &'a mut SmallVector } + impl<'a, 'b> Visitor<'a> for IdVisitor<'b> { + fn visit_ty(&mut self, ty: &'a Ty) { + match ty.node { + | TyKind::Typeof(_) + | TyKind::BareFn(_) + => return, + + TyKind::ImplTrait(id, _) => self.ids.push(hir::ItemId { id }), + _ => {}, + } + visit::walk_ty(self, ty); + } + fn visit_path_segment( + &mut self, + path_span: Span, + path_segment: &'v PathSegment, + ) { + if let Some(ref p) = path_segment.args { + if let GenericArgs::Parenthesized(_) = **p { + return; + } + } + visit::walk_path_segment(self, path_span, path_segment) + } + } + let mut visitor = IdVisitor { ids }; + match decl.output { + FunctionRetTy::Default(_) => {}, + FunctionRetTy::Ty(ref ty) => visitor.visit_ty(ty), + } + } + fn lower_item_id(&mut self, i: &Item) -> SmallVector { match i.node { ItemKind::Use(ref use_tree) => { let mut vec = SmallVector::one(hir::ItemId { id: i.id }); self.lower_item_id_use_tree(use_tree, i.id, &mut vec); - return vec; + vec } - ItemKind::MacroDef(..) => return SmallVector::new(), - _ => {} + ItemKind::MacroDef(..) => SmallVector::new(), + ItemKind::Fn(ref decl, ref header, ..) => { + let mut ids = SmallVector::one(hir::ItemId { id: i.id }); + self.lower_impl_trait_ids(decl, header, &mut ids); + ids + }, + ItemKind::Impl(.., None, _, ref items) => { + let mut ids = SmallVector::one(hir::ItemId { id: i.id }); + for item in items { + if let ImplItemKind::Method(ref sig, _) = item.node { + self.lower_impl_trait_ids(&sig.decl, &sig.header, &mut ids); + } + } + ids + }, + _ => SmallVector::one(hir::ItemId { id: i.id }), } - SmallVector::one(hir::ItemId { id: i.id }) } fn lower_item_id_use_tree(&mut self, @@ -3173,7 +3219,7 @@ impl<'a> LoweringContext<'a> { |this| { ( // Disallow impl Trait in foreign items - this.lower_fn_decl(fdec, None, false, false), + this.lower_fn_decl(fdec, None, false, None), this.lower_fn_args_to_names(fdec), ) }, @@ -3197,7 +3243,7 @@ impl<'a> LoweringContext<'a> { sig: &MethodSig, fn_def_id: DefId, impl_trait_return_allow: bool, - is_async: bool, + is_async: Option, ) -> hir::MethodSig { hir::MethodSig { header: self.lower_fn_header(sig.header), @@ -3237,7 +3283,7 @@ impl<'a> LoweringContext<'a> { fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync { match a { - IsAsync::Async(_) => hir::IsAsync::Async, + IsAsync::Async { .. } => hir::IsAsync::Async, IsAsync::NotAsync => hir::IsAsync::NotAsync, } } @@ -3540,7 +3586,7 @@ impl<'a> LoweringContext<'a> { ExprKind::Closure( capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span ) => { - if let IsAsync::Async(async_closure_node_id) = asyncness { + if let IsAsync::Async { closure_id, .. } = asyncness { let outer_decl = FnDecl { inputs: decl.inputs.clone(), output: FunctionRetTy::Default(fn_decl_span), @@ -3549,7 +3595,7 @@ impl<'a> LoweringContext<'a> { // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. - let fn_decl = self.lower_fn_decl(&outer_decl, None, false, false); + let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None); self.with_new_scopes(|this| { // FIXME(cramertj) allow `async` non-`move` closures with @@ -3576,7 +3622,7 @@ impl<'a> LoweringContext<'a> { Some(&**ty) } else { None }; let async_body = this.make_async_expr( - capture_clause, async_closure_node_id, async_ret_ty, + capture_clause, closure_id, async_ret_ty, |this| { this.with_new_scopes(|this| this.lower_expr(body)) }); @@ -3592,7 +3638,7 @@ impl<'a> LoweringContext<'a> { }) } else { // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = self.lower_fn_decl(decl, None, false, false); + let fn_decl = self.lower_fn_decl(decl, None, false, None); self.with_new_scopes(|this| { let mut is_generator = false; diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 14cecba490d0a..5c09a263ad128 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -221,9 +221,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { // Make sure that the DepNode of some node coincides with the HirId // owner of that node. if cfg!(debug_assertions) { - let hir_id_owner = self.definitions.node_to_hir_id(id).owner; + let hir_id = self.definitions.node_to_hir_id(id); - if hir_id_owner != self.current_dep_node_owner { + if hir_id.owner != self.current_dep_node_owner { let node_str = match self.definitions.opt_def_index(id) { Some(def_index) => { self.definitions.def_path(def_index).to_string_no_crate() @@ -231,13 +231,17 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { None => format!("{:?}", node) }; + if hir_id == ::hir::DUMMY_HIR_ID { + debug!("Maybe you forgot to lower the node id {:?}?", id); + } + bug!("inconsistent DepNode for `{}`: \ current_dep_node_owner={}, hir_id.owner={}", node_str, self.definitions .def_path(self.current_dep_node_owner) .to_string_no_crate(), - self.definitions.def_path(hir_id_owner).to_string_no_crate()) + self.definitions.def_path(hir_id.owner).to_string_no_crate()) } } diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 7c71401c8b2e8..47ebc97310213 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -77,6 +77,7 @@ impl<'a> DefCollector<'a> { &mut self, id: NodeId, async_node_id: NodeId, + return_impl_trait_id: NodeId, name: Name, span: Span, visit_fn: impl FnOnce(&mut DefCollector<'a>) @@ -86,6 +87,7 @@ impl<'a> DefCollector<'a> { let fn_def_data = DefPathData::ValueNs(name.as_interned_str()); let fn_def = self.create_def(id, fn_def_data, ITEM_LIKE_SPACE, span); return self.with_parent(fn_def, |this| { + this.create_def(return_impl_trait_id, DefPathData::ImplTrait, REGULAR_SPACE, span); let closure_def = this.create_def(async_node_id, DefPathData::ClosureExpr, REGULAR_SPACE, @@ -120,10 +122,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { return visit::walk_item(self, i); } - ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async(async_node_id), .. }, ..) => { + ItemKind::Fn(_, FnHeader { asyncness: IsAsync::Async { + closure_id, + return_impl_trait_id, + }, .. }, ..) => { return self.visit_async_fn( i.id, - async_node_id, + closure_id, + return_impl_trait_id, i.ident.name, i.span, |this| visit::walk_item(this, i) @@ -228,11 +234,15 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_impl_item(&mut self, ii: &'a ImplItem) { let def_data = match ii.node { ImplItemKind::Method(MethodSig { - header: FnHeader { asyncness: IsAsync::Async(async_node_id), .. }, .. + header: FnHeader { asyncness: IsAsync::Async { + closure_id, + return_impl_trait_id, + }, .. }, .. }, ..) => { return self.visit_async_fn( ii.id, - async_node_id, + closure_id, + return_impl_trait_id, ii.ident.name, ii.span, |this| visit::walk_impl_item(this, ii) @@ -277,8 +287,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { // Async closures desugar to closures inside of closures, so // we must create two defs. - if let IsAsync::Async(async_id) = asyncness { - let async_def = self.create_def(async_id, + if let IsAsync::Async { closure_id, .. } = asyncness { + let async_def = self.create_def(closure_id, DefPathData::ClosureExpr, REGULAR_SPACE, expr.span); @@ -302,6 +312,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_ty(&mut self, ty: &'a Ty) { match ty.node { TyKind::Mac(..) => return self.visit_macro_invoc(ty.id), + TyKind::ImplTrait(node_id, _) => { + self.create_def(node_id, DefPathData::ImplTrait, REGULAR_SPACE, ty.span); + } _ => {} } visit::walk_ty(self, ty); diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index b2365e22cc66f..ca2789f04f2e2 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -374,10 +374,8 @@ pub enum DefPathData { StructCtor, /// A constant expression (see {ast,hir}::AnonConst). AnonConst, - /// An `impl Trait` type node in argument position. - UniversalImplTrait, - /// An `impl Trait` type node in return position. - ExistentialImplTrait, + /// An `impl Trait` type node + ImplTrait, /// GlobalMetaData identifies a piece of crate metadata that is global to /// a whole crate (as opposed to just one item). GlobalMetaData components @@ -641,8 +639,7 @@ impl DefPathData { ClosureExpr | StructCtor | AnonConst | - ExistentialImplTrait | - UniversalImplTrait => None + ImplTrait => None } } @@ -672,8 +669,7 @@ impl DefPathData { ClosureExpr => "{{closure}}", StructCtor => "{{constructor}}", AnonConst => "{{constant}}", - ExistentialImplTrait => "{{exist-impl-Trait}}", - UniversalImplTrait => "{{univ-impl-Trait}}", + ImplTrait => "{{impl-Trait}}", }; Symbol::intern(s).as_interned_str() diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 479fbe2673b97..95da68bc9ffc2 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -221,8 +221,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { data @ DefPathData::AnonConst | data @ DefPathData::MacroDef(..) | data @ DefPathData::ClosureExpr | - data @ DefPathData::ExistentialImplTrait | - data @ DefPathData::UniversalImplTrait | + data @ DefPathData::ImplTrait | data @ DefPathData::GlobalMetaData(..) => { let parent_def_id = self.parent_def_id(def_id).unwrap(); self.push_item_path(buffer, parent_def_id); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 4fe9c34c140cb..24bda3a47442a 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -291,8 +291,7 @@ impl PrintContext { DefPathData::Field(_) | DefPathData::StructCtor | DefPathData::AnonConst | - DefPathData::ExistentialImplTrait | - DefPathData::UniversalImplTrait | + DefPathData::ImplTrait | DefPathData::GlobalMetaData(_) => { // if we're making a symbol for something, there ought // to be a value or type-def or something in there diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 38ecbf5ca8ada..711bcfbde2c6f 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -669,7 +669,7 @@ impl<'a> ReplaceBodyWithLoop<'a> { if let ast::FunctionRetTy::Ty(ref ty) = ret_ty.output { fn involves_impl_trait(ty: &ast::Ty) -> bool { match ty.node { - ast::TyKind::ImplTrait(_) => true, + ast::TyKind::ImplTrait(..) => true, ast::TyKind::Slice(ref subty) | ast::TyKind::Array(ref subty, _) | ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. }) | diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 25187032fb473..97140d18c0865 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -208,7 +208,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } self.no_questions_in_bounds(bounds, "trait object types", false); } - TyKind::ImplTrait(ref bounds) => { + TyKind::ImplTrait(_, ref bounds) => { if !bounds.iter() .any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) { self.err_handler().span_err(ty.span, "at least one trait must be specified"); @@ -505,7 +505,7 @@ impl<'a> NestedImplTraitVisitor<'a> { impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> { fn visit_ty(&mut self, t: &'a Ty) { - if let TyKind::ImplTrait(_) = t.node { + if let TyKind::ImplTrait(..) = t.node { if let Some(outer_impl_trait) = self.outer_impl_trait { struct_span_err!(self.session, t.span, E0666, "nested `impl Trait` is not allowed") @@ -570,7 +570,7 @@ impl<'a> ImplTraitProjectionVisitor<'a> { impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> { fn visit_ty(&mut self, t: &'a Ty) { match t.node { - TyKind::ImplTrait(_) => { + TyKind::ImplTrait(..) => { if self.is_banned { struct_span_err!(self.session, t.span, E0667, "`impl Trait` is not allowed in path parameters") diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2052918747b39..159850098434e 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -777,8 +777,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { visit::walk_fn_ret_ty(self, &declaration.output); // Resolve the function body, potentially inside the body of an async closure - if let IsAsync::Async(async_closure_id) = asyncness { - let rib_kind = ClosureRibKind(async_closure_id); + if let IsAsync::Async { closure_id, .. } = asyncness { + let rib_kind = ClosureRibKind(closure_id); self.ribs[ValueNS].push(Rib::new(rib_kind)); self.label_ribs.push(Rib::new(rib_kind)); } @@ -3935,8 +3935,9 @@ impl<'a> Resolver<'a> { // resolve the arguments within the proper scopes so that usages of them inside the // closure are detected as upvars rather than normal closure arg usages. ExprKind::Closure( - _, IsAsync::Async(inner_closure_id), _, ref fn_decl, ref body, _span) => - { + _, IsAsync::Async { closure_id: inner_closure_id, .. }, _, + ref fn_decl, ref body, _span, + ) => { let rib_kind = ClosureRibKind(expr.id); self.ribs[ValueNS].push(Rib::new(rib_kind)); self.label_ribs.push(Rib::new(rib_kind)); diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 9f2ca20276cdc..70feba1eff866 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -306,7 +306,7 @@ impl Sig for ast::Ty { let nested = pprust::bounds_to_string(bounds); Ok(text_sig(nested)) } - ast::TyKind::ImplTrait(ref bounds) => { + ast::TyKind::ImplTrait(_, ref bounds) => { // FIXME recurse into bounds let nested = pprust::bounds_to_string(bounds); Ok(text_sig(format!("impl {}", nested))) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 53465c071f33a..d767265ead9d4 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1547,7 +1547,11 @@ pub enum TyKind { TraitObject(GenericBounds, TraitObjectSyntax), /// An `impl Bound1 + Bound2 + Bound3` type /// where `Bound` is a trait or a lifetime. - ImplTrait(GenericBounds), + /// + /// The `NodeId` exists to prevent lowering from having to + /// generate `NodeId`s on the fly, which would complicate + /// the generation of `existential type` items significantly + ImplTrait(NodeId, GenericBounds), /// No-op; kept solely so that we can pretty-print faithfully Paren(P), /// Unused for now @@ -1718,18 +1722,28 @@ pub enum Unsafety { #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum IsAsync { - Async(NodeId), + Async { + closure_id: NodeId, + return_impl_trait_id: NodeId, + }, NotAsync, } impl IsAsync { pub fn is_async(self) -> bool { - if let IsAsync::Async(_) = self { + if let IsAsync::Async { .. } = self { true } else { false } } + /// In case this is an `Async` return the `NodeId` for the generated impl Trait item + pub fn opt_return_id(self) -> Option { + match self { + IsAsync::Async { return_impl_trait_id, .. } => Some(return_impl_trait_id), + IsAsync::NotAsync => None, + } + } } #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c813ec1977b88..2a21e4c017112 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1726,7 +1726,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "labels on blocks are unstable"); } } - ast::ExprKind::Closure(_, ast::IsAsync::Async(_), ..) => { + ast::ExprKind::Closure(_, ast::IsAsync::Async { .. }, ..) => { gate_feature_post!(&self, async_await, e.span, "async closures are unstable"); } ast::ExprKind::Async(..) => { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 712d00fde32db..d9d3febc4fe4d 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -100,6 +100,10 @@ pub trait Folder : Sized { noop_fold_fn_decl(d, self) } + fn fold_asyncness(&mut self, a: IsAsync) -> IsAsync { + noop_fold_asyncness(a, self) + } + fn fold_block(&mut self, b: P) -> P { noop_fold_block(b, self) } @@ -396,8 +400,8 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { TyKind::TraitObject(bounds, syntax) => { TyKind::TraitObject(bounds.move_map(|b| fld.fold_param_bound(b)), syntax) } - TyKind::ImplTrait(bounds) => { - TyKind::ImplTrait(bounds.move_map(|b| fld.fold_param_bound(b))) + TyKind::ImplTrait(id, bounds) => { + TyKind::ImplTrait(fld.new_id(id), bounds.move_map(|b| fld.fold_param_bound(b))) } TyKind::Mac(mac) => { TyKind::Mac(fld.fold_mac(mac)) @@ -669,6 +673,16 @@ pub fn noop_fold_interpolated(nt: token::Nonterminal, fld: &mut T) } } +pub fn noop_fold_asyncness(asyncness: IsAsync, fld: &mut T) -> IsAsync { + match asyncness { + IsAsync::Async { closure_id, return_impl_trait_id } => IsAsync::Async { + closure_id: fld.new_id(closure_id), + return_impl_trait_id: fld.new_id(return_impl_trait_id), + }, + IsAsync::NotAsync => IsAsync::NotAsync, + } +} + pub fn noop_fold_fn_decl(decl: P, fld: &mut T) -> P { decl.map(|FnDecl {inputs, output, variadic}| FnDecl { inputs: inputs.move_map(|x| fld.fold_arg(x)), @@ -996,10 +1010,7 @@ pub fn noop_fold_impl_item(i: ImplItem, folder: &mut T) } pub fn noop_fold_fn_header(mut header: FnHeader, folder: &mut T) -> FnHeader { - header.asyncness = match header.asyncness { - IsAsync::Async(node_id) => IsAsync::Async(folder.new_id(node_id)), - IsAsync::NotAsync => IsAsync::NotAsync, - }; + header.asyncness = folder.fold_asyncness(header.asyncness); header } @@ -1249,12 +1260,8 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu arms.move_map(|x| folder.fold_arm(x))) } ExprKind::Closure(capture_clause, asyncness, movability, decl, body, span) => { - let asyncness = match asyncness { - IsAsync::Async(node_id) => IsAsync::Async(folder.new_id(node_id)), - IsAsync::NotAsync => IsAsync::NotAsync, - }; ExprKind::Closure(capture_clause, - asyncness, + folder.fold_asyncness(asyncness), movability, folder.fold_fn_decl(decl), folder.fold_expr(body), @@ -1265,7 +1272,11 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu opt_label.map(|label| folder.fold_label(label))) } ExprKind::Async(capture_clause, node_id, body) => { - ExprKind::Async(capture_clause, folder.new_id(node_id), folder.fold_block(body)) + ExprKind::Async( + capture_clause, + folder.new_id(node_id), + folder.fold_block(body), + ) } ExprKind::Assign(el, er) => { ExprKind::Assign(folder.fold_expr(el), folder.fold_expr(er)) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 21bd6c083244d..4c86a64b0997b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1299,7 +1299,10 @@ impl<'a> Parser<'a> { /// Parse asyncness: `async` or nothing fn parse_asyncness(&mut self) -> IsAsync { if self.eat_keyword(keywords::Async) { - IsAsync::Async(ast::DUMMY_NODE_ID) + IsAsync::Async { + closure_id: ast::DUMMY_NODE_ID, + return_impl_trait_id: ast::DUMMY_NODE_ID, + } } else { IsAsync::NotAsync } @@ -1537,7 +1540,7 @@ impl<'a> Parser<'a> { // Always parse bounds greedily for better error recovery. let bounds = self.parse_generic_bounds()?; impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; - TyKind::ImplTrait(bounds) + TyKind::ImplTrait(ast::DUMMY_NODE_ID, bounds) } else if self.check_keyword(keywords::Dyn) && self.look_ahead(1, |t| t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t)) { @@ -3279,10 +3282,8 @@ impl<'a> Parser<'a> { } else { Movability::Movable }; - let asyncness = if self.span.edition() >= Edition::Edition2018 - && self.eat_keyword(keywords::Async) - { - IsAsync::Async(ast::DUMMY_NODE_ID) + let asyncness = if self.span.edition() >= Edition::Edition2018 { + self.parse_asyncness() } else { IsAsync::NotAsync }; @@ -6798,7 +6799,10 @@ impl<'a> Parser<'a> { let fn_span = self.prev_span; let (ident, item_, extra_attrs) = self.parse_item_fn(unsafety, - IsAsync::Async(ast::DUMMY_NODE_ID), + IsAsync::Async { + closure_id: ast::DUMMY_NODE_ID, + return_impl_trait_id: ast::DUMMY_NODE_ID, + }, respan(fn_span, Constness::NotConst), Abi::Rust)?; let prev_span = self.prev_span; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3359225e15965..74edf538842c6 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1078,7 +1078,7 @@ impl<'a> State<'a> { let prefix = if syntax == ast::TraitObjectSyntax::Dyn { "dyn" } else { "" }; self.print_type_bounds(prefix, &bounds[..])?; } - ast::TyKind::ImplTrait(ref bounds) => { + ast::TyKind::ImplTrait(_, ref bounds) => { self.print_type_bounds("impl", &bounds[..])?; } ast::TyKind::Array(ref ty, ref length) => { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 41e3ad9d4f4b1..bb35bcee43806 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -338,7 +338,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { visitor.visit_anon_const(length) } TyKind::TraitObject(ref bounds, ..) | - TyKind::ImplTrait(ref bounds) => { + TyKind::ImplTrait(_, ref bounds) => { walk_list!(visitor, visit_param_bound, bounds); } TyKind::Typeof(ref expression) => { diff --git a/src/test/compile-fail/private-type-in-interface.rs b/src/test/compile-fail/private-type-in-interface.rs index 1842790a1405f..4235b4be27158 100644 --- a/src/test/compile-fail/private-type-in-interface.rs +++ b/src/test/compile-fail/private-type-in-interface.rs @@ -35,6 +35,8 @@ type A = ::X; //~ ERROR type `m::Priv` is private trait Tr2 {} impl Tr2 for u8 {} fn g() -> impl Tr2 { 0 } //~ ERROR type `m::Priv` is private +//~^ ERROR type `m::Priv` is private fn g_ext() -> impl Tr2 { 0 } //~ ERROR type `ext::Priv` is private +//~^ ERROR type `ext::Priv` is private fn main() {} diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index 490817c46f811..6681116f0f393 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -5,7 +5,7 @@ LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... -note: ...which requires processing `cycle2::{{exist-impl-Trait}}`... +note: ...which requires processing `cycle2::{{impl-Trait}}`... --> $DIR/auto-trait-leak.rs:31:16 | LL | fn cycle2() -> impl Clone { @@ -16,7 +16,7 @@ note: ...which requires processing `cycle2`... LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... -note: ...which requires processing `cycle1::{{exist-impl-Trait}}`... +note: ...which requires processing `cycle1::{{impl-Trait}}`... --> $DIR/auto-trait-leak.rs:24:16 | LL | fn cycle1() -> impl Clone {