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/hir/lowering.rs b/src/librustc/hir/lowering.rs index 6291e0eb11372..1274df4fb7260 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::GenericParam], &'a hir::Generics), /// `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, generics) => Existential(*did, params, generics), + 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, &hir::Generics) -> 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, &generics); + (params, (generics, res)) }) }, ); @@ -1035,11 +1045,15 @@ 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)), } } 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, @@ -1076,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)).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); @@ -1110,7 +1129,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) => { @@ -1128,16 +1147,10 @@ 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) => { - - // 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(); - + 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. @@ -1148,36 +1161,30 @@ 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, - exist_ty_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(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 (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds( - exist_ty_node_id, + let (params, lifetimes) = self.generics_from_impl_trait_bounds( + 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: lifetime_defs, + params, where_clause: hir::WhereClause { id: lctx.next_id().node_id, predicates: Vec::new().into(), @@ -1187,7 +1194,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` @@ -1219,23 +1226,22 @@ impl<'a> LoweringContext<'a> { ) }) } - ImplTraitContext::Universal(def_id) => { - let def_node_id = self.next_id().node_id; - + 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, 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 { + in_band_ty_params.push(hir::GenericParam { id: def_node_id, name: ParamName::Plain(name), span, @@ -1273,20 +1279,20 @@ 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 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) { + ) -> (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>` @@ -1298,7 +1304,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> { @@ -1321,20 +1327,21 @@ 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 { - 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); - - self.collect_elided_lifetimes = old_collect_elided_lifetimes; - } else { - hir::intravisit::walk_ty(self, t); + match t.node { + // 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; + + // 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; + }, + _ => hir::intravisit::walk_ty(self, t), } } @@ -1401,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, @@ -1417,7 +1424,7 @@ impl<'a> LoweringContext<'a> { attrs: hir_vec![], bounds: hir_vec![], kind: hir::GenericParamKind::Lifetime { - in_band: false, + in_band, } }); } @@ -1432,7 +1439,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 +1447,8 @@ impl<'a> LoweringContext<'a> { } ( + lifetime_collector.output_params.into(), lifetime_collector.output_lifetimes.into(), - lifetime_collector.output_lifetime_params.into(), ) } @@ -1480,10 +1487,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 +1577,7 @@ impl<'a> LoweringContext<'a> { param_mode, num_lifetimes, parenthesized_generic_args, - itctx, + itctx.reborrow(), ) }) .collect(), @@ -1593,7 +1600,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", @@ -1613,7 +1620,7 @@ impl<'a> LoweringContext<'a> { param_mode, 0, ParenthesizedGenericArgs::Warn, - itctx, + itctx.reborrow(), )); let qpath = hir::QPath::TypeRelative(ty, segment); @@ -1624,7 +1631,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. @@ -1730,7 +1737,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 +1745,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) @@ -1759,10 +1766,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 } }; ( @@ -1775,7 +1782,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), } ], @@ -1832,7 +1839,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, &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, @@ -1846,17 +1853,21 @@ 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_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(), 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, 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)), }, @@ -1889,24 +1900,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( @@ -1926,17 +1936,21 @@ 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() + 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; @@ -1974,7 +1988,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(); } @@ -2169,10 +2186,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), @@ -2217,9 +2234,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 { @@ -2295,7 +2312,11 @@ impl<'a> LoweringContext<'a> { generics, fn_def_id, AnonymousLifetimeMode::PassThrough, - |this| this.lower_fn_decl(decl, Some(fn_def_id), true), + |this, idty, generics| this.lower_fn_decl( + decl, + Some((fn_def_id, idty, generics)), + true, + ), ); hir::ItemFn( @@ -2367,7 +2388,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) }); @@ -2614,17 +2635,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 +2649,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 +2727,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), @@ -2779,17 +2784,69 @@ 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.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, ..) => { + let mut ids = SmallVector::one(hir::ItemId { id: i.id }); + self.lower_impl_trait_ids(decl, &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, &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, @@ -2862,7 +2919,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), @@ -2886,16 +2943,32 @@ 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, idty, generics| this.lower_fn_decl( + &sig.decl, + Some((fn_def_id, idty, generics)), + impl_trait_return_allow, + ), + ); + ( + generics, + hir::MethodSig { + abi: sig.abi, + unsafety, + constness, + decl, + }, + ) } fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto { @@ -3273,7 +3346,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())); @@ -4151,7 +4224,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) => { @@ -4176,12 +4249,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/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()) } } 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/hir/mod.rs b/src/librustc/hir/mod.rs index f6876113c1176..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)] @@ -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..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) @@ -1789,7 +1788,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() 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 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_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 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/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/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)); 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) => { 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/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/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 b34facd2d39ce..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::{{exist-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::{{exist-impl-Trait}}`... - --> $DIR/auto-trait-leak.rs:33:16 +note: ...which requires processing `cycle2::{{impl-Trait}}`... + --> $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::{{exist-impl-Trait}}`, completing the cycle - -error[E0391]: cycle detected when processing `cycle1::{{exist-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::{{exist-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::{{exist-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`. 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`.