From 4093d373018d84527082a5f7e396b0fec241c090 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 18 Jun 2018 13:18:33 +0200 Subject: [PATCH 01/20] Use `PathParameters` even if just the `lifetimes` field is used --- src/librustc/hir/lowering.rs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 6291e0eb11372..d7875f43a24fe 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1168,7 +1168,7 @@ impl<'a> LoweringContext<'a> { lctx.lower_param_bounds(bounds, itctx) }); - let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds( + let (path_params, params) = self.generics_from_impl_trait_bounds( exist_ty_node_id, exist_ty_def_index, &hir_bounds, @@ -1177,7 +1177,7 @@ impl<'a> LoweringContext<'a> { self.with_hir_id_owner(exist_ty_node_id, |lctx| { let exist_ty_item_kind = hir::ItemExistential(hir::ExistTy { generics: hir::Generics { - params: lifetime_defs, + params, where_clause: hir::WhereClause { id: lctx.next_id().node_id, predicates: Vec::new().into(), @@ -1215,7 +1215,7 @@ impl<'a> LoweringContext<'a> { id: exist_ty_id.node_id }, DefId::local(exist_ty_def_index), - lifetimes, + path_params.lifetimes, ) }) } @@ -1281,12 +1281,12 @@ impl<'a> LoweringContext<'a> { }) } - fn lifetimes_from_impl_trait_bounds( + fn generics_from_impl_trait_bounds( &mut self, exist_ty_id: NodeId, parent_index: DefIndex, bounds: &hir::GenericBounds, - ) -> (HirVec, HirVec) { + ) -> (hir::PathParameters, HirVec) { // This visitor walks over impl trait bounds and creates defs for all lifetimes which // appear in the bounds, excluding lifetimes that are created within the bounds. // e.g. 'a, 'b, but not 'c in `impl for<'c> SomeTrait<'a, 'b, 'c>` @@ -1298,7 +1298,7 @@ impl<'a> LoweringContext<'a> { currently_bound_lifetimes: Vec, already_defined_lifetimes: HashSet, output_lifetimes: Vec, - output_lifetime_params: Vec, + output_params: Vec, } impl<'r, 'a: 'r, 'v> hir::intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a> { @@ -1432,7 +1432,7 @@ impl<'a> LoweringContext<'a> { currently_bound_lifetimes: Vec::new(), already_defined_lifetimes: HashSet::new(), output_lifetimes: Vec::new(), - output_lifetime_params: Vec::new(), + output_params: Vec::new(), }; for bound in bounds { @@ -1440,8 +1440,13 @@ impl<'a> LoweringContext<'a> { } ( - lifetime_collector.output_lifetimes.into(), - lifetime_collector.output_lifetime_params.into(), + hir::PathParameters { + lifetimes: lifetime_collector.output_lifetimes.into(), + types: HirVec::new(), + bindings: HirVec::new(), + parenthesized: false, + }, + lifetime_collector.output_params.into(), ) } From 51812185f8cbb15690a43dad3b7d9c143c39d222 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 18 Jun 2018 13:44:36 +0200 Subject: [PATCH 02/20] Cleanup in preparation of generic extraction --- src/librustc/hir/lowering.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index d7875f43a24fe..7f73d5005eeba 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1321,8 +1321,9 @@ impl<'a> LoweringContext<'a> { } fn visit_ty(&mut self, t: &'v hir::Ty) { + match t.node { // Don't collect elided lifetimes used inside of `fn()` syntax - if let &hir::Ty_::TyBareFn(_) = &t.node { + hir::Ty_::TyBareFn(_) => { let old_collect_elided_lifetimes = self.collect_elided_lifetimes; self.collect_elided_lifetimes = false; @@ -1333,8 +1334,8 @@ impl<'a> LoweringContext<'a> { self.currently_bound_lifetimes.truncate(old_len); self.collect_elided_lifetimes = old_collect_elided_lifetimes; - } else { - hir::intravisit::walk_ty(self, t); + }, + _ => hir::intravisit::walk_ty(self, t), } } From dea4d5bb1de2260710d2cd1303c3572289cf3f03 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 18 Jun 2018 16:23:13 +0200 Subject: [PATCH 03/20] Generate the `NodeId` for `existential type` in the AST --- src/librustc/hir/lowering.rs | 50 ++++++++++++++++----------- src/librustc_driver/pretty.rs | 2 +- src/librustc_passes/ast_validation.rs | 6 ++-- src/librustc_save_analysis/sig.rs | 2 +- src/libsyntax/ast.rs | 6 +++- src/libsyntax/fold.rs | 4 +-- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax/print/pprust.rs | 2 +- src/libsyntax/visit.rs | 2 +- 9 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 7f73d5005eeba..d8bc44d3c9bc6 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1128,16 +1128,10 @@ impl<'a> LoweringContext<'a> { } hir::TyTraitObject(bounds, lifetime_bound) } - TyKind::ImplTrait(ref bounds) => { + TyKind::ImplTrait(exist_ty_node_id, ref bounds) => { let span = t.span; match itctx { ImplTraitContext::Existential(fn_def_id) => { - - // 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. @@ -1322,18 +1316,18 @@ impl<'a> LoweringContext<'a> { fn visit_ty(&mut self, t: &'v hir::Ty) { match t.node { - // Don't collect elided lifetimes used inside of `fn()` syntax + // Don't collect elided lifetimes used inside of `fn()` syntax hir::Ty_::TyBareFn(_) => { - let old_collect_elided_lifetimes = self.collect_elided_lifetimes; - self.collect_elided_lifetimes = false; + let old_collect_elided_lifetimes = self.collect_elided_lifetimes; + self.collect_elided_lifetimes = false; - // Record the "stack height" of `for<'a>` lifetime bindings - // to be able to later fully undo their introduction. - let old_len = self.currently_bound_lifetimes.len(); - hir::intravisit::walk_ty(self, t); - self.currently_bound_lifetimes.truncate(old_len); + // Record the "stack height" of `for<'a>` lifetime bindings + // to be able to later fully undo their introduction. + let old_len = self.currently_bound_lifetimes.len(); + hir::intravisit::walk_ty(self, t); + self.currently_bound_lifetimes.truncate(old_len); - self.collect_elided_lifetimes = old_collect_elided_lifetimes; + self.collect_elided_lifetimes = old_collect_elided_lifetimes; }, _ => hir::intravisit::walk_ty(self, t), } @@ -2790,12 +2784,28 @@ impl<'a> LoweringContext<'a> { 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, ..) => { + struct IdVisitor { ids: SmallVector } + impl<'a> Visitor<'a> for IdVisitor { + fn visit_ty(&mut self, ty: &'a Ty) { + if let TyKind::ImplTrait(id, _) = ty.node { + self.ids.push(hir::ItemId { id }); + } + visit::walk_ty(self, ty); + } + } + let mut visitor = IdVisitor { ids: SmallVector::one(hir::ItemId { id: i.id }) }; + match decl.output { + FunctionRetTy::Default(_) => {}, + FunctionRetTy::Ty(ref ty) => visitor.visit_ty(ty), + } + visitor.ids + }, + _ => SmallVector::one(hir::ItemId { id: i.id }), } - SmallVector::one(hir::ItemId { id: i.id }) } fn lower_item_id_use_tree(&mut self, diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 67720e61e91af..eb96e7fd99c19 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 fc54d323b0f96..3b5e6112df319 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -201,7 +201,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"); @@ -496,7 +496,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") @@ -561,7 +561,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_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 7f2f0b0c83716..d7e83e6012de3 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 c6de2c4da39cf..f1924698e7250 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1539,7 +1539,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 diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 93248fe3bfab0..4a96bf60bef1b 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -392,8 +392,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)) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 3955ccb4c420a..dcff86b4e3dea 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1522,7 +1522,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)) { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 7a55919f422b8..b076a5ee3ea7c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1079,7 +1079,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 613f1a4f113bd..d1baddb2512ce 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -340,7 +340,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) => { From 2b7f86a4c50c3e3fed38dfa875626155cc5d7db1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 19 Jun 2018 10:09:00 +0200 Subject: [PATCH 04/20] Reduce repetition around `lower_method_sig` --- src/librustc/hir/lowering.rs | 70 +++++++++++++++++------------------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index d8bc44d3c9bc6..7f87290e54e60 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2614,17 +2614,13 @@ impl<'a> LoweringContext<'a> { ), TraitItemKind::Method(ref sig, None) => { let names = self.lower_fn_args_to_names(&sig.decl); - self.add_in_band_defs( + let (generics, sig) = self.lower_method_sig( &i.generics, + sig, trait_item_def_id, - AnonymousLifetimeMode::PassThrough, - |this| { - hir::TraitItemKind::Method( - this.lower_method_sig(sig, trait_item_def_id, false), - hir::TraitMethod::Required(names), - ) - }, - ) + false, + ); + (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names))) } TraitItemKind::Method(ref sig, Some(ref body)) => { let body_id = self.lower_body(Some(&sig.decl), |this| { @@ -2632,17 +2628,14 @@ impl<'a> LoweringContext<'a> { this.expr_block(body, ThinVec::new()) }); - self.add_in_band_defs( + let (generics, sig) = self.lower_method_sig( &i.generics, + sig, trait_item_def_id, - AnonymousLifetimeMode::PassThrough, - |this| { - hir::TraitItemKind::Method( - this.lower_method_sig(sig, trait_item_def_id, false), - hir::TraitMethod::Provided(body_id), - ) - }, - ) + false, + ); + + (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id))) } TraitItemKind::Type(ref bounds, ref default) => ( self.lower_generics(&i.generics, ImplTraitContext::Disallowed), @@ -2713,22 +2706,13 @@ impl<'a> LoweringContext<'a> { this.expr_block(body, ThinVec::new()) }); let impl_trait_return_allow = !self.is_in_trait_impl; - - self.add_in_band_defs( + let (generics, sig) = self.lower_method_sig( &i.generics, - impl_item_def_id, - AnonymousLifetimeMode::PassThrough, - |this| { - hir::ImplItemKind::Method( - this.lower_method_sig( sig, impl_item_def_id, impl_trait_return_allow, - ), - body_id, - ) - }, - ) + ); + (generics, hir::ImplItemKind::Method(sig, body_id)) } ImplItemKind::Type(ref ty) => ( self.lower_generics(&i.generics, ImplTraitContext::Disallowed), @@ -2902,16 +2886,28 @@ impl<'a> LoweringContext<'a> { fn lower_method_sig( &mut self, + generics: &Generics, sig: &MethodSig, fn_def_id: DefId, impl_trait_return_allow: bool, - ) -> hir::MethodSig { - hir::MethodSig { - abi: sig.abi, - unsafety: self.lower_unsafety(sig.unsafety), - constness: self.lower_constness(sig.constness), - decl: self.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow), - } + ) -> (hir::Generics, hir::MethodSig) { + let unsafety = self.lower_unsafety(sig.unsafety); + let constness = self.lower_constness(sig.constness); + let (generics, decl) = self.add_in_band_defs( + generics, + fn_def_id, + AnonymousLifetimeMode::PassThrough, + |this| this.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow), + ); + ( + generics, + hir::MethodSig { + abi: sig.abi, + unsafety, + constness, + decl, + }, + ) } fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto { From 0dcb45e9e9ace948f07c449592a5a007fb19fd8b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 19 Jun 2018 10:54:48 +0200 Subject: [PATCH 05/20] Deduplicate code in `lower_lifetime` --- src/librustc/hir/lowering.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 7f87290e54e60..7cb4474373785 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1889,24 +1889,23 @@ impl<'a> LoweringContext<'a> { fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { let span = l.ident.span; - match self.lower_ident(l.ident) { - x if x == "'static" => self.new_named_lifetime(l.id, span, hir::LifetimeName::Static), + let name = match self.lower_ident(l.ident) { + x if x == "'static" => hir::LifetimeName::Static, x if x == "'_" => match self.anonymous_lifetime_mode { AnonymousLifetimeMode::CreateParameter => { let fresh_name = self.collect_fresh_in_band_lifetime(span); - self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(fresh_name)) + hir::LifetimeName::Param(fresh_name) } - AnonymousLifetimeMode::PassThrough => { - self.new_named_lifetime(l.id, span, hir::LifetimeName::Underscore) - } + AnonymousLifetimeMode::PassThrough => hir::LifetimeName::Underscore, }, name => { self.maybe_collect_in_band_lifetime(span, name); let param_name = ParamName::Plain(name); - self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(param_name)) + hir::LifetimeName::Param(param_name) } - } + }; + self.new_named_lifetime(l.id, span, name) } fn new_named_lifetime( From 98d4500cc949314cc95ec00f7351e8aee07cd088 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 19 Jun 2018 13:47:53 +0200 Subject: [PATCH 06/20] Remove some global state from the lowering pass --- src/librustc/hir/lowering.rs | 116 ++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 48 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 7cb4474373785..d08941d3ab9e8 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -111,13 +111,6 @@ pub struct LoweringContext<'a> { /// written at all (e.g., `&T` or `std::cell::Ref`). anonymous_lifetime_mode: AnonymousLifetimeMode, - // This is a list of in-band type definitions being generated by - // Argument-position `impl Trait`. - // When traversing a signature such as `fn foo(x: impl Trait)`, - // we record `impl Trait` as a new type parameter, then later - // add it on to `foo`s generics. - in_band_ty_params: Vec, - // Used to create lifetime definitions from in-band lifetime usages. // e.g. `fn foo(x: &'x u8) -> &'x u8` to `fn foo<'x>(x: &'x u8) -> &'x u8` // When a named lifetime is encountered in a function or impl header and @@ -172,26 +165,41 @@ pub trait Resolver { ) -> hir::Path; } -#[derive(Clone, Copy, Debug)] -enum ImplTraitContext { +#[derive(Debug)] +enum ImplTraitContext<'a> { /// Treat `impl Trait` as shorthand for a new universal generic parameter. /// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually /// equivalent to a fresh universal parameter like `fn foo(x: T)`. /// /// We store a DefId here so we can look up necessary information later - Universal(DefId), + /// + /// Newly generated parameters should be inserted into the given `Vec` + Universal(DefId, &'a mut Vec), /// Treat `impl Trait` as shorthand for a new universal existential parameter. /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually /// equivalent to a fresh existential parameter like `abstract type T; fn foo() -> T`. /// /// We store a DefId here so we can look up necessary information later - Existential(DefId), + /// + /// All generics of the surrounding function must go into the generated existential type + Existential(DefId, &'a [hir::TyParam]), /// `impl Trait` is not accepted in this position. Disallowed, } +impl<'a> ImplTraitContext<'a> { + fn reborrow(&'b mut self) -> ImplTraitContext<'b> { + use self::ImplTraitContext::*; + match self { + Universal(did, params) => Universal(*did, params), + Existential(did, params) => Existential(*did, params), + Disallowed => Disallowed, + } + } +} + pub fn lower_crate( sess: &Session, cstore: &CrateStore, @@ -227,7 +235,6 @@ pub fn lower_crate( node_id_to_hir_id: IndexVec::new(), is_generator: false, is_in_trait_impl: false, - in_band_ty_params: Vec::new(), lifetimes_to_define: Vec::new(), is_collecting_in_band_lifetimes: false, in_scope_lifetimes: Vec::new(), @@ -649,7 +656,7 @@ impl<'a> LoweringContext<'a> { f: F, ) -> (Vec, T) where - F: FnOnce(&mut LoweringContext) -> T, + F: FnOnce(&mut LoweringContext) -> (Vec, T), { assert!(!self.is_collecting_in_band_lifetimes); assert!(self.lifetimes_to_define.is_empty()); @@ -660,13 +667,11 @@ impl<'a> LoweringContext<'a> { self.anonymous_lifetime_mode = anonymous_lifetime_mode; } - assert!(self.in_band_ty_params.is_empty()); - let res = f(self); + let (in_band_ty_params, res) = f(self); self.is_collecting_in_band_lifetimes = false; self.anonymous_lifetime_mode = old_anonymous_lifetime_mode; - let in_band_ty_params = self.in_band_ty_params.split_off(0); let lifetimes_to_define = self.lifetimes_to_define.split_off(0); let params = lifetimes_to_define @@ -799,14 +804,19 @@ impl<'a> LoweringContext<'a> { f: F, ) -> (hir::Generics, T) where - F: FnOnce(&mut LoweringContext) -> T, + F: FnOnce(&mut LoweringContext, &mut Vec) -> T, { let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs( &generics.params, |this| { - let itctx = ImplTraitContext::Universal(parent_id); this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| { - (this.lower_generics(generics, itctx), f(this)) + let mut params = Vec::new(); + let generics = this.lower_generics( + generics, + ImplTraitContext::Universal(parent_id, &mut params), + ); + let res = f(this, &mut params); + (params, (generics, res)) }) }, ); @@ -1039,7 +1049,7 @@ impl<'a> LoweringContext<'a> { } } - fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P { + fn lower_ty(&mut self, t: &Ty, mut itctx: ImplTraitContext) -> P { let kind = match t.node { TyKind::Infer => hir::TyInfer, TyKind::Err => hir::TyErr, @@ -1076,7 +1086,7 @@ impl<'a> LoweringContext<'a> { ), TyKind::Never => hir::TyNever, TyKind::Tup(ref tys) => { - hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty, itctx)).collect()) + hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty, itctx.reborrow())).collect()) } TyKind::Paren(ref ty) => { return self.lower_ty(ty, itctx); @@ -1110,7 +1120,7 @@ impl<'a> LoweringContext<'a> { .iter() .filter_map(|bound| match *bound { GenericBound::Trait(ref ty, TraitBoundModifier::None) => { - Some(self.lower_poly_trait_ref(ty, itctx)) + Some(self.lower_poly_trait_ref(ty, itctx.reborrow())) } GenericBound::Trait(_, TraitBoundModifier::Maybe) => None, GenericBound::Outlives(ref lifetime) => { @@ -1131,7 +1141,7 @@ impl<'a> LoweringContext<'a> { TyKind::ImplTrait(exist_ty_node_id, ref bounds) => { let span = t.span; match itctx { - ImplTraitContext::Existential(fn_def_id) => { + ImplTraitContext::Existential(fn_def_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. @@ -1213,7 +1223,7 @@ impl<'a> LoweringContext<'a> { ) }) } - ImplTraitContext::Universal(def_id) => { + ImplTraitContext::Universal(def_id, in_band_ty_params) => { let def_node_id = self.next_id().node_id; // Add a definition for the in-band TyParam @@ -1226,7 +1236,10 @@ impl<'a> LoweringContext<'a> { span, ); - let hir_bounds = self.lower_param_bounds(bounds, itctx); + let hir_bounds = self.lower_param_bounds( + bounds, + ImplTraitContext::Universal(def_id, in_band_ty_params), + ); // Set the name to `impl Bound1 + Bound2` let name = Symbol::intern(&pprust::ty_to_string(t)); self.in_band_ty_params.push(hir::GenericParam { @@ -1480,10 +1493,10 @@ impl<'a> LoweringContext<'a> { qself: &Option, p: &Path, param_mode: ParamMode, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext, ) -> hir::QPath { let qself_position = qself.as_ref().map(|q| q.position); - let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx)); + let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx.reborrow())); let resolution = self.resolver .get_resolution(id) @@ -1570,7 +1583,7 @@ impl<'a> LoweringContext<'a> { param_mode, num_lifetimes, parenthesized_generic_args, - itctx, + itctx.reborrow(), ) }) .collect(), @@ -1613,7 +1626,7 @@ impl<'a> LoweringContext<'a> { param_mode, 0, ParenthesizedGenericArgs::Warn, - itctx, + itctx.reborrow(), )); let qpath = hir::QPath::TypeRelative(ty, segment); @@ -1730,7 +1743,7 @@ impl<'a> LoweringContext<'a> { &mut self, data: &AngleBracketedArgs, param_mode: ParamMode, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext, ) -> (hir::GenericArgs, bool) { let &AngleBracketedArgs { ref args, ref bindings, .. } = data; let has_types = args.iter().any(|arg| match arg { @@ -1738,8 +1751,8 @@ impl<'a> LoweringContext<'a> { _ => false, }); (hir::GenericArgs { - args: args.iter().map(|a| self.lower_generic_arg(a, itctx)).collect(), - bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx)).collect(), + args: args.iter().map(|a| self.lower_generic_arg(a, itctx.reborrow())).collect(), + bindings: bindings.iter().map(|b| self.lower_ty_binding(b, itctx.reborrow())).collect(), parenthesized: false, }, !has_types && param_mode == ParamMode::Optional) @@ -1832,7 +1845,7 @@ impl<'a> LoweringContext<'a> { fn lower_fn_decl( &mut self, decl: &FnDecl, - fn_def_id: Option, + mut in_band_ty_params: Option<(DefId, &mut Vec)>, impl_trait_return_allow: bool, ) -> P { // NOTE: The two last parameters here have to do with impl Trait. If fn_def_id is Some, @@ -1846,17 +1859,17 @@ impl<'a> LoweringContext<'a> { inputs: decl.inputs .iter() .map(|arg| { - if let Some(def_id) = fn_def_id { - self.lower_ty(&arg.ty, ImplTraitContext::Universal(def_id)) + if let Some((def_id, ibty)) = in_band_ty_params.as_mut() { + self.lower_ty(&arg.ty, ImplTraitContext::Universal(*def_id, ibty)) } else { self.lower_ty(&arg.ty, ImplTraitContext::Disallowed) } }) .collect(), output: match decl.output { - FunctionRetTy::Ty(ref ty) => match fn_def_id { - Some(def_id) if impl_trait_return_allow => { - hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(def_id))) + FunctionRetTy::Ty(ref ty) => match in_band_ty_params { + Some((def_id, ref mut ibty)) if impl_trait_return_allow => { + hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(def_id, ibty))) } _ => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)), }, @@ -1925,7 +1938,7 @@ impl<'a> LoweringContext<'a> { &mut self, params: &Vec, add_bounds: &NodeMap>, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext, ) -> hir::HirVec { params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect() } @@ -1973,7 +1986,10 @@ impl<'a> LoweringContext<'a> { let add_bounds = add_bounds.get(¶m.id).map_or(&[][..], |x| &x); if !add_bounds.is_empty() { bounds = bounds.into_iter() - .chain(self.lower_param_bounds(add_bounds, itctx).into_iter()) + .chain(self.lower_param_bounds( + add_bounds, + itctx.reborrow(), + ).into_iter()) .collect(); } @@ -2168,10 +2184,10 @@ impl<'a> LoweringContext<'a> { fn lower_poly_trait_ref( &mut self, p: &PolyTraitRef, - itctx: ImplTraitContext, + mut itctx: ImplTraitContext, ) -> hir::PolyTraitRef { let bound_generic_params = - self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx); + self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx.reborrow()); let trait_ref = self.with_parent_impl_lifetime_defs( &bound_generic_params, |this| this.lower_trait_ref(&p.trait_ref, itctx), @@ -2216,9 +2232,9 @@ impl<'a> LoweringContext<'a> { } } - fn lower_param_bounds(&mut self, bounds: &[GenericBound], itctx: ImplTraitContext) + fn lower_param_bounds(&mut self, bounds: &[GenericBound], mut itctx: ImplTraitContext) -> hir::GenericBounds { - bounds.iter().map(|bound| self.lower_param_bound(bound, itctx)).collect() + bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect() } fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P { @@ -2294,7 +2310,7 @@ impl<'a> LoweringContext<'a> { generics, fn_def_id, AnonymousLifetimeMode::PassThrough, - |this| this.lower_fn_decl(decl, Some(fn_def_id), true), + |this, idty| this.lower_fn_decl(decl, Some((fn_def_id, idty)), true), ); hir::ItemFn( @@ -2366,7 +2382,7 @@ impl<'a> LoweringContext<'a> { ast_generics, def_id, AnonymousLifetimeMode::CreateParameter, - |this| { + |this, _| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed) }); @@ -2861,7 +2877,7 @@ impl<'a> LoweringContext<'a> { generics, def_id, AnonymousLifetimeMode::PassThrough, - |this| { + |this, _| { ( // Disallow impl Trait in foreign items this.lower_fn_decl(fdec, None, false), @@ -2896,7 +2912,11 @@ impl<'a> LoweringContext<'a> { generics, fn_def_id, AnonymousLifetimeMode::PassThrough, - |this| this.lower_fn_decl(&sig.decl, Some(fn_def_id), impl_trait_return_allow), + |this, idty| this.lower_fn_decl( + &sig.decl, + Some((fn_def_id, idty)), + impl_trait_return_allow, + ), ); ( generics, From 3ae2e3182d1db72240ad14429b6e2ae085dd08c0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 19 Jun 2018 14:12:28 +0200 Subject: [PATCH 07/20] Pass generics through to existential impl Trait lowering --- src/librustc/hir/lowering.rs | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index d08941d3ab9e8..4e6a1d83ca597 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -183,7 +183,7 @@ enum ImplTraitContext<'a> { /// We store a DefId here so we can look up necessary information later /// /// All generics of the surrounding function must go into the generated existential type - Existential(DefId, &'a [hir::TyParam]), + Existential(DefId, &'a [hir::TyParam], &'a hir::Generics), /// `impl Trait` is not accepted in this position. Disallowed, @@ -194,7 +194,7 @@ impl<'a> ImplTraitContext<'a> { use self::ImplTraitContext::*; match self { Universal(did, params) => Universal(*did, params), - Existential(did, params) => Existential(*did, params), + Existential(did, params, generics) => Existential(*did, params, generics), Disallowed => Disallowed, } } @@ -804,7 +804,7 @@ impl<'a> LoweringContext<'a> { f: F, ) -> (hir::Generics, T) where - F: FnOnce(&mut LoweringContext, &mut Vec) -> T, + F: FnOnce(&mut LoweringContext, &mut Vec, &hir::Generics) -> T, { let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs( &generics.params, @@ -815,7 +815,7 @@ impl<'a> LoweringContext<'a> { generics, ImplTraitContext::Universal(parent_id, &mut params), ); - let res = f(this, &mut params); + let res = f(this, &mut params, &generics); (params, (generics, res)) }) }, @@ -1141,7 +1141,7 @@ impl<'a> LoweringContext<'a> { TyKind::ImplTrait(exist_ty_node_id, ref bounds) => { let span = t.span; match itctx { - ImplTraitContext::Existential(fn_def_id, _) => { + ImplTraitContext::Existential(fn_def_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. @@ -1845,7 +1845,7 @@ impl<'a> LoweringContext<'a> { fn lower_fn_decl( &mut self, decl: &FnDecl, - mut in_band_ty_params: Option<(DefId, &mut Vec)>, + mut in_band_ty_params: Option<(DefId, &mut Vec, &hir::Generics)>, impl_trait_return_allow: bool, ) -> P { // NOTE: The two last parameters here have to do with impl Trait. If fn_def_id is Some, @@ -1859,7 +1859,7 @@ impl<'a> LoweringContext<'a> { inputs: decl.inputs .iter() .map(|arg| { - if let Some((def_id, ibty)) = in_band_ty_params.as_mut() { + if let Some((def_id, ibty, _)) = in_band_ty_params.as_mut() { self.lower_ty(&arg.ty, ImplTraitContext::Universal(*def_id, ibty)) } else { self.lower_ty(&arg.ty, ImplTraitContext::Disallowed) @@ -1868,8 +1868,12 @@ impl<'a> LoweringContext<'a> { .collect(), output: match decl.output { FunctionRetTy::Ty(ref ty) => match in_band_ty_params { - Some((def_id, ref mut ibty)) if impl_trait_return_allow => { - hir::Return(self.lower_ty(ty, ImplTraitContext::Existential(def_id, ibty))) + Some((def_id, ref mut ibty, generics)) if impl_trait_return_allow => { + hir::Return(self.lower_ty(ty, ImplTraitContext::Existential( + def_id, + ibty, + generics, + ))) } _ => hir::Return(self.lower_ty(ty, ImplTraitContext::Disallowed)), }, @@ -2310,7 +2314,11 @@ impl<'a> LoweringContext<'a> { generics, fn_def_id, AnonymousLifetimeMode::PassThrough, - |this, idty| this.lower_fn_decl(decl, Some((fn_def_id, idty)), true), + |this, idty, generics| this.lower_fn_decl( + decl, + Some((fn_def_id, idty, generics)), + true, + ), ); hir::ItemFn( @@ -2382,7 +2390,7 @@ impl<'a> LoweringContext<'a> { ast_generics, def_id, AnonymousLifetimeMode::CreateParameter, - |this, _| { + |this, _, _| { let trait_ref = trait_ref.as_ref().map(|trait_ref| { this.lower_trait_ref(trait_ref, ImplTraitContext::Disallowed) }); @@ -2877,7 +2885,7 @@ impl<'a> LoweringContext<'a> { generics, def_id, AnonymousLifetimeMode::PassThrough, - |this, _| { + |this, _, _| { ( // Disallow impl Trait in foreign items this.lower_fn_decl(fdec, None, false), @@ -2912,9 +2920,9 @@ impl<'a> LoweringContext<'a> { generics, fn_def_id, AnonymousLifetimeMode::PassThrough, - |this, idty| this.lower_fn_decl( + |this, idty, generics| this.lower_fn_decl( &sig.decl, - Some((fn_def_id, idty)), + Some((fn_def_id, idty, generics)), impl_trait_return_allow, ), ); From 3dbe3486b161e0a03d24b20073d0b2a564b80502 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 20 Jun 2018 10:44:31 +0200 Subject: [PATCH 08/20] Don't generate a new NodeId for universal impl Trait --- src/librustc/hir/lowering.rs | 17 ++++++++--------- src/librustc/hir/map/collector.rs | 10 +++++++--- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 4e6a1d83ca597..96e1b72a05fac 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1138,7 +1138,7 @@ impl<'a> LoweringContext<'a> { } hir::TyTraitObject(bounds, lifetime_bound) } - TyKind::ImplTrait(exist_ty_node_id, ref bounds) => { + TyKind::ImplTrait(def_node_id, ref bounds) => { let span = t.span; match itctx { ImplTraitContext::Existential(fn_def_id, _, _) => { @@ -1158,7 +1158,7 @@ impl<'a> LoweringContext<'a> { .definitions() .create_def_with_parent( fn_def_id.index, - exist_ty_node_id, + def_node_id, DefPathData::ExistentialImplTrait, DefIndexAddressSpace::High, Mark::root(), @@ -1166,19 +1166,19 @@ impl<'a> LoweringContext<'a> { ); // the `t` is just for printing debug messages - self.allocate_hir_id_counter(exist_ty_node_id, t); + self.allocate_hir_id_counter(def_node_id, t); - let hir_bounds = self.with_hir_id_owner(exist_ty_node_id, |lctx| { + let hir_bounds = self.with_hir_id_owner(def_node_id, |lctx| { lctx.lower_param_bounds(bounds, itctx) }); let (path_params, params) = self.generics_from_impl_trait_bounds( - exist_ty_node_id, + def_node_id, exist_ty_def_index, &hir_bounds, ); - self.with_hir_id_owner(exist_ty_node_id, |lctx| { + self.with_hir_id_owner(def_node_id, |lctx| { let exist_ty_item_kind = hir::ItemExistential(hir::ExistTy { generics: hir::Generics { params, @@ -1191,7 +1191,7 @@ impl<'a> LoweringContext<'a> { bounds: hir_bounds, impl_trait_fn: Some(fn_def_id), }); - let exist_ty_id = lctx.lower_node_id(exist_ty_node_id); + let exist_ty_id = lctx.lower_node_id(def_node_id); // Generate an `existential type Foo: Trait;` declaration trace!("creating existential type with id {:#?}", exist_ty_id); // Set the name to `impl Bound1 + Bound2` @@ -1224,8 +1224,7 @@ impl<'a> LoweringContext<'a> { }) } ImplTraitContext::Universal(def_id, in_band_ty_params) => { - let def_node_id = self.next_id().node_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, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 14cecba490d0a..f16bf1d774455 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 { + println!("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()) } } From 90a54c13261181cf6eae91efb7d8000d20779246 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 20 Jun 2018 10:59:24 +0200 Subject: [PATCH 09/20] Generate `DefId`s for impl Trait in the def_collector --- src/librustc/hir/lowering.rs | 25 ++++++++----------------- src/librustc/hir/map/def_collector.rs | 3 +++ src/librustc/hir/map/definitions.rs | 12 ++++-------- src/librustc/ty/item_path.rs | 3 +-- src/librustc/util/ppaux.rs | 3 +-- 5 files changed, 17 insertions(+), 29 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 96e1b72a05fac..78983953aeabf 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1152,18 +1152,12 @@ impl<'a> LoweringContext<'a> { t.span, ); - // Pull a new definition from the ether let exist_ty_def_index = self .resolver .definitions() - .create_def_with_parent( - fn_def_id.index, - def_node_id, - DefPathData::ExistentialImplTrait, - DefIndexAddressSpace::High, - Mark::root(), - exist_ty_span, - ); + .opt_def_index(def_node_id) + .unwrap(); + // the `t` is just for printing debug messages self.allocate_hir_id_counter(def_node_id, t); @@ -1226,14 +1220,11 @@ impl<'a> LoweringContext<'a> { ImplTraitContext::Universal(def_id, in_band_ty_params) => { 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, diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 8aa5dd4ad80fd..0a3b6069a2a21 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -244,6 +244,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 b1cb9d7fbd4a5..b99f446890094 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -369,10 +369,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 @@ -636,8 +634,7 @@ impl DefPathData { ClosureExpr | StructCtor | AnonConst | - ExistentialImplTrait | - UniversalImplTrait => None + ImplTrait => None } } @@ -667,8 +664,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 3252a2cd6ab0f..ece0af5aa0d0e 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 From 2fdb64c6c023799ffdb4c8c5bcec5128253e2857 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 20 Jun 2018 13:04:18 +0200 Subject: [PATCH 10/20] Update ui tests --- src/test/ui/impl-trait/auto-trait-leak.stderr | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index b34facd2d39ce..10711d1cd8cec 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -1,4 +1,4 @@ -error[E0391]: cycle detected when processing `cycle1::{{exist-impl-Trait}}` +error[E0391]: cycle detected when processing `cycle1::{{impl-Trait}}` --> $DIR/auto-trait-leak.rs:24:16 | LL | fn cycle1() -> impl Clone { @@ -10,7 +10,7 @@ note: ...which requires processing `cycle1`... 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:33:16 | LL | fn cycle2() -> impl Clone { @@ -21,9 +21,9 @@ 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 again requires processing `cycle1::{{exist-impl-Trait}}`, completing the cycle + = note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle -error[E0391]: cycle detected when processing `cycle1::{{exist-impl-Trait}}` +error[E0391]: cycle detected when processing `cycle1::{{impl-Trait}}` --> $DIR/auto-trait-leak.rs:24:16 | LL | fn cycle1() -> impl Clone { @@ -35,7 +35,7 @@ note: ...which requires processing `cycle1`... 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:33:16 | LL | fn cycle2() -> impl Clone { @@ -45,7 +45,7 @@ note: ...which requires processing `cycle2`... | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires processing `cycle1::{{exist-impl-Trait}}`, completing the cycle + = note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle error[E0277]: `std::rc::Rc` cannot be sent between threads safely --> $DIR/auto-trait-leak.rs:27:5 From 19f5e5e8c91c83c4c465c90d751b6379960d7352 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 20 Jun 2018 18:59:17 +0200 Subject: [PATCH 11/20] While we don't have full existential types yet, there is some duplication in privacy related errors for impl Trait --- src/test/compile-fail/private-type-in-interface.rs | 2 ++ 1 file changed, 2 insertions(+) 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() {} From a83733fd413008bbffc16f6735fab2c75ca91b61 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 20 Jun 2018 19:05:27 +0200 Subject: [PATCH 12/20] Flatten some occurrences of `[P]` to `[T]` --- src/librustc/hir/lowering.rs | 41 +++++++++++++++---------- src/librustc/hir/mod.rs | 6 ++-- src/librustc/middle/resolve_lifetime.rs | 2 +- src/librustc/traits/error_reporting.rs | 2 +- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 78983953aeabf..037cc32f090d7 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1049,7 +1049,11 @@ impl<'a> LoweringContext<'a> { } } - fn lower_ty(&mut self, t: &Ty, mut itctx: ImplTraitContext) -> P { + fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P { + P(self.lower_ty_direct(t, itctx)) + } + + fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext) -> hir::Ty { let kind = match t.node { TyKind::Infer => hir::TyInfer, TyKind::Err => hir::TyErr, @@ -1086,10 +1090,15 @@ impl<'a> LoweringContext<'a> { ), TyKind::Never => hir::TyNever, TyKind::Tup(ref tys) => { - hir::TyTup(tys.iter().map(|ty| self.lower_ty(ty, itctx.reborrow())).collect()) + hir::TyTup( + tys + .iter() + .map(|ty| self.lower_ty_direct(ty, itctx.reborrow())) + .collect() + ) } TyKind::Paren(ref ty) => { - return self.lower_ty(ty, itctx); + return self.lower_ty_direct(ty, itctx); } TyKind::Path(ref qself, ref path) => { let id = self.lower_node_id(t.id); @@ -1270,12 +1279,12 @@ impl<'a> LoweringContext<'a> { }; let LoweredNodeId { node_id, hir_id } = self.lower_node_id(t.id); - P(hir::Ty { + hir::Ty { id: node_id, node: kind, span: t.span, hir_id, - }) + } } fn generics_from_impl_trait_bounds( @@ -1596,7 +1605,7 @@ impl<'a> LoweringContext<'a> { // e.g. `Vec` in `Vec::new` or `::Item` in // `::Item::default`. let new_id = self.next_id(); - self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path)) + P(self.ty_path(new_id, p.span, hir::QPath::Resolved(qself, path))) }; // Anything after the base path are associated "extensions", @@ -1627,7 +1636,7 @@ impl<'a> LoweringContext<'a> { // Wrap the associated extension in another type node. let new_id = self.next_id(); - ty = self.ty_path(new_id, p.span, qpath); + ty = P(self.ty_path(new_id, p.span, qpath)); } // Should've returned in the for loop above. @@ -1762,10 +1771,10 @@ impl<'a> LoweringContext<'a> { |this| { const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed; let &ParenthesisedArgs { ref inputs, ref output, span } = data; - let inputs = inputs.iter().map(|ty| this.lower_ty(ty, DISALLOWED)).collect(); + let inputs = inputs.iter().map(|ty| this.lower_ty_direct(ty, DISALLOWED)).collect(); let mk_tup = |this: &mut Self, tys, span| { let LoweredNodeId { node_id, hir_id } = this.next_id(); - P(hir::Ty { node: hir::TyTup(tys), id: node_id, hir_id, span }) + hir::Ty { node: hir::TyTup(tys), id: node_id, hir_id, span } }; ( @@ -1778,7 +1787,7 @@ impl<'a> LoweringContext<'a> { ty: output .as_ref() .map(|ty| this.lower_ty(&ty, DISALLOWED)) - .unwrap_or_else(|| mk_tup(this, hir::HirVec::new(), span)), + .unwrap_or_else(|| P(mk_tup(this, hir::HirVec::new(), span))), span: output.as_ref().map_or(span, |ty| ty.span), } ], @@ -1850,9 +1859,9 @@ impl<'a> LoweringContext<'a> { .iter() .map(|arg| { if let Some((def_id, ibty, _)) = in_band_ty_params.as_mut() { - self.lower_ty(&arg.ty, ImplTraitContext::Universal(*def_id, ibty)) + self.lower_ty_direct(&arg.ty, ImplTraitContext::Universal(*def_id, ibty)) } else { - self.lower_ty(&arg.ty, ImplTraitContext::Disallowed) + self.lower_ty_direct(&arg.ty, ImplTraitContext::Disallowed) } }) .collect(), @@ -3302,7 +3311,7 @@ impl<'a> LoweringContext<'a> { let e1 = self.lower_expr(e1); let e2 = self.lower_expr(e2); let ty_path = P(self.std_path(span, &["ops", "RangeInclusive"], false)); - let ty = self.ty_path(id, span, hir::QPath::Resolved(None, ty_path)); + let ty = P(self.ty_path(id, span, hir::QPath::Resolved(None, ty_path))); let new_seg = P(hir::PathSegment::from_name(Symbol::intern("new"))); let new_path = hir::QPath::TypeRelative(ty, new_seg); let new = P(self.expr(span, hir::ExprPath(new_path), ThinVec::new())); @@ -4180,7 +4189,7 @@ impl<'a> LoweringContext<'a> { .resolve_str_path(span, self.crate_root, components, is_value) } - fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> P { + fn ty_path(&mut self, id: LoweredNodeId, span: Span, qpath: hir::QPath) -> hir::Ty { let mut id = id; let node = match qpath { hir::QPath::Resolved(None, path) => { @@ -4205,12 +4214,12 @@ impl<'a> LoweringContext<'a> { } _ => hir::TyPath(qpath), }; - P(hir::Ty { + hir::Ty { id: id.node_id, hir_id: id.hir_id, node, span, - }) + } } /// Invoked to create the lifetime argument for a type `&T` diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index f6876113c1176..120d12b6100d6 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -412,7 +412,7 @@ impl GenericArgs { self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized } - pub fn inputs(&self) -> &[P] { + pub fn inputs(&self) -> &[Ty] { if self.parenthesized { for arg in &self.args { match arg { @@ -1660,7 +1660,7 @@ pub enum Ty_ { /// The never type (`!`) TyNever, /// A tuple (`(A, B, C, D,...)`) - TyTup(HirVec>), + TyTup(HirVec), /// A path to a type definition (`module::module::...::Type`), or an /// associated type, e.g. ` as Trait>::Type` or `::Target`. /// @@ -1721,7 +1721,7 @@ pub struct Arg { /// Represents the header (not the body) of a function declaration #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct FnDecl { - pub inputs: HirVec>, + pub inputs: HirVec, pub output: FunctionRetTy, pub variadic: bool, /// True if this function has an `self`, `&self` or `&mut self` receiver diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index f73e0ab2a9d77..67bac22152b70 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -1789,7 +1789,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn visit_fn_like_elision( &mut self, - inputs: &'tcx [P], + inputs: &'tcx [hir::Ty], output: Option<&'tcx P>, ) { debug!("visit_fn_like_elision: enter"); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index f76b312ee530d..7ea86c7be7296 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -964,7 +964,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .. }) => { (self.tcx.sess.codemap().def_span(span), decl.inputs.iter() - .map(|arg| match arg.clone().into_inner().node { + .map(|arg| match arg.clone().node { hir::TyTup(ref tys) => ArgKind::Tuple( Some(arg.span), tys.iter() From 47732a4f4f2d76bae588a8a16489f8a0b8d65daf Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 21 Jun 2018 16:28:02 +0200 Subject: [PATCH 13/20] Prevent lowering item ids from behaving differently than lowering items --- src/librustc/hir/lowering.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 037cc32f090d7..d3c8bc18dfcdd 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2797,11 +2797,28 @@ impl<'a> LoweringContext<'a> { struct IdVisitor { ids: SmallVector } impl<'a> Visitor<'a> for IdVisitor { fn visit_ty(&mut self, ty: &'a Ty) { - if let TyKind::ImplTrait(id, _) = ty.node { - self.ids.push(hir::ItemId { id }); + 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.parameters { + if let PathParameters::Parenthesized(..) = **p { + return; + } + } + visit::walk_path_segment(self, path_span, path_segment) + } } let mut visitor = IdVisitor { ids: SmallVector::one(hir::ItemId { id: i.id }) }; match decl.output { From 057cf0ff8c8138913c471ac165e78b8e0507dd0f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 21 Jun 2018 18:49:34 +0200 Subject: [PATCH 14/20] Update rustdoc --- src/librustdoc/clean/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 0979c3d85587d..b47af2fa30ef1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2159,7 +2159,7 @@ pub struct Arguments { pub values: Vec, } -impl<'a> Clean for (&'a [P], &'a [Spanned]) { +impl<'a> Clean for (&'a [hir::Ty], &'a [Spanned]) { fn clean(&self, cx: &DocContext) -> Arguments { Arguments { values: self.0.iter().enumerate().map(|(i, ty)| { @@ -2177,7 +2177,7 @@ impl<'a> Clean for (&'a [P], &'a [Spanned]) { } } -impl<'a> Clean for (&'a [P], hir::BodyId) { +impl<'a> Clean for (&'a [hir::Ty], hir::BodyId) { fn clean(&self, cx: &DocContext) -> Arguments { let body = cx.tcx.hir.body(self.1); @@ -2193,7 +2193,7 @@ impl<'a> Clean for (&'a [P], hir::BodyId) { } impl<'a, A: Copy> Clean for (&'a hir::FnDecl, A) - where (&'a [P], A): Clean + where (&'a [hir::Ty], A): Clean { fn clean(&self, cx: &DocContext) -> FnDecl { FnDecl { @@ -2929,7 +2929,7 @@ impl Clean for hir::Ty { } }); if let Some(ty) = type_.cloned() { - ty_substs.insert(ty_param_def, ty.into_inner().clean(cx)); + ty_substs.insert(ty_param_def, ty.clean(cx)); } else if let Some(default) = default.clone() { ty_substs.insert(ty_param_def, default.into_inner().clean(cx)); From 1bf351dd870f2e8b99bb29f4c08c388e7b8cea7c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 22 Jun 2018 10:46:16 +0200 Subject: [PATCH 15/20] We now have proper locations for the `existential type` items. --- src/librustc/hir/intravisit.rs | 3 +- src/librustc/middle/resolve_lifetime.rs | 3 +- src/librustc_privacy/lib.rs | 44 +++++++++---------------- 3 files changed, 17 insertions(+), 33 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index ed86ef705649b..4ec8ea8689adf 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -610,9 +610,8 @@ 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) => { 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/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 67bac22152b70..039fc0550c766 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -498,13 +498,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }; self.with(scope, |_, this| intravisit::walk_item(this, item)); } - hir::ItemExistential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => { + hir::ItemExistential(hir::ExistTy { .. }) => { // currently existential type declarations are just generated from impl Trait // items. doing anything on this node is irrelevant, as we currently don't need // it. } hir::ItemTy(_, ref generics) - | hir::ItemExistential(hir::ExistTy { impl_trait_fn: None, ref generics, .. }) | hir::ItemEnum(_, ref generics) | hir::ItemStruct(_, ref generics) | hir::ItemUnion(_, ref generics) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index de087049267b1..44c855f89a45d 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -229,8 +229,12 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemUse(..) => {} // The interface is empty hir::ItemGlobalAsm(..) => {} - // Checked by visit_ty - hir::ItemExistential(..) => {} + hir::ItemExistential(..) => { + if item_level.is_some() { + // Reach the (potentially private) type and the API being exposed + self.reach(item.id).ty().predicates(); + } + } // Visit everything hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) | hir::ItemTy(..) => { @@ -390,17 +394,6 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { module_id = self.tcx.hir.get_parent_node(module_id); } } - - fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if let hir::TyImplTraitExistential(item_id, _, _) = ty.node { - if self.get(item_id.id).is_some() { - // Reach the (potentially private) type and the API being exposed - self.reach(item_id.id).ty().predicates(); - } - } - - intravisit::walk_ty(self, ty); - } } impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { @@ -1556,8 +1549,15 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> hir::ItemUse(..) => {} // No subitems hir::ItemGlobalAsm(..) => {} - // Checked in visit_ty - hir::ItemExistential(..) => {} + hir::ItemExistential(..) => { + // Check the traits being exposed, as they're separate, + // e.g. `impl Iterator` has two predicates, + // `X: Iterator` and `::Item == T`, + // where `X` is the `impl Iterator` itself, + // stored in `predicates_of`, not in the `Ty` itself. + + self.check(item.id, self.inner_visibility).predicates(); + } // Subitems of these items have inherited publicity hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) | hir::ItemTy(..) => { @@ -1655,20 +1655,6 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> // handled in `visit_item` above } - fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - if let hir::TyImplTraitExistential(ref exist_item, _, _) = ty.node { - // Check the traits being exposed, as they're separate, - // e.g. `impl Iterator` has two predicates, - // `X: Iterator` and `::Item == T`, - // where `X` is the `impl Iterator` itself, - // stored in `predicates_of`, not in the `Ty` itself. - - self.check(exist_item.id, self.inner_visibility).predicates(); - } - - intravisit::walk_ty(self, ty); - } - // Don't recurse into expressions in array sizes or const initializers fn visit_expr(&mut self, _: &'tcx hir::Expr) {} // Don't recurse into patterns in function arguments From 356d68385de40c368c27e396229c5bbce24e9c90 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 22 Jun 2018 12:03:44 +0200 Subject: [PATCH 16/20] Also place method impl trait into the surrounding module --- src/librustc/hir/lowering.rs | 79 ++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index d3c8bc18dfcdd..8946304f28a97 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2785,6 +2785,45 @@ impl<'a> LoweringContext<'a> { } } + /// Lowers `impl Trait` items and appends them to the list + fn lower_impl_trait_ids( + &mut self, + decl: &FnDecl, + ids: &mut SmallVector, + ) { + 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.parameters { + if let PathParameters::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) => { @@ -2794,38 +2833,18 @@ impl<'a> LoweringContext<'a> { } ItemKind::MacroDef(..) => SmallVector::new(), ItemKind::Fn(ref decl, ..) => { - struct IdVisitor { ids: SmallVector } - impl<'a> Visitor<'a> for IdVisitor { - 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.parameters { - if let PathParameters::Parenthesized(..) = **p { - return; - } - } - visit::walk_path_segment(self, path_span, path_segment) + let mut ids = SmallVector::one(hir::ItemId { id: i.id }); + self.lower_impl_trait_ids(decl, &mut ids); + ids + }, + ItemKind::Impl(.., 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, &mut ids); } } - let mut visitor = IdVisitor { ids: SmallVector::one(hir::ItemId { id: i.id }) }; - match decl.output { - FunctionRetTy::Default(_) => {}, - FunctionRetTy::Ty(ref ty) => visitor.visit_ty(ty), - } - visitor.ids + ids }, _ => SmallVector::one(hir::ItemId { id: i.id }), } From 398a5f89e3585781c4ba92736cb55014a43d4c72 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 22 Jun 2018 15:00:52 +0200 Subject: [PATCH 17/20] Ignore existential type items during collection for now --- src/librustc_typeck/collect.rs | 2 +- src/test/ui/impl-trait/auto-trait-leak.rs | 2 - src/test/ui/impl-trait/auto-trait-leak.stderr | 56 +++---------------- 3 files changed, 10 insertions(+), 50 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4c849cad187ab..efc747531214f 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -419,7 +419,7 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) { convert_variant_ctor(tcx, struct_def.id()); } }, - hir::ItemExistential(..) | + hir::ItemExistential(..) => {} hir::ItemTy(..) | hir::ItemStatic(..) | hir::ItemConst(..) | hir::ItemFn(..) => { tcx.generics_of(def_id); tcx.type_of(def_id); diff --git a/src/test/ui/impl-trait/auto-trait-leak.rs b/src/test/ui/impl-trait/auto-trait-leak.rs index f6b64b394fc12..a594ee8aab42a 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.rs +++ b/src/test/ui/impl-trait/auto-trait-leak.rs @@ -23,9 +23,7 @@ fn main() { // return type, which can't depend on the obligation. fn cycle1() -> impl Clone { //~^ ERROR cycle detected - //~| ERROR cycle detected send(cycle2().clone()); - //~^ ERROR `std::rc::Rc` cannot be sent between threads safely Rc::new(Cell::new(5)) } diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index 10711d1cd8cec..6681116f0f393 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -1,67 +1,29 @@ -error[E0391]: cycle detected when processing `cycle1::{{impl-Trait}}` - --> $DIR/auto-trait-leak.rs:24:16 - | -LL | fn cycle1() -> impl Clone { - | ^^^^^^^^^^ - | -note: ...which requires processing `cycle1`... +error[E0391]: cycle detected when processing `cycle1` --> $DIR/auto-trait-leak.rs:24:1 | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... note: ...which requires processing `cycle2::{{impl-Trait}}`... - --> $DIR/auto-trait-leak.rs:33:16 + --> $DIR/auto-trait-leak.rs:31:16 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ note: ...which requires processing `cycle2`... - --> $DIR/auto-trait-leak.rs:33:1 + --> $DIR/auto-trait-leak.rs:31:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... - = note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle - -error[E0391]: cycle detected when processing `cycle1::{{impl-Trait}}` +note: ...which requires processing `cycle1::{{impl-Trait}}`... --> $DIR/auto-trait-leak.rs:24:16 | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^ - | -note: ...which requires processing `cycle1`... - --> $DIR/auto-trait-leak.rs:24:1 - | -LL | fn cycle1() -> impl Clone { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... -note: ...which requires processing `cycle2::{{impl-Trait}}`... - --> $DIR/auto-trait-leak.rs:33:16 - | -LL | fn cycle2() -> impl Clone { - | ^^^^^^^^^^ -note: ...which requires processing `cycle2`... - --> $DIR/auto-trait-leak.rs:33:1 - | -LL | fn cycle2() -> impl Clone { - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle - -error[E0277]: `std::rc::Rc` cannot be sent between threads safely - --> $DIR/auto-trait-leak.rs:27:5 - | -LL | send(cycle2().clone()); - | ^^^^ `std::rc::Rc` cannot be sent between threads safely - | - = help: within `impl std::clone::Clone`, the trait `std::marker::Send` is not implemented for `std::rc::Rc` - = note: required because it appears within the type `impl std::clone::Clone` -note: required by `send` - --> $DIR/auto-trait-leak.rs:16:1 - | -LL | fn send(_: T) {} - | ^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires processing `cycle1`, completing the cycle +note: cycle used when type-checking all item bodies -error: aborting due to 3 previous errors +error: aborting due to previous error -Some errors occurred: E0277, E0391. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0391`. From 9859a529f318e5109e709bb8430b59600a82d98e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 22 Jun 2018 15:01:47 +0200 Subject: [PATCH 18/20] Don't try to do impl Trait lowering for `impl Trait for Type` items --- src/librustc/hir/lowering.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 8946304f28a97..7077ef3db2340 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2837,7 +2837,7 @@ impl<'a> LoweringContext<'a> { self.lower_impl_trait_ids(decl, &mut ids); ids }, - ItemKind::Impl(.., ref items) => { + 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 { From a1527702c31452c7d7d6edb13acc87fed8134cb9 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 25 Jun 2018 10:03:22 +0200 Subject: [PATCH 19/20] Generics Unification rebase fallout --- src/librustc/hir/lowering.rs | 51 ++++++++++++++++++------------------ src/librustc/hir/mod.rs | 2 +- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 7077ef3db2340..1274df4fb7260 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -174,7 +174,7 @@ enum ImplTraitContext<'a> { /// We store a DefId here so we can look up necessary information later /// /// Newly generated parameters should be inserted into the given `Vec` - Universal(DefId, &'a mut Vec), + Universal(DefId, &'a mut Vec), /// Treat `impl Trait` as shorthand for a new universal existential parameter. /// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually @@ -183,7 +183,7 @@ enum ImplTraitContext<'a> { /// We store a DefId here so we can look up necessary information later /// /// All generics of the surrounding function must go into the generated existential type - Existential(DefId, &'a [hir::TyParam], &'a hir::Generics), + Existential(DefId, &'a [hir::GenericParam], &'a hir::Generics), /// `impl Trait` is not accepted in this position. Disallowed, @@ -656,7 +656,7 @@ impl<'a> LoweringContext<'a> { f: F, ) -> (Vec, T) where - F: FnOnce(&mut LoweringContext) -> (Vec, T), + F: FnOnce(&mut LoweringContext) -> (Vec, T), { assert!(!self.is_collecting_in_band_lifetimes); assert!(self.lifetimes_to_define.is_empty()); @@ -804,7 +804,7 @@ impl<'a> LoweringContext<'a> { f: F, ) -> (hir::Generics, T) where - F: FnOnce(&mut LoweringContext, &mut Vec, &hir::Generics) -> T, + F: FnOnce(&mut LoweringContext, &mut Vec, &hir::Generics) -> T, { let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs( &generics.params, @@ -1045,7 +1045,7 @@ impl<'a> LoweringContext<'a> { -> hir::GenericArg { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), - ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty(&ty, itctx)), + ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty_direct(&ty, itctx)), } } @@ -1175,7 +1175,7 @@ impl<'a> LoweringContext<'a> { lctx.lower_param_bounds(bounds, itctx) }); - let (path_params, params) = self.generics_from_impl_trait_bounds( + let (params, lifetimes) = self.generics_from_impl_trait_bounds( def_node_id, exist_ty_def_index, &hir_bounds, @@ -1222,7 +1222,7 @@ impl<'a> LoweringContext<'a> { id: exist_ty_id.node_id }, DefId::local(exist_ty_def_index), - path_params.lifetimes, + lifetimes, ) }) } @@ -1241,7 +1241,7 @@ impl<'a> LoweringContext<'a> { ); // Set the name to `impl Bound1 + Bound2` let name = Symbol::intern(&pprust::ty_to_string(t)); - self.in_band_ty_params.push(hir::GenericParam { + in_band_ty_params.push(hir::GenericParam { id: def_node_id, name: ParamName::Plain(name), span, @@ -1292,7 +1292,7 @@ impl<'a> LoweringContext<'a> { exist_ty_id: NodeId, parent_index: DefIndex, bounds: &hir::GenericBounds, - ) -> (hir::PathParameters, HirVec) { + ) -> (HirVec, HirVec) { // This visitor walks over impl trait bounds and creates defs for all lifetimes which // appear in the bounds, excluding lifetimes that are created within the bounds. // e.g. 'a, 'b, but not 'c in `impl for<'c> SomeTrait<'a, 'b, 'c>` @@ -1408,15 +1408,15 @@ impl<'a> LoweringContext<'a> { lifetime.span, ); - let name = match name { + let (in_band, name) = match name { hir::LifetimeName::Underscore => { - hir::ParamName::Plain(keywords::UnderscoreLifetime.name()) + (true, hir::ParamName::Plain(keywords::UnderscoreLifetime.name())) } - hir::LifetimeName::Param(param_name) => param_name, + hir::LifetimeName::Param(param_name) => (false, param_name), _ => bug!("expected LifetimeName::Param or ParamName::Plain"), }; - self.output_lifetime_params.push(hir::GenericParam { + self.output_params.push(hir::GenericParam { id: def_node_id, name, span: lifetime.span, @@ -1424,7 +1424,7 @@ impl<'a> LoweringContext<'a> { attrs: hir_vec![], bounds: hir_vec![], kind: hir::GenericParamKind::Lifetime { - in_band: false, + in_band, } }); } @@ -1447,13 +1447,8 @@ impl<'a> LoweringContext<'a> { } ( - hir::PathParameters { - lifetimes: lifetime_collector.output_lifetimes.into(), - types: HirVec::new(), - bindings: HirVec::new(), - parenthesized: false, - }, lifetime_collector.output_params.into(), + lifetime_collector.output_lifetimes.into(), ) } @@ -1844,7 +1839,7 @@ impl<'a> LoweringContext<'a> { fn lower_fn_decl( &mut self, decl: &FnDecl, - mut in_band_ty_params: Option<(DefId, &mut Vec, &hir::Generics)>, + mut in_band_ty_params: Option<(DefId, &mut Vec, &hir::Generics)>, impl_trait_return_allow: bool, ) -> P { // NOTE: The two last parameters here have to do with impl Trait. If fn_def_id is Some, @@ -1943,15 +1938,19 @@ impl<'a> LoweringContext<'a> { add_bounds: &NodeMap>, mut itctx: ImplTraitContext, ) -> hir::HirVec { - params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect() + params.iter().map(|param| self.lower_generic_param( + param, + add_bounds, + itctx.reborrow(), + )).collect() } fn lower_generic_param(&mut self, param: &GenericParam, add_bounds: &NodeMap>, - itctx: ImplTraitContext) + mut itctx: ImplTraitContext) -> hir::GenericParam { - let mut bounds = self.lower_param_bounds(¶m.bounds, itctx); + let mut bounds = self.lower_param_bounds(¶m.bounds, itctx.reborrow()); match param.kind { GenericParamKind::Lifetime => { let was_collecting_in_band = self.is_collecting_in_band_lifetimes; @@ -2809,8 +2808,8 @@ impl<'a> LoweringContext<'a> { path_span: Span, path_segment: &'v PathSegment, ) { - if let Some(ref p) = path_segment.parameters { - if let PathParameters::Parenthesized(..) = **p { + if let Some(ref p) = path_segment.args { + if let GenericArgs::Parenthesized(..) = **p { return; } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 120d12b6100d6..cf00e83af6b25 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -383,7 +383,7 @@ impl PathSegment { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub enum GenericArg { Lifetime(Lifetime), - Type(P), + Type(Ty), } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] From 922249c1faea7cb32662faac6be4ac8b3aac00b2 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 25 Jun 2018 10:06:22 +0200 Subject: [PATCH 20/20] Update tests --- src/test/ui/error-codes/E0657.rs | 4 +-- src/test/ui/error-codes/E0657.stderr | 23 ++-------------- src/test/ui/impl_trait_projections.rs | 5 ++-- src/test/ui/impl_trait_projections.stderr | 33 +++-------------------- 4 files changed, 9 insertions(+), 56 deletions(-) diff --git a/src/test/ui/error-codes/E0657.rs b/src/test/ui/error-codes/E0657.rs index 05a4b8b3544f5..c23aa40ee3790 100644 --- a/src/test/ui/error-codes/E0657.rs +++ b/src/test/ui/error-codes/E0657.rs @@ -19,7 +19,7 @@ fn free_fn_capture_hrtb_in_impl_trait() -> Box Id>> //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657] { - () //~ ERROR mismatched types + () } struct Foo; @@ -28,7 +28,7 @@ impl Foo { -> Box Id>> //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level { - () //~ ERROR mismatched types + () } } diff --git a/src/test/ui/error-codes/E0657.stderr b/src/test/ui/error-codes/E0657.stderr index 23b9666de3cd9..737ae3a163ac2 100644 --- a/src/test/ui/error-codes/E0657.stderr +++ b/src/test/ui/error-codes/E0657.stderr @@ -10,25 +10,6 @@ error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl le LL | -> Box Id>> | ^^ -error[E0308]: mismatched types - --> $DIR/E0657.rs:22:5 - | -LL | () //~ ERROR mismatched types - | ^^ expected struct `std::boxed::Box`, found () - | - = note: expected type `std::boxed::Box + 'static>` - found type `()` - -error[E0308]: mismatched types - --> $DIR/E0657.rs:31:9 - | -LL | () //~ ERROR mismatched types - | ^^ expected struct `std::boxed::Box`, found () - | - = note: expected type `std::boxed::Box + 'static>` - found type `()` - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors occurred: E0308, E0657. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0657`. diff --git a/src/test/ui/impl_trait_projections.rs b/src/test/ui/impl_trait_projections.rs index b64caccd98abe..57a0040600a25 100644 --- a/src/test/ui/impl_trait_projections.rs +++ b/src/test/ui/impl_trait_projections.rs @@ -34,9 +34,8 @@ fn projection_with_named_trait_is_disallowed(x: impl Iterator) fn projection_with_named_trait_inside_path_is_disallowed() -> <::std::ops::Range as Iterator>::Item //~^ ERROR `impl Trait` is not allowed in path parameters -//~| ERROR trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied -{ //~ ERROR trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied - (1i32..100).next().unwrap() //~ ERROR mismatched types +{ + (1i32..100).next().unwrap() } fn projection_from_impl_trait_inside_dyn_trait_is_disallowed() diff --git a/src/test/ui/impl_trait_projections.stderr b/src/test/ui/impl_trait_projections.stderr index b495d4b4b010b..f6d58984ecef7 100644 --- a/src/test/ui/impl_trait_projections.stderr +++ b/src/test/ui/impl_trait_projections.stderr @@ -17,7 +17,7 @@ LL | -> <::std::ops::Range as Iterator>::Item | ^^^^^^^^^^ error[E0667]: `impl Trait` is not allowed in path parameters - --> $DIR/impl_trait_projections.rs:43:29 + --> $DIR/impl_trait_projections.rs:42:29 | LL | -> as Iterator>::Item | ^^^^^^^^^^ @@ -30,34 +30,7 @@ LL | fn projection_is_disallowed(x: impl Iterator) -> ::Item { | = note: specify the type using the syntax `::Item` -error[E0277]: the trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied - --> $DIR/impl_trait_projections.rs:38:1 - | -LL | / { //~ ERROR trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied -LL | | (1i32..100).next().unwrap() //~ ERROR mismatched types -LL | | } - | |_^ the trait `std::iter::Step` is not implemented for `impl std::fmt::Debug` - | - = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::Range` - -error[E0308]: mismatched types - --> $DIR/impl_trait_projections.rs:39:5 - | -LL | (1i32..100).next().unwrap() //~ ERROR mismatched types - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected anonymized type, found i32 - | - = note: expected type `impl std::fmt::Debug` - found type `i32` - -error[E0277]: the trait bound `impl std::fmt::Debug: std::iter::Step` is not satisfied - --> $DIR/impl_trait_projections.rs:35:8 - | -LL | -> <::std::ops::Range as Iterator>::Item - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::iter::Step` is not implemented for `impl std::fmt::Debug` - | - = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::ops::Range` - -error: aborting due to 8 previous errors +error: aborting due to 5 previous errors -Some errors occurred: E0223, E0277, E0308, E0667. +Some errors occurred: E0223, E0667. For more information about an error, try `rustc --explain E0223`.