diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 12ccb329e06ff..ed86ef705649b 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -314,8 +314,8 @@ pub trait Visitor<'v> : Sized { fn visit_trait_ref(&mut self, t: &'v TraitRef) { walk_trait_ref(self, t) } - fn visit_ty_param_bound(&mut self, bounds: &'v TyParamBound) { - walk_ty_param_bound(self, bounds) + fn visit_param_bound(&mut self, bounds: &'v GenericBound) { + walk_param_bound(self, bounds) } fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef, m: TraitBoundModifier) { walk_poly_trait_ref(self, t, m) @@ -344,6 +344,12 @@ pub trait Visitor<'v> : Sized { fn visit_label(&mut self, label: &'v Label) { walk_label(self, label) } + fn visit_generic_arg(&mut self, generic_arg: &'v GenericArg) { + match generic_arg { + GenericArg::Lifetime(lt) => self.visit_lifetime(lt), + GenericArg::Type(ty) => self.visit_ty(ty), + } + } fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { walk_lifetime(self, lifetime) } @@ -356,8 +362,8 @@ pub trait Visitor<'v> : Sized { fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) { walk_path_segment(self, path_span, path_segment) } - fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'v PathParameters) { - walk_path_parameters(self, path_span, path_parameters) + fn visit_generic_args(&mut self, path_span: Span, generic_args: &'v GenericArgs) { + walk_generic_args(self, path_span, generic_args) } fn visit_assoc_type_binding(&mut self, type_binding: &'v TypeBinding) { walk_assoc_type_binding(self, type_binding) @@ -427,10 +433,10 @@ pub fn walk_label<'v, V: Visitor<'v>>(visitor: &mut V, label: &'v Label) { pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime) { visitor.visit_id(lifetime.id); match lifetime.name { - LifetimeName::Name(name) => { + LifetimeName::Param(ParamName::Plain(name)) => { visitor.visit_name(lifetime.span, name); } - LifetimeName::Fresh(_) | + LifetimeName::Param(ParamName::Fresh(_)) | LifetimeName::Static | LifetimeName::Implicit | LifetimeName::Underscore => {} @@ -505,7 +511,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { ItemExistential(ExistTy {ref generics, ref bounds, impl_trait_fn}) => { visitor.visit_id(item.id); walk_generics(visitor, generics); - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); if let Some(impl_trait_fn) = impl_trait_fn { visitor.visit_def_mention(Def::Fn(impl_trait_fn)) } @@ -531,13 +537,13 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { ItemTrait(.., ref generics, ref bounds, ref trait_item_refs) => { visitor.visit_id(item.id); visitor.visit_generics(generics); - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_trait_item_ref, trait_item_refs); } ItemTraitAlias(ref generics, ref bounds) => { visitor.visit_id(item.id); visitor.visit_generics(generics); - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); } } walk_list!(visitor, visit_attribute, &item.attrs); @@ -642,17 +648,16 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, path_span: Span, segment: &'v PathSegment) { visitor.visit_name(path_span, segment.name); - if let Some(ref parameters) = segment.parameters { - visitor.visit_path_parameters(path_span, parameters); + if let Some(ref args) = segment.args { + visitor.visit_generic_args(path_span, args); } } -pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V, - _path_span: Span, - path_parameters: &'v PathParameters) { - walk_list!(visitor, visit_lifetime, &path_parameters.lifetimes); - walk_list!(visitor, visit_ty, &path_parameters.types); - walk_list!(visitor, visit_assoc_type_binding, &path_parameters.bindings); +pub fn walk_generic_args<'v, V: Visitor<'v>>(visitor: &mut V, + _path_span: Span, + generic_args: &'v GenericArgs) { + walk_list!(visitor, visit_generic_arg, &generic_args.args); + walk_list!(visitor, visit_assoc_type_binding, &generic_args.bindings); } pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V, @@ -726,40 +731,27 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>(visitor: &mut V, foreign_item: &'v walk_list!(visitor, visit_attribute, &foreign_item.attrs); } -pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyParamBound) { +pub fn walk_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v GenericBound) { match *bound { - TraitTyParamBound(ref typ, modifier) => { + GenericBound::Trait(ref typ, modifier) => { visitor.visit_poly_trait_ref(typ, modifier); } - RegionTyParamBound(ref lifetime) => { - visitor.visit_lifetime(lifetime); - } + GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), } } pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam) { - match *param { - GenericParam::Lifetime(ref ld) => { - visitor.visit_id(ld.lifetime.id); - match ld.lifetime.name { - LifetimeName::Name(name) => { - visitor.visit_name(ld.lifetime.span, name); - } - LifetimeName::Fresh(_) | - LifetimeName::Static | - LifetimeName::Implicit | - LifetimeName::Underscore => {} - } - walk_list!(visitor, visit_lifetime, &ld.bounds); - } - GenericParam::Type(ref ty_param) => { - visitor.visit_id(ty_param.id); - visitor.visit_name(ty_param.span, ty_param.name); - walk_list!(visitor, visit_ty_param_bound, &ty_param.bounds); - walk_list!(visitor, visit_ty, &ty_param.default); - walk_list!(visitor, visit_attribute, ty_param.attrs.iter()); - } + visitor.visit_id(param.id); + walk_list!(visitor, visit_attribute, ¶m.attrs); + match param.name { + ParamName::Plain(name) => visitor.visit_name(param.span, name), + ParamName::Fresh(_) => {} + } + match param.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default), } + walk_list!(visitor, visit_param_bound, ¶m.bounds); } pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) { @@ -778,14 +770,14 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( ref bound_generic_params, ..}) => { visitor.visit_ty(bounded_ty); - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_generic_param, bound_generic_params); } &WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime, ref bounds, ..}) => { visitor.visit_lifetime(lifetime); - walk_list!(visitor, visit_lifetime, bounds); + walk_list!(visitor, visit_param_bound, bounds); } &WherePredicate::EqPredicate(WhereEqPredicate{id, ref lhs_ty, @@ -862,7 +854,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai } TraitItemKind::Type(ref bounds, ref default) => { visitor.visit_id(trait_item.id); - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, default); } } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index dd12edb73027a..6291e0eb11372 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -41,11 +41,12 @@ //! in the HIR, especially for multiple identifiers. use dep_graph::DepGraph; -use hir; +use hir::{self, ParamName}; use hir::HirVec; use hir::map::{DefKey, DefPathData, Definitions}; use hir::def_id::{DefId, DefIndex, DefIndexAddressSpace, CRATE_DEF_INDEX}; use hir::def::{Def, PathResolution, PerNS}; +use hir::GenericArg; use lint::builtin::{self, PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES}; use middle::cstore::CrateStore; use rustc_data_structures::indexed_vec::IndexVec; @@ -58,6 +59,7 @@ use std::fmt::Debug; use std::iter; use std::mem; use syntax::attr; +use syntax::ast; use syntax::ast::*; use syntax::errors; use syntax::ext::hygiene::{Mark, SyntaxContext}; @@ -114,7 +116,7 @@ pub struct LoweringContext<'a> { // 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, + 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` @@ -123,7 +125,7 @@ pub struct LoweringContext<'a> { // (i.e. it doesn't appear in the in_scope_lifetimes list), it is added // to this list. The results of this list are then added to the list of // lifetime definitions in the corresponding impl or function generics. - lifetimes_to_define: Vec<(Span, hir::LifetimeName)>, + lifetimes_to_define: Vec<(Span, ParamName)>, // Whether or not in-band lifetimes are being collected. This is used to // indicate whether or not we're in a place where new lifetimes will result @@ -322,7 +324,10 @@ impl<'a> LoweringContext<'a> { let count = generics .params .iter() - .filter(|param| param.is_lifetime_param()) + .filter(|param| match param.kind { + ast::GenericParamKind::Lifetime { .. } => true, + _ => false, + }) .count(); self.lctx.type_def_lifetime_params.insert(def_id, count); } @@ -374,25 +379,24 @@ impl<'a> LoweringContext<'a> { }); if item_lowered { - let item_lifetimes = match self.lctx.items.get(&item.id).unwrap().node { + let item_generics = match self.lctx.items.get(&item.id).unwrap().node { hir::Item_::ItemImpl(_, _, _, ref generics, ..) | hir::Item_::ItemTrait(_, _, ref generics, ..) => { - generics.lifetimes().cloned().collect::>() + generics.params.clone() } - _ => Vec::new(), + _ => HirVec::new(), }; - self.lctx - .with_parent_impl_lifetime_defs(&item_lifetimes, |this| { - let this = &mut ItemLowerer { lctx: this }; - if let ItemKind::Impl(_, _, _, _, ref opt_trait_ref, _, _) = item.node { - this.with_trait_impl_ref(opt_trait_ref, |this| { - visit::walk_item(this, item) - }); - } else { - visit::walk_item(this, item); - } - }); + self.lctx.with_parent_impl_lifetime_defs(&item_generics, |this| { + let this = &mut ItemLowerer { lctx: this }; + if let ItemKind::Impl(_, _, _, _, ref opt_trait_ref, _, _) = item.node { + this.with_trait_impl_ref(opt_trait_ref, |this| { + visit::walk_item(this, item) + }); + } else { + visit::walk_item(this, item); + } + }); } } @@ -674,41 +678,31 @@ impl<'a> LoweringContext<'a> { // that collisions are ok here and this shouldn't // really show up for end-user. let str_name = match hir_name { - hir::LifetimeName::Name(n) => n.as_str(), - hir::LifetimeName::Fresh(_) => keywords::UnderscoreLifetime.name().as_str(), - hir::LifetimeName::Implicit - | hir::LifetimeName::Underscore - | hir::LifetimeName::Static => { - span_bug!(span, "unexpected in-band lifetime name: {:?}", hir_name) - } + ParamName::Plain(name) => name.as_str(), + ParamName::Fresh(_) => keywords::UnderscoreLifetime.name().as_str(), }; // Add a definition for the in-band lifetime def self.resolver.definitions().create_def_with_parent( parent_id.index, def_node_id, - DefPathData::LifetimeDef(str_name.as_interned_str()), + DefPathData::LifetimeParam(str_name.as_interned_str()), DefIndexAddressSpace::High, Mark::root(), span, ); - hir::GenericParam::Lifetime(hir::LifetimeDef { - lifetime: hir::Lifetime { - id: def_node_id, - span, - name: hir_name, - }, - bounds: Vec::new().into(), + hir::GenericParam { + id: def_node_id, + name: hir_name, + attrs: hir_vec![], + bounds: hir_vec![], + span, pure_wrt_drop: false, - in_band: true, - }) + kind: hir::GenericParamKind::Lifetime { in_band: true } + } }) - .chain( - in_band_ty_params - .into_iter() - .map(|tp| hir::GenericParam::Type(tp)), - ) + .chain(in_band_ty_params.into_iter()) .collect(); (params, res) @@ -727,12 +721,9 @@ impl<'a> LoweringContext<'a> { return; } - let hir_name = hir::LifetimeName::Name(name); + let hir_name = ParamName::Plain(name); - if self.lifetimes_to_define - .iter() - .any(|(_, lt_name)| *lt_name == hir_name) - { + if self.lifetimes_to_define.iter().any(|(_, lt_name)| *lt_name == hir_name) { return; } @@ -741,28 +732,27 @@ impl<'a> LoweringContext<'a> { /// When we have either an elided or `'_` lifetime in an impl /// header, we convert it to - fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> hir::LifetimeName { + fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName { assert!(self.is_collecting_in_band_lifetimes); let index = self.lifetimes_to_define.len(); - let hir_name = hir::LifetimeName::Fresh(index); + let hir_name = ParamName::Fresh(index); self.lifetimes_to_define.push((span, hir_name)); hir_name } - // Evaluates `f` with the lifetimes in `lt_defs` in-scope. + // Evaluates `f` with the lifetimes in `params` in-scope. // This is used to track which lifetimes have already been defined, and // which are new in-band lifetimes that need to have a definition created // for them. - fn with_in_scope_lifetime_defs<'l, T, F>( - &mut self, - lt_defs: impl Iterator, - f: F, - ) -> T + fn with_in_scope_lifetime_defs(&mut self, params: &Vec, f: F) -> T where F: FnOnce(&mut LoweringContext) -> T, { let old_len = self.in_scope_lifetimes.len(); - let lt_def_names = lt_defs.map(|lt_def| lt_def.lifetime.ident.name); + let lt_def_names = params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some(param.ident.name), + _ => None, + }); self.in_scope_lifetimes.extend(lt_def_names); let res = f(self); @@ -771,17 +761,22 @@ impl<'a> LoweringContext<'a> { res } - // Same as the method above, but accepts `hir::LifetimeDef`s - // instead of `ast::LifetimeDef`s. + // Same as the method above, but accepts `hir::GenericParam`s + // instead of `ast::GenericParam`s. // This should only be used with generics that have already had their // in-band lifetimes added. In practice, this means that this function is // only used when lowering a child item of a trait or impl. - fn with_parent_impl_lifetime_defs(&mut self, lt_defs: &[hir::LifetimeDef], f: F) -> T - where + fn with_parent_impl_lifetime_defs(&mut self, + params: &HirVec, + f: F + ) -> T where F: FnOnce(&mut LoweringContext) -> T, { let old_len = self.in_scope_lifetimes.len(); - let lt_def_names = lt_defs.iter().map(|lt_def| lt_def.lifetime.name.name()); + let lt_def_names = params.iter().filter_map(|param| match param.kind { + hir::GenericParamKind::Lifetime { .. } => Some(param.name.name()), + _ => None, + }); self.in_scope_lifetimes.extend(lt_def_names); let res = f(self); @@ -807,10 +802,7 @@ impl<'a> LoweringContext<'a> { F: FnOnce(&mut LoweringContext) -> T, { let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs( - generics.params.iter().filter_map(|p| match p { - GenericParam::Lifetime(ld) => Some(ld), - _ => None, - }), + &generics.params, |this| { let itctx = ImplTraitContext::Universal(parent_id); this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| { @@ -1037,6 +1029,16 @@ impl<'a> LoweringContext<'a> { } } + fn lower_generic_arg(&mut self, + arg: &ast::GenericArg, + itctx: ImplTraitContext) + -> hir::GenericArg { + match arg { + ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), + ast::GenericArg::Type(ty) => GenericArg::Type(self.lower_ty(&ty, itctx)), + } + } + fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P { let kind = match t.node { TyKind::Infer => hir::TyInfer, @@ -1052,10 +1054,7 @@ impl<'a> LoweringContext<'a> { hir::TyRptr(lifetime, self.lower_mt(mt, itctx)) } TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs( - f.generic_params.iter().filter_map(|p| match p { - GenericParam::Lifetime(ld) => Some(ld), - _ => None, - }), + &f.generic_params, |this| { this.with_anonymous_lifetime_mode( AnonymousLifetimeMode::PassThrough, @@ -1110,11 +1109,11 @@ impl<'a> LoweringContext<'a> { let bounds = bounds .iter() .filter_map(|bound| match *bound { - TraitTyParamBound(ref ty, TraitBoundModifier::None) => { + GenericBound::Trait(ref ty, TraitBoundModifier::None) => { Some(self.lower_poly_trait_ref(ty, itctx)) } - TraitTyParamBound(_, TraitBoundModifier::Maybe) => None, - RegionTyParamBound(ref lifetime) => { + GenericBound::Trait(_, TraitBoundModifier::Maybe) => None, + GenericBound::Outlives(ref lifetime) => { if lifetime_bound.is_none() { lifetime_bound = Some(self.lower_lifetime(lifetime)); } @@ -1166,7 +1165,7 @@ impl<'a> LoweringContext<'a> { self.allocate_hir_id_counter(exist_ty_node_id, t); let hir_bounds = self.with_hir_id_owner(exist_ty_node_id, |lctx| { - lctx.lower_bounds(bounds, itctx) + lctx.lower_param_bounds(bounds, itctx) }); let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds( @@ -1233,18 +1232,20 @@ impl<'a> LoweringContext<'a> { span, ); - let hir_bounds = self.lower_bounds(bounds, itctx); + let hir_bounds = self.lower_param_bounds(bounds, itctx); // Set the name to `impl Bound1 + Bound2` let name = Symbol::intern(&pprust::ty_to_string(t)); - self.in_band_ty_params.push(hir::TyParam { - name, + self.in_band_ty_params.push(hir::GenericParam { id: def_node_id, - bounds: hir_bounds, - default: None, + name: ParamName::Plain(name), span, pure_wrt_drop: false, - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), - attrs: P::new(), + attrs: hir_vec![], + bounds: hir_bounds, + kind: hir::GenericParamKind::Type { + default: None, + synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), + } }); hir::TyPath(hir::QPath::Resolved( @@ -1284,7 +1285,7 @@ impl<'a> LoweringContext<'a> { &mut self, exist_ty_id: NodeId, parent_index: DefIndex, - bounds: &hir::TyParamBounds, + bounds: &hir::GenericBounds, ) -> (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. @@ -1307,15 +1308,15 @@ impl<'a> LoweringContext<'a> { hir::intravisit::NestedVisitorMap::None } - fn visit_path_parameters(&mut self, span: Span, parameters: &'v hir::PathParameters) { + fn visit_generic_args(&mut self, span: Span, parameters: &'v hir::GenericArgs) { // Don't collect elided lifetimes used inside of `Fn()` syntax. if parameters.parenthesized { let old_collect_elided_lifetimes = self.collect_elided_lifetimes; self.collect_elided_lifetimes = false; - hir::intravisit::walk_path_parameters(self, span, parameters); + hir::intravisit::walk_generic_args(self, span, parameters); self.collect_elided_lifetimes = old_collect_elided_lifetimes; } else { - hir::intravisit::walk_path_parameters(self, span, parameters); + hir::intravisit::walk_generic_args(self, span, parameters); } } @@ -1351,10 +1352,11 @@ impl<'a> LoweringContext<'a> { fn visit_generic_param(&mut self, param: &'v hir::GenericParam) { // Record the introduction of 'a in `for<'a> ...` - if let hir::GenericParam::Lifetime(ref lt_def) = *param { + if let hir::GenericParamKind::Lifetime { .. } = param.kind { // Introduce lifetimes one at a time so that we can handle // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>` - self.currently_bound_lifetimes.push(lt_def.lifetime.name); + let lt_name = hir::LifetimeName::Param(param.name); + self.currently_bound_lifetimes.push(lt_name); } hir::intravisit::walk_generic_param(self, param); @@ -1371,14 +1373,12 @@ impl<'a> LoweringContext<'a> { return; } } - name @ hir::LifetimeName::Fresh(_) => name, - name @ hir::LifetimeName::Name(_) => name, + hir::LifetimeName::Param(_) => lifetime.name, hir::LifetimeName::Static => return, }; if !self.currently_bound_lifetimes.contains(&name) - && !self.already_defined_lifetimes.contains(&name) - { + && !self.already_defined_lifetimes.contains(&name) { self.already_defined_lifetimes.insert(name); self.output_lifetimes.push(hir::Lifetime { @@ -1395,23 +1395,31 @@ impl<'a> LoweringContext<'a> { self.context.resolver.definitions().create_def_with_parent( self.parent, def_node_id, - DefPathData::LifetimeDef(name.name().as_interned_str()), + DefPathData::LifetimeParam(name.name().as_interned_str()), DefIndexAddressSpace::High, Mark::root(), lifetime.span, ); - let def_lifetime = hir::Lifetime { + + let name = match name { + hir::LifetimeName::Underscore => { + hir::ParamName::Plain(keywords::UnderscoreLifetime.name()) + } + hir::LifetimeName::Param(param_name) => param_name, + _ => bug!("expected LifetimeName::Param or ParamName::Plain"), + }; + + self.output_lifetime_params.push(hir::GenericParam { id: def_node_id, - span: lifetime.span, name, - }; - self.output_lifetime_params - .push(hir::GenericParam::Lifetime(hir::LifetimeDef { - lifetime: def_lifetime, - bounds: Vec::new().into(), - pure_wrt_drop: false, + span: lifetime.span, + pure_wrt_drop: false, + attrs: hir_vec![], + bounds: hir_vec![], + kind: hir::GenericParamKind::Lifetime { in_band: false, - })); + } + }); } } } @@ -1428,7 +1436,7 @@ impl<'a> LoweringContext<'a> { }; for bound in bounds { - hir::intravisit::walk_ty_param_bound(&mut lifetime_collector, &bound); + hir::intravisit::walk_param_bound(&mut lifetime_collector, &bound); } ( @@ -1669,13 +1677,13 @@ impl<'a> LoweringContext<'a> { parenthesized_generic_args: ParenthesizedGenericArgs, itctx: ImplTraitContext, ) -> hir::PathSegment { - let (mut parameters, infer_types) = if let Some(ref parameters) = segment.parameters { + let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args { let msg = "parenthesized parameters may only be used with a trait"; - match **parameters { - PathParameters::AngleBracketed(ref data) => { + match **generic_args { + GenericArgs::AngleBracketed(ref data) => { self.lower_angle_bracketed_parameter_data(data, param_mode, itctx) } - PathParameters::Parenthesized(ref data) => match parenthesized_generic_args { + GenericArgs::Parenthesized(ref data) => match parenthesized_generic_args { ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), ParenthesizedGenericArgs::Warn => { self.sess.buffer_lint( @@ -1684,13 +1692,13 @@ impl<'a> LoweringContext<'a> { data.span, msg.into(), ); - (hir::PathParameters::none(), true) + (hir::GenericArgs::none(), true) } ParenthesizedGenericArgs::Err => { struct_span_err!(self.sess, data.span, E0214, "{}", msg) .span_label(data.span, "only traits may use parentheses") .emit(); - (hir::PathParameters::none(), true) + (hir::GenericArgs::none(), true) } }, } @@ -1698,47 +1706,49 @@ impl<'a> LoweringContext<'a> { self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode, itctx) }; - if !parameters.parenthesized && parameters.lifetimes.is_empty() { - parameters.lifetimes = self.elided_path_lifetimes(path_span, expected_lifetimes); + let has_lifetimes = generic_args.args.iter().any(|arg| match arg { + GenericArg::Lifetime(_) => true, + _ => false, + }); + if !generic_args.parenthesized && !has_lifetimes { + generic_args.args = + self.elided_path_lifetimes(path_span, expected_lifetimes) + .into_iter() + .map(|lt| GenericArg::Lifetime(lt)) + .chain(generic_args.args.into_iter()) + .collect(); } hir::PathSegment::new( self.lower_ident(segment.ident), - parameters, + generic_args, infer_types, ) } fn lower_angle_bracketed_parameter_data( &mut self, - data: &AngleBracketedParameterData, + data: &AngleBracketedArgs, param_mode: ParamMode, itctx: ImplTraitContext, - ) -> (hir::PathParameters, bool) { - let &AngleBracketedParameterData { - ref lifetimes, - ref types, - ref bindings, - .. - } = data; - ( - hir::PathParameters { - lifetimes: self.lower_lifetimes(lifetimes), - types: types.iter().map(|ty| self.lower_ty(ty, itctx)).collect(), - bindings: bindings - .iter() - .map(|b| self.lower_ty_binding(b, itctx)) - .collect(), - parenthesized: false, - }, - types.is_empty() && param_mode == ParamMode::Optional, - ) + ) -> (hir::GenericArgs, bool) { + let &AngleBracketedArgs { ref args, ref bindings, .. } = data; + let has_types = args.iter().any(|arg| match arg { + ast::GenericArg::Type(_) => true, + _ => 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(), + parenthesized: false, + }, + !has_types && param_mode == ParamMode::Optional) } fn lower_parenthesized_parameter_data( &mut self, - data: &ParenthesizedParameterData, - ) -> (hir::PathParameters, bool) { + data: &ParenthesisedArgs, + ) -> (hir::GenericArgs, bool) { // Switch to `PassThrough` mode for anonymous lifetimes: this // means that we permit things like `&Ref`, where `Ref` has // a hidden lifetime parameter. This is needed for backwards @@ -1748,29 +1758,16 @@ impl<'a> LoweringContext<'a> { AnonymousLifetimeMode::PassThrough, |this| { const DISALLOWED: ImplTraitContext = ImplTraitContext::Disallowed; - let &ParenthesizedParameterData { - ref inputs, - ref output, - span, - } = data; - let inputs = inputs - .iter() - .map(|ty| this.lower_ty(ty, DISALLOWED)) - .collect(); + let &ParenthesisedArgs { ref inputs, ref output, span } = data; + let inputs = inputs.iter().map(|ty| this.lower_ty(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, - }) + P(hir::Ty { node: hir::TyTup(tys), id: node_id, hir_id, span }) }; ( - hir::PathParameters { - lifetimes: hir::HirVec::new(), - types: hir_vec![mk_tup(this, inputs, span)], + hir::GenericArgs { + args: hir_vec![GenericArg::Type(mk_tup(this, inputs, span))], bindings: hir_vec![ hir::TypeBinding { id: this.next_id().node_id, @@ -1874,63 +1871,22 @@ impl<'a> LoweringContext<'a> { }) } - fn lower_ty_param_bound( + fn lower_param_bound( &mut self, - tpb: &TyParamBound, + tpb: &GenericBound, itctx: ImplTraitContext, - ) -> hir::TyParamBound { + ) -> hir::GenericBound { match *tpb { - TraitTyParamBound(ref ty, modifier) => hir::TraitTyParamBound( + GenericBound::Trait(ref ty, modifier) => hir::GenericBound::Trait( self.lower_poly_trait_ref(ty, itctx), self.lower_trait_bound_modifier(modifier), ), - RegionTyParamBound(ref lifetime) => { - hir::RegionTyParamBound(self.lower_lifetime(lifetime)) + GenericBound::Outlives(ref lifetime) => { + hir::GenericBound::Outlives(self.lower_lifetime(lifetime)) } } } - fn lower_ty_param( - &mut self, - tp: &TyParam, - add_bounds: &[TyParamBound], - itctx: ImplTraitContext, - ) -> hir::TyParam { - let mut name = self.lower_ident(tp.ident); - - // Don't expose `Self` (recovered "keyword used as ident" parse error). - // `rustc::ty` expects `Self` to be only used for a trait's `Self`. - // Instead, use gensym("Self") to create a distinct name that looks the same. - if name == keywords::SelfType.name() { - name = Symbol::gensym("Self"); - } - - let mut bounds = self.lower_bounds(&tp.bounds, itctx); - if !add_bounds.is_empty() { - bounds = bounds - .into_iter() - .chain(self.lower_bounds(add_bounds, itctx).into_iter()) - .collect(); - } - - hir::TyParam { - id: self.lower_node_id(tp.id).node_id, - name, - bounds, - default: tp.default - .as_ref() - .map(|x| self.lower_ty(x, ImplTraitContext::Disallowed)), - span: tp.ident.span, - pure_wrt_drop: attr::contains_name(&tp.attrs, "may_dangle"), - synthetic: tp.attrs - .iter() - .filter(|attr| attr.check_name("rustc_synthetic")) - .map(|_| hir::SyntheticTyParamKind::ImplTrait) - .nth(0), - attrs: self.lower_attrs(&tp.attrs), - } - } - fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { let span = l.ident.span; match self.lower_ident(l.ident) { @@ -1938,7 +1894,7 @@ impl<'a> LoweringContext<'a> { 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, fresh_name) + self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(fresh_name)) } AnonymousLifetimeMode::PassThrough => { @@ -1947,7 +1903,8 @@ impl<'a> LoweringContext<'a> { }, name => { self.maybe_collect_in_band_lifetime(span, name); - self.new_named_lifetime(l.id, span, hir::LifetimeName::Name(name)) + let param_name = ParamName::Plain(name); + self.new_named_lifetime(l.id, span, hir::LifetimeName::Param(param_name)) } } } @@ -1965,57 +1922,98 @@ impl<'a> LoweringContext<'a> { } } - fn lower_lifetime_def(&mut self, l: &LifetimeDef) -> hir::LifetimeDef { - let was_collecting_in_band = self.is_collecting_in_band_lifetimes; - self.is_collecting_in_band_lifetimes = false; - - let def = hir::LifetimeDef { - lifetime: self.lower_lifetime(&l.lifetime), - bounds: self.lower_lifetimes(&l.bounds), - pure_wrt_drop: attr::contains_name(&l.attrs, "may_dangle"), - in_band: false, - }; - - self.is_collecting_in_band_lifetimes = was_collecting_in_band; - - def - } - - fn lower_lifetimes(&mut self, lts: &Vec) -> hir::HirVec { - lts.iter().map(|l| self.lower_lifetime(l)).collect() - } - fn lower_generic_params( &mut self, params: &Vec, - add_bounds: &NodeMap>, + add_bounds: &NodeMap>, itctx: ImplTraitContext, ) -> hir::HirVec { - params - .iter() - .map(|param| match *param { - GenericParam::Lifetime(ref lifetime_def) => { - hir::GenericParam::Lifetime(self.lower_lifetime_def(lifetime_def)) + params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect() + } + + fn lower_generic_param(&mut self, + param: &GenericParam, + add_bounds: &NodeMap>, + itctx: ImplTraitContext) + -> hir::GenericParam { + let mut bounds = self.lower_param_bounds(¶m.bounds, itctx); + match param.kind { + GenericParamKind::Lifetime => { + let was_collecting_in_band = self.is_collecting_in_band_lifetimes; + self.is_collecting_in_band_lifetimes = false; + + let lt = self.lower_lifetime(&Lifetime { id: param.id, ident: param.ident }); + let param_name = match lt.name { + hir::LifetimeName::Param(param_name) => param_name, + _ => hir::ParamName::Plain(lt.name.name()), + }; + let param = hir::GenericParam { + id: lt.id, + name: param_name, + span: lt.span, + pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"), + attrs: self.lower_attrs(¶m.attrs), + bounds, + kind: hir::GenericParamKind::Lifetime { in_band: false } + }; + + self.is_collecting_in_band_lifetimes = was_collecting_in_band; + + param + } + GenericParamKind::Type { ref default, .. } => { + let mut name = self.lower_ident(param.ident); + + // Don't expose `Self` (recovered "keyword used as ident" parse error). + // `rustc::ty` expects `Self` to be only used for a trait's `Self`. + // Instead, use gensym("Self") to create a distinct name that looks the same. + if name == keywords::SelfType.name() { + name = Symbol::gensym("Self"); } - GenericParam::Type(ref ty_param) => hir::GenericParam::Type(self.lower_ty_param( - ty_param, - add_bounds.get(&ty_param.id).map_or(&[][..], |x| &x), - itctx, - )), - }) - .collect() + + 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()) + .collect(); + } + + hir::GenericParam { + id: self.lower_node_id(param.id).node_id, + name: hir::ParamName::Plain(name), + span: param.ident.span, + pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"), + attrs: self.lower_attrs(¶m.attrs), + bounds, + kind: hir::GenericParamKind::Type { + default: default.as_ref().map(|x| { + self.lower_ty(x, ImplTraitContext::Disallowed) + }), + synthetic: param.attrs.iter() + .filter(|attr| attr.check_name("rustc_synthetic")) + .map(|_| hir::SyntheticTyParamKind::ImplTrait) + .next(), + } + } + } + } } - fn lower_generics(&mut self, g: &Generics, itctx: ImplTraitContext) -> hir::Generics { + fn lower_generics( + &mut self, + generics: &Generics, + itctx: ImplTraitContext) + -> hir::Generics + { // Collect `?Trait` bounds in where clause and move them to parameter definitions. // FIXME: This could probably be done with less rightward drift. Also looks like two control // paths where report_error is called are also the only paths that advance to after // the match statement, so the error reporting could probably just be moved there. let mut add_bounds = NodeMap(); - for pred in &g.where_clause.predicates { + for pred in &generics.where_clause.predicates { if let WherePredicate::BoundPredicate(ref bound_pred) = *pred { 'next_bound: for bound in &bound_pred.bounds { - if let TraitTyParamBound(_, TraitBoundModifier::Maybe) = *bound { + if let GenericBound::Trait(_, TraitBoundModifier::Maybe) = *bound { let report_error = |this: &mut Self| { this.diagnostic().span_err( bound_pred.bounded_ty.span, @@ -2036,15 +2034,17 @@ impl<'a> LoweringContext<'a> { if let Some(node_id) = self.resolver.definitions().as_local_node_id(def_id) { - for param in &g.params { - if let GenericParam::Type(ref ty_param) = *param { - if node_id == ty_param.id { - add_bounds - .entry(ty_param.id) - .or_insert(Vec::new()) - .push(bound.clone()); - continue 'next_bound; + for param in &generics.params { + match param.kind { + GenericParamKind::Type { .. } => { + if node_id == param.id { + add_bounds.entry(param.id) + .or_insert(Vec::new()) + .push(bound.clone()); + continue 'next_bound; + } } + _ => {} } } } @@ -2059,9 +2059,9 @@ impl<'a> LoweringContext<'a> { } hir::Generics { - params: self.lower_generic_params(&g.params, &add_bounds, itctx), - where_clause: self.lower_where_clause(&g.where_clause), - span: g.span, + params: self.lower_generic_params(&generics.params, &add_bounds, itctx), + where_clause: self.lower_where_clause(&generics.where_clause), + span: generics.span, } } @@ -2084,10 +2084,7 @@ impl<'a> LoweringContext<'a> { span, }) => { self.with_in_scope_lifetime_defs( - bound_generic_params.iter().filter_map(|p| match p { - GenericParam::Lifetime(ld) => Some(ld), - _ => None, - }), + &bound_generic_params, |this| { hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { bound_generic_params: this.lower_generic_params( @@ -2101,8 +2098,8 @@ impl<'a> LoweringContext<'a> { .filter_map(|bound| match *bound { // Ignore `?Trait` bounds. // Tthey were copied into type parameters already. - TraitTyParamBound(_, TraitBoundModifier::Maybe) => None, - _ => Some(this.lower_ty_param_bound( + GenericBound::Trait(_, TraitBoundModifier::Maybe) => None, + _ => Some(this.lower_param_bound( bound, ImplTraitContext::Disallowed, )), @@ -2120,10 +2117,7 @@ impl<'a> LoweringContext<'a> { }) => hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { span, lifetime: self.lower_lifetime(lifetime), - bounds: bounds - .iter() - .map(|bound| self.lower_lifetime(bound)) - .collect(), + bounds: self.lower_param_bounds(bounds, ImplTraitContext::Disallowed), }), WherePredicate::EqPredicate(WhereEqPredicate { id, @@ -2180,13 +2174,7 @@ impl<'a> LoweringContext<'a> { let bound_generic_params = self.lower_generic_params(&p.bound_generic_params, &NodeMap(), itctx); let trait_ref = self.with_parent_impl_lifetime_defs( - &bound_generic_params - .iter() - .filter_map(|p| match *p { - hir::GenericParam::Lifetime(ref ld) => Some(ld.clone()), - _ => None, - }) - .collect::>(), + &bound_generic_params, |this| this.lower_trait_ref(&p.trait_ref, itctx), ); @@ -2229,15 +2217,9 @@ impl<'a> LoweringContext<'a> { } } - fn lower_bounds( - &mut self, - bounds: &[TyParamBound], - itctx: ImplTraitContext, - ) -> hir::TyParamBounds { - bounds - .iter() - .map(|bound| self.lower_ty_param_bound(bound, itctx)) - .collect() + fn lower_param_bounds(&mut self, bounds: &[GenericBound], itctx: ImplTraitContext) + -> hir::GenericBounds { + bounds.iter().map(|bound| self.lower_param_bound(bound, itctx)).collect() } fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P { @@ -2403,10 +2385,7 @@ impl<'a> LoweringContext<'a> { ); let new_impl_items = self.with_in_scope_lifetime_defs( - ast_generics.params.iter().filter_map(|p| match p { - GenericParam::Lifetime(ld) => Some(ld), - _ => None, - }), + &ast_generics.params, |this| { impl_items .iter() @@ -2426,7 +2405,7 @@ impl<'a> LoweringContext<'a> { ) } ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => { - let bounds = self.lower_bounds(bounds, ImplTraitContext::Disallowed); + let bounds = self.lower_param_bounds(bounds, ImplTraitContext::Disallowed); let items = items .iter() .map(|item| self.lower_trait_item_ref(item)) @@ -2441,7 +2420,7 @@ impl<'a> LoweringContext<'a> { } ItemKind::TraitAlias(ref generics, ref bounds) => hir::ItemTraitAlias( self.lower_generics(generics, ImplTraitContext::Disallowed), - self.lower_bounds(bounds, ImplTraitContext::Disallowed), + self.lower_param_bounds(bounds, ImplTraitContext::Disallowed), ), ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"), } @@ -2668,7 +2647,7 @@ impl<'a> LoweringContext<'a> { TraitItemKind::Type(ref bounds, ref default) => ( self.lower_generics(&i.generics, ImplTraitContext::Disallowed), hir::TraitItemKind::Type( - self.lower_bounds(bounds, ImplTraitContext::Disallowed), + self.lower_param_bounds(bounds, ImplTraitContext::Disallowed), default .as_ref() .map(|x| self.lower_ty(x, ImplTraitContext::Disallowed)), @@ -4217,7 +4196,7 @@ impl<'a> LoweringContext<'a> { hir::Lifetime { id: self.next_id().node_id, span, - name: fresh_name, + name: hir::LifetimeName::Param(fresh_name), } } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 7835d4e782c43..14cecba490d0a 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -212,7 +212,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { NodeBlock(n) => EntryBlock(parent, dep_node_index, n), NodeStructCtor(n) => EntryStructCtor(parent, dep_node_index, n), NodeLifetime(n) => EntryLifetime(parent, dep_node_index, n), - NodeTyParam(n) => EntryTyParam(parent, dep_node_index, n), + NodeGenericParam(n) => EntryGenericParam(parent, dep_node_index, n), NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n), NodeLocal(n) => EntryLocal(parent, dep_node_index, n), NodeMacroDef(n) => EntryMacroDef(dep_node_index, n), @@ -347,14 +347,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_generic_param(&mut self, param: &'hir GenericParam) { - match *param { - GenericParam::Lifetime(ref ld) => { - self.insert(ld.lifetime.id, NodeLifetime(&ld.lifetime)); - } - GenericParam::Type(ref ty_param) => { - self.insert(ty_param.id, NodeTyParam(ty_param)); - } - } + self.insert(param.id, NodeGenericParam(param)); intravisit::walk_generic_param(self, param); } diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 48d959b4f8e41..8aa5dd4ad80fd 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -171,24 +171,12 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } fn visit_generic_param(&mut self, param: &'a GenericParam) { - match *param { - GenericParam::Lifetime(ref lifetime_def) => { - self.create_def( - lifetime_def.lifetime.id, - DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_interned_str()), - REGULAR_SPACE, - lifetime_def.lifetime.ident.span - ); - } - GenericParam::Type(ref ty_param) => { - self.create_def( - ty_param.id, - DefPathData::TypeParam(ty_param.ident.name.as_interned_str()), - REGULAR_SPACE, - ty_param.ident.span - ); - } - } + let name = param.ident.name.as_interned_str(); + let def_path_data = match param.kind { + GenericParamKind::Lifetime { .. } => DefPathData::LifetimeParam(name), + GenericParamKind::Type { .. } => DefPathData::TypeParam(name), + }; + self.create_def(param.id, def_path_data, REGULAR_SPACE, param.ident.span); visit::walk_generic_param(self, param); } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 99023a1686741..b1cb9d7fbd4a5 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -360,7 +360,7 @@ pub enum DefPathData { /// A type parameter (generic parameter) TypeParam(InternedString), /// A lifetime definition - LifetimeDef(InternedString), + LifetimeParam(InternedString), /// A variant of a enum EnumVariant(InternedString), /// A struct field @@ -625,7 +625,7 @@ impl DefPathData { Module(name) | MacroDef(name) | TypeParam(name) | - LifetimeDef(name) | + LifetimeParam(name) | EnumVariant(name) | Field(name) | GlobalMetaData(name) => Some(name), @@ -652,7 +652,7 @@ impl DefPathData { Module(name) | MacroDef(name) | TypeParam(name) | - LifetimeDef(name) | + LifetimeParam(name) | EnumVariant(name) | Field(name) | GlobalMetaData(name) => { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index d2e04ef31c86a..c2c8c7a391b9c 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -68,7 +68,7 @@ pub enum Node<'hir> { NodeStructCtor(&'hir VariantData), NodeLifetime(&'hir Lifetime), - NodeTyParam(&'hir TyParam), + NodeGenericParam(&'hir GenericParam), NodeVisibility(&'hir Visibility), } @@ -96,7 +96,7 @@ enum MapEntry<'hir> { EntryBlock(NodeId, DepNodeIndex, &'hir Block), EntryStructCtor(NodeId, DepNodeIndex, &'hir VariantData), EntryLifetime(NodeId, DepNodeIndex, &'hir Lifetime), - EntryTyParam(NodeId, DepNodeIndex, &'hir TyParam), + EntryGenericParam(NodeId, DepNodeIndex, &'hir GenericParam), EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility), EntryLocal(NodeId, DepNodeIndex, &'hir Local), @@ -132,7 +132,7 @@ impl<'hir> MapEntry<'hir> { EntryBlock(id, _, _) => id, EntryStructCtor(id, _, _) => id, EntryLifetime(id, _, _) => id, - EntryTyParam(id, _, _) => id, + EntryGenericParam(id, _, _) => id, EntryVisibility(id, _, _) => id, EntryLocal(id, _, _) => id, @@ -160,7 +160,7 @@ impl<'hir> MapEntry<'hir> { EntryBlock(_, _, n) => NodeBlock(n), EntryStructCtor(_, _, n) => NodeStructCtor(n), EntryLifetime(_, _, n) => NodeLifetime(n), - EntryTyParam(_, _, n) => NodeTyParam(n), + EntryGenericParam(_, _, n) => NodeGenericParam(n), EntryVisibility(_, _, n) => NodeVisibility(n), EntryLocal(_, _, n) => NodeLocal(n), EntryMacroDef(_, n) => NodeMacroDef(n), @@ -328,7 +328,7 @@ impl<'hir> Map<'hir> { EntryBlock(_, dep_node_index, _) | EntryStructCtor(_, dep_node_index, _) | EntryLifetime(_, dep_node_index, _) | - EntryTyParam(_, dep_node_index, _) | + EntryGenericParam(_, dep_node_index, _) | EntryVisibility(_, dep_node_index, _) | EntryAnonConst(_, dep_node_index, _) | EntryExpr(_, dep_node_index, _) | @@ -494,8 +494,11 @@ impl<'hir> Map<'hir> { Some(Def::Macro(self.local_def_id(macro_def.id), MacroKind::Bang)) } - NodeTyParam(param) => { - Some(Def::TyParam(self.local_def_id(param.id))) + NodeGenericParam(param) => { + Some(match param.kind { + GenericParamKind::Lifetime { .. } => Def::Local(param.id), + GenericParamKind::Type { .. } => Def::TyParam(self.local_def_id(param.id)), + }) } } } @@ -600,7 +603,7 @@ impl<'hir> Map<'hir> { pub fn ty_param_owner(&self, id: NodeId) -> NodeId { match self.get(id) { NodeItem(&Item { node: ItemTrait(..), .. }) => id, - NodeTyParam(_) => self.get_parent_node(id), + NodeGenericParam(_) => self.get_parent_node(id), _ => { bug!("ty_param_owner: {} not a type parameter", self.node_to_string(id)) @@ -613,11 +616,8 @@ impl<'hir> Map<'hir> { NodeItem(&Item { node: ItemTrait(..), .. }) => { keywords::SelfType.name() } - NodeTyParam(tp) => tp.name, - _ => { - bug!("ty_param_name: {} not a type parameter", - self.node_to_string(id)) - } + NodeGenericParam(param) => param.name.name(), + _ => bug!("ty_param_name: {} not a type parameter", self.node_to_string(id)), } } @@ -954,7 +954,7 @@ impl<'hir> Map<'hir> { NodeVariant(v) => v.node.name, NodeField(f) => f.ident.name, NodeLifetime(lt) => lt.name.name(), - NodeTyParam(tp) => tp.name, + NodeGenericParam(param) => param.name.name(), NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node, NodeStructCtor(_) => self.name(self.get_parent(id)), _ => bug!("no name for {}", self.node_to_string(id)) @@ -974,7 +974,7 @@ impl<'hir> Map<'hir> { Some(NodeField(ref f)) => Some(&f.attrs[..]), Some(NodeExpr(ref e)) => Some(&*e.attrs), Some(NodeStmt(ref s)) => Some(s.node.attrs()), - Some(NodeTyParam(tp)) => Some(&tp.attrs[..]), + Some(NodeGenericParam(param)) => Some(¶m.attrs[..]), // unit/tuple structs take the attributes straight from // the struct definition. Some(NodeStructCtor(_)) => { @@ -1021,7 +1021,7 @@ impl<'hir> Map<'hir> { Some(EntryBlock(_, _, block)) => block.span, Some(EntryStructCtor(_, _, _)) => self.expect_item(self.get_parent(id)).span, Some(EntryLifetime(_, _, lifetime)) => lifetime.span, - Some(EntryTyParam(_, _, ty_param)) => ty_param.span, + Some(EntryGenericParam(_, _, param)) => param.span, Some(EntryVisibility(_, _, &Visibility::Restricted { ref path, .. })) => path.span, Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v), Some(EntryLocal(_, _, local)) => local.span, @@ -1226,19 +1226,19 @@ impl<'hir> print::PpAnn for Map<'hir> { impl<'a> print::State<'a> { pub fn print_node(&mut self, node: Node) -> io::Result<()> { match node { - NodeItem(a) => self.print_item(&a), - NodeForeignItem(a) => self.print_foreign_item(&a), - NodeTraitItem(a) => self.print_trait_item(a), - NodeImplItem(a) => self.print_impl_item(a), - NodeVariant(a) => self.print_variant(&a), - NodeAnonConst(a) => self.print_anon_const(&a), - NodeExpr(a) => self.print_expr(&a), - NodeStmt(a) => self.print_stmt(&a), - NodeTy(a) => self.print_type(&a), - NodeTraitRef(a) => self.print_trait_ref(&a), + NodeItem(a) => self.print_item(&a), + NodeForeignItem(a) => self.print_foreign_item(&a), + NodeTraitItem(a) => self.print_trait_item(a), + NodeImplItem(a) => self.print_impl_item(a), + NodeVariant(a) => self.print_variant(&a), + NodeAnonConst(a) => self.print_anon_const(&a), + NodeExpr(a) => self.print_expr(&a), + NodeStmt(a) => self.print_stmt(&a), + NodeTy(a) => self.print_type(&a), + NodeTraitRef(a) => self.print_trait_ref(&a), NodeBinding(a) | - NodePat(a) => self.print_pat(&a), - NodeBlock(a) => { + NodePat(a) => self.print_pat(&a), + NodeBlock(a) => { use syntax::print::pprust::PrintState; // containing cbox, will be closed by print-block at } @@ -1247,16 +1247,16 @@ impl<'a> print::State<'a> { self.ibox(0)?; self.print_block(&a) } - NodeLifetime(a) => self.print_lifetime(&a), - NodeVisibility(a) => self.print_visibility(&a), - NodeTyParam(_) => bug!("cannot print TyParam"), - NodeField(_) => bug!("cannot print StructField"), + NodeLifetime(a) => self.print_lifetime(&a), + NodeVisibility(a) => self.print_visibility(&a), + NodeGenericParam(_) => bug!("cannot print NodeGenericParam"), + NodeField(_) => bug!("cannot print StructField"), // these cases do not carry enough information in the // hir_map to reconstruct their full structure for pretty // printing. - NodeStructCtor(_) => bug!("cannot print isolated StructCtor"), - NodeLocal(a) => self.print_local_decl(&a), - NodeMacroDef(_) => bug!("cannot print MacroDef"), + NodeStructCtor(_) => bug!("cannot print isolated StructCtor"), + NodeLocal(a) => self.print_local_decl(&a), + NodeMacroDef(_) => bug!("cannot print MacroDef"), } } } @@ -1371,8 +1371,8 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { Some(NodeLifetime(_)) => { format!("lifetime {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeTyParam(ref ty_param)) => { - format!("typaram {:?}{}", ty_param, id_str) + Some(NodeGenericParam(ref param)) => { + format!("generic_param {:?}{}", param, id_str) } Some(NodeVisibility(ref vis)) => { format!("visibility {:?}{}", vis, id_str) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 833090c3ee092..f6876113c1176 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -22,7 +22,6 @@ pub use self::Mutability::*; pub use self::PrimTy::*; pub use self::Stmt_::*; pub use self::Ty_::*; -pub use self::TyParamBound::*; pub use self::UnOp::*; pub use self::UnsafeSource::*; pub use self::Visibility::{Public, Inherited}; @@ -53,8 +52,6 @@ use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope} use serialize::{self, Encoder, Encodable, Decoder, Decodable}; use std::collections::BTreeMap; use std::fmt; -use std::iter; -use std::slice; /// HIR doesn't commit to a concrete storage type and has its own alias for a vector. /// It can be `Vec`, `P<[T]>` or potentially `Box<[T]>`, or some other container with similar @@ -203,12 +200,9 @@ pub struct Lifetime { } #[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] -pub enum LifetimeName { - /// User typed nothing. e.g. the lifetime in `&u32`. - Implicit, - - /// User typed `'_`. - Underscore, +pub enum ParamName { + /// Some user-given name like `T` or `'x`. + Plain(Name), /// Synthetic name generated when user elided a lifetime in an impl header, /// e.g. the lifetimes in cases like these: @@ -224,12 +218,30 @@ pub enum LifetimeName { /// where `'f` is something like `Fresh(0)`. The indices are /// unique per impl, but not necessarily continuous. Fresh(usize), +} + +impl ParamName { + pub fn name(&self) -> Name { + match *self { + ParamName::Plain(name) => name, + ParamName::Fresh(_) => keywords::UnderscoreLifetime.name(), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] +pub enum LifetimeName { + /// User-given names or fresh (synthetic) names. + Param(ParamName), + + /// User typed nothing. e.g. the lifetime in `&u32`. + Implicit, + + /// User typed `'_`. + Underscore, /// User wrote `'static` Static, - - /// Some user-given name like `'x` - Name(Name), } impl LifetimeName { @@ -237,11 +249,29 @@ impl LifetimeName { use self::LifetimeName::*; match *self { Implicit => keywords::Invalid.name(), - Fresh(_) | Underscore => keywords::UnderscoreLifetime.name(), + Underscore => keywords::UnderscoreLifetime.name(), Static => keywords::StaticLifetime.name(), - Name(name) => name, + Param(param_name) => param_name.name(), } } + + fn is_elided(&self) -> bool { + use self::LifetimeName::*; + match self { + Implicit | Underscore => true, + + // It might seem surprising that `Fresh(_)` counts as + // *not* elided -- but this is because, as far as the code + // in the compiler is concerned -- `Fresh(_)` variants act + // equivalently to "some fresh name". They correspond to + // early-bound regions on an impl, in other words. + Param(_) | Static => false, + } + } + + fn is_static(&self) -> bool { + self == &LifetimeName::Static + } } impl fmt::Debug for Lifetime { @@ -255,36 +285,14 @@ impl fmt::Debug for Lifetime { impl Lifetime { pub fn is_elided(&self) -> bool { - use self::LifetimeName::*; - match self.name { - Implicit | Underscore => true, - - // It might seem surprising that `Fresh(_)` counts as - // *not* elided -- but this is because, as far as the code - // in the compiler is concerned -- `Fresh(_)` variants act - // equivalently to "some fresh name". They correspond to - // early-bound regions on an impl, in other words. - Fresh(_) | Static | Name(_) => false, - } + self.name.is_elided() } pub fn is_static(&self) -> bool { - self.name == LifetimeName::Static + self.name.is_static() } } -/// A lifetime definition, eg `'a: 'b+'c+'d` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct LifetimeDef { - pub lifetime: Lifetime, - pub bounds: HirVec, - pub pure_wrt_drop: bool, - // Indicates that the lifetime definition was synthetically added - // as a result of an in-band lifetime usage like - // `fn foo(x: &'a u8) -> &'a u8 { x }` - pub in_band: bool, -} - /// A "Path" is essentially Rust's notion of a name; for instance: /// `std::cmp::PartialEq`. It's represented as a sequence of identifiers, /// along with a bunch of supporting information. @@ -327,7 +335,7 @@ pub struct PathSegment { /// this is more than just simple syntactic sugar; the use of /// parens affects the region binding rules, so we preserve the /// distinction. - pub parameters: Option>, + pub args: Option>, /// Whether to infer remaining type parameters, if any. /// This only applies to expression and pattern paths, and @@ -342,30 +350,30 @@ impl PathSegment { PathSegment { name, infer_types: true, - parameters: None + args: None, } } - pub fn new(name: Name, parameters: PathParameters, infer_types: bool) -> Self { + pub fn new(name: Name, args: GenericArgs, infer_types: bool) -> Self { PathSegment { name, infer_types, - parameters: if parameters.is_empty() { + args: if args.is_empty() { None } else { - Some(P(parameters)) + Some(P(args)) } } } // FIXME: hack required because you can't create a static - // PathParameters, so you can't just return a &PathParameters. - pub fn with_parameters(&self, f: F) -> R - where F: FnOnce(&PathParameters) -> R + // GenericArgs, so you can't just return a &GenericArgs. + pub fn with_generic_args(&self, f: F) -> R + where F: FnOnce(&GenericArgs) -> R { - let dummy = PathParameters::none(); - f(if let Some(ref params) = self.parameters { - ¶ms + let dummy = GenericArgs::none(); + f(if let Some(ref args) = self.args { + &args } else { &dummy }) @@ -373,142 +381,114 @@ impl PathSegment { } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct PathParameters { - /// The lifetime parameters for this path segment. - pub lifetimes: HirVec, - /// The type parameters for this path segment, if present. - pub types: HirVec>, +pub enum GenericArg { + Lifetime(Lifetime), + Type(P), +} + +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub struct GenericArgs { + /// The generic arguments for this path segment. + pub args: HirVec, /// Bindings (equality constraints) on associated types, if present. /// E.g., `Foo`. pub bindings: HirVec, - /// Were parameters written in parenthesized form `Fn(T) -> U`? + /// Were arguments written in parenthesized form `Fn(T) -> U`? /// This is required mostly for pretty-printing and diagnostics, /// but also for changing lifetime elision rules to be "function-like". pub parenthesized: bool, } -impl PathParameters { +impl GenericArgs { pub fn none() -> Self { Self { - lifetimes: HirVec::new(), - types: HirVec::new(), + args: HirVec::new(), bindings: HirVec::new(), parenthesized: false, } } pub fn is_empty(&self) -> bool { - self.lifetimes.is_empty() && self.types.is_empty() && - self.bindings.is_empty() && !self.parenthesized + self.args.is_empty() && self.bindings.is_empty() && !self.parenthesized } pub fn inputs(&self) -> &[P] { if self.parenthesized { - if let Some(ref ty) = self.types.get(0) { - if let TyTup(ref tys) = ty.node { - return tys; + for arg in &self.args { + match arg { + GenericArg::Lifetime(_) => {} + GenericArg::Type(ref ty) => { + if let TyTup(ref tys) = ty.node { + return tys; + } + break; + } } } } - bug!("PathParameters::inputs: not a `Fn(T) -> U`"); + bug!("GenericArgs::inputs: not a `Fn(T) -> U`"); } } +/// A modifier on a bound, currently this is only used for `?Sized`, where the +/// modifier is `Maybe`. Negative bounds should also be handled here. +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum TraitBoundModifier { + None, + Maybe, +} + /// The AST represents all type param bounds as types. /// typeck::collect::compute_bounds matches these against /// the "special" built-in traits (see middle::lang_items) and /// detects Copy, Send and Sync. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TyParamBound { - TraitTyParamBound(PolyTraitRef, TraitBoundModifier), - RegionTyParamBound(Lifetime), +pub enum GenericBound { + Trait(PolyTraitRef, TraitBoundModifier), + Outlives(Lifetime), } -impl TyParamBound { +impl GenericBound { pub fn span(&self) -> Span { match self { - &TraitTyParamBound(ref t, ..) => t.span, - &RegionTyParamBound(ref l) => l.span, + &GenericBound::Trait(ref t, ..) => t.span, + &GenericBound::Outlives(ref l) => l.span, } } } -/// A modifier on a bound, currently this is only used for `?Sized`, where the -/// modifier is `Maybe`. Negative bounds should also be handled here. -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TraitBoundModifier { - None, - Maybe, -} +pub type GenericBounds = HirVec; -pub type TyParamBounds = HirVec; +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum GenericParamKind { + /// A lifetime definition, eg `'a: 'b + 'c + 'd`. + Lifetime { + // Indicates that the lifetime definition was synthetically added + // as a result of an in-band lifetime usage like: + // `fn foo(x: &'a u8) -> &'a u8 { x }` + in_band: bool, + }, + Type { + default: Option>, + synthetic: Option, + } +} #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct TyParam { - pub name: Name, +pub struct GenericParam { pub id: NodeId, - pub bounds: TyParamBounds, - pub default: Option>, + pub name: ParamName, + pub attrs: HirVec, + pub bounds: GenericBounds, pub span: Span, pub pure_wrt_drop: bool, - pub synthetic: Option, - pub attrs: HirVec, -} -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum GenericParam { - Lifetime(LifetimeDef), - Type(TyParam), + pub kind: GenericParamKind, } -impl GenericParam { - pub fn is_lifetime_param(&self) -> bool { - match *self { - GenericParam::Lifetime(_) => true, - _ => false, - } - } - - pub fn is_type_param(&self) -> bool { - match *self { - GenericParam::Type(_) => true, - _ => false, - } - } -} - -pub trait GenericParamsExt { - fn lifetimes<'a>(&'a self) -> iter::FilterMap< - slice::Iter, - fn(&GenericParam) -> Option<&LifetimeDef>, - >; - - fn ty_params<'a>(&'a self) -> iter::FilterMap< - slice::Iter, - fn(&GenericParam) -> Option<&TyParam>, - >; -} - -impl GenericParamsExt for [GenericParam] { - fn lifetimes<'a>(&'a self) -> iter::FilterMap< - slice::Iter, - fn(&GenericParam) -> Option<&LifetimeDef>, - > { - self.iter().filter_map(|param| match *param { - GenericParam::Lifetime(ref l) => Some(l), - _ => None, - }) - } - - fn ty_params<'a>(&'a self) -> iter::FilterMap< - slice::Iter, - fn(&GenericParam) -> Option<&TyParam>, - > { - self.iter().filter_map(|param| match *param { - GenericParam::Type(ref t) => Some(t), - _ => None, - }) - } +pub struct GenericParamCount { + pub lifetimes: usize, + pub types: usize, } /// Represents lifetimes and type parameters attached to a declaration @@ -532,55 +512,23 @@ impl Generics { } } - pub fn is_lt_parameterized(&self) -> bool { - self.params.iter().any(|param| param.is_lifetime_param()) - } - - pub fn is_type_parameterized(&self) -> bool { - self.params.iter().any(|param| param.is_type_param()) - } - - pub fn lifetimes<'a>(&'a self) -> impl Iterator { - self.params.lifetimes() - } - - pub fn ty_params<'a>(&'a self) -> impl Iterator { - self.params.ty_params() - } -} - -pub enum UnsafeGeneric { - Region(LifetimeDef, &'static str), - Type(TyParam, &'static str), -} + pub fn own_counts(&self) -> GenericParamCount { + // We could cache this as a property of `GenericParamCount`, but + // the aim is to refactor this away entirely eventually and the + // presence of this method will be a constant reminder. + let mut own_counts = GenericParamCount { + lifetimes: 0, + types: 0, + }; -impl UnsafeGeneric { - pub fn attr_name(&self) -> &'static str { - match *self { - UnsafeGeneric::Region(_, s) => s, - UnsafeGeneric::Type(_, s) => s, - } - } -} - -impl Generics { - pub fn carries_unsafe_attr(&self) -> Option { for param in &self.params { - match *param { - GenericParam::Lifetime(ref l) => { - if l.pure_wrt_drop { - return Some(UnsafeGeneric::Region(l.clone(), "may_dangle")); - } - } - GenericParam::Type(ref t) => { - if t.pure_wrt_drop { - return Some(UnsafeGeneric::Type(t.clone(), "may_dangle")); - } - } - } + match param.kind { + GenericParamKind::Lifetime { .. } => own_counts.lifetimes += 1, + GenericParamKind::Type { .. } => own_counts.types += 1, + }; } - None + own_counts } } @@ -640,7 +588,7 @@ pub struct WhereBoundPredicate { /// The type being bounded pub bounded_ty: P, /// Trait and lifetime bounds (`Clone+Send+'static`) - pub bounds: TyParamBounds, + pub bounds: GenericBounds, } /// A lifetime predicate, e.g. `'a: 'b+'c` @@ -648,7 +596,7 @@ pub struct WhereBoundPredicate { pub struct WhereRegionPredicate { pub span: Span, pub lifetime: Lifetime, - pub bounds: HirVec, + pub bounds: GenericBounds, } /// An equality predicate (unsupported), e.g. `T=int` @@ -1607,7 +1555,7 @@ pub enum TraitItemKind { Method(MethodSig, TraitMethod), /// An associated type with (possibly empty) bounds and optional concrete /// type - Type(TyParamBounds, Option>), + Type(GenericBounds, Option>), } // The bodies for items are stored "out of line", in a separate @@ -1692,7 +1640,7 @@ pub struct BareFnTy { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct ExistTy { pub generics: Generics, - pub bounds: TyParamBounds, + pub bounds: GenericBounds, pub impl_trait_fn: Option, } @@ -2101,9 +2049,9 @@ pub enum Item_ { /// A union definition, e.g. `union Foo {x: A, y: B}` ItemUnion(VariantData, Generics), /// Represents a Trait Declaration - ItemTrait(IsAuto, Unsafety, Generics, TyParamBounds, HirVec), + ItemTrait(IsAuto, Unsafety, Generics, GenericBounds, HirVec), /// Represents a Trait Alias Declaration - ItemTraitAlias(Generics, TyParamBounds), + ItemTraitAlias(Generics, GenericBounds), /// An implementation, eg `impl Trait for Foo { .. }` ItemImpl(Unsafety, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 1beef3f715e22..14f780fab7f2e 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -24,7 +24,8 @@ use syntax::util::parser::{self, AssocOp, Fixity}; use syntax_pos::{self, BytePos, FileName}; use hir; -use hir::{PatKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier, RangeEnd}; +use hir::{PatKind, GenericBound, TraitBoundModifier, RangeEnd}; +use hir::{GenericParam, GenericParamKind, GenericArg}; use std::cell::Cell; use std::io::{self, Write, Read}; @@ -513,7 +514,7 @@ impl<'a> State<'a> { fn print_associated_type(&mut self, name: ast::Name, - bounds: Option<&hir::TyParamBounds>, + bounds: Option<&hir::GenericBounds>, ty: Option<&hir::Ty>) -> io::Result<()> { self.word_space("type")?; @@ -661,7 +662,7 @@ impl<'a> State<'a> { self.word_space(":")?; let mut real_bounds = Vec::with_capacity(exist.bounds.len()); for b in exist.bounds.iter() { - if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b { + if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { self.s.space()?; self.word_space("for ?")?; self.print_trait_ref(&ptr.trait_ref)?; @@ -739,7 +740,7 @@ impl<'a> State<'a> { self.print_generic_params(&generics.params)?; let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { - if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b { + if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { self.s.space()?; self.word_space("for ?")?; self.print_trait_ref(&ptr.trait_ref)?; @@ -765,7 +766,7 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(bounds.len()); // FIXME(durka) this seems to be some quite outdated syntax for b in bounds.iter() { - if let TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = *b { + if let GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = *b { self.s.space()?; self.word_space("for ?")?; self.print_trait_ref(&ptr.trait_ref)?; @@ -1268,15 +1269,11 @@ impl<'a> State<'a> { self.s.word(".")?; self.print_name(segment.name)?; - segment.with_parameters(|parameters| { - if !parameters.lifetimes.is_empty() || - !parameters.types.is_empty() || - !parameters.bindings.is_empty() - { - self.print_path_parameters(¶meters, segment.infer_types, true) - } else { - Ok(()) + segment.with_generic_args(|generic_args| { + if !generic_args.args.is_empty() || !generic_args.bindings.is_empty() { + return self.print_generic_args(&generic_args, segment.infer_types, true); } + Ok(()) })?; self.print_call_post(base_args) } @@ -1641,10 +1638,9 @@ impl<'a> State<'a> { if segment.name != keywords::CrateRoot.name() && segment.name != keywords::DollarCrate.name() { self.print_name(segment.name)?; - segment.with_parameters(|parameters| { - self.print_path_parameters(parameters, - segment.infer_types, - colons_before_params) + segment.with_generic_args(|generic_args| { + self.print_generic_args(generic_args, segment.infer_types, + colons_before_params) })?; } } @@ -1673,10 +1669,10 @@ impl<'a> State<'a> { if segment.name != keywords::CrateRoot.name() && segment.name != keywords::DollarCrate.name() { self.print_name(segment.name)?; - segment.with_parameters(|parameters| { - self.print_path_parameters(parameters, - segment.infer_types, - colons_before_params) + segment.with_generic_args(|generic_args| { + self.print_generic_args(generic_args, + segment.infer_types, + colons_before_params) })?; } } @@ -1685,10 +1681,10 @@ impl<'a> State<'a> { self.s.word("::")?; let item_segment = path.segments.last().unwrap(); self.print_name(item_segment.name)?; - item_segment.with_parameters(|parameters| { - self.print_path_parameters(parameters, - item_segment.infer_types, - colons_before_params) + item_segment.with_generic_args(|generic_args| { + self.print_generic_args(generic_args, + item_segment.infer_types, + colons_before_params) }) } hir::QPath::TypeRelative(ref qself, ref item_segment) => { @@ -1697,28 +1693,28 @@ impl<'a> State<'a> { self.s.word(">")?; self.s.word("::")?; self.print_name(item_segment.name)?; - item_segment.with_parameters(|parameters| { - self.print_path_parameters(parameters, - item_segment.infer_types, - colons_before_params) + item_segment.with_generic_args(|generic_args| { + self.print_generic_args(generic_args, + item_segment.infer_types, + colons_before_params) }) } } } - fn print_path_parameters(&mut self, - parameters: &hir::PathParameters, + fn print_generic_args(&mut self, + generic_args: &hir::GenericArgs, infer_types: bool, colons_before_params: bool) -> io::Result<()> { - if parameters.parenthesized { + if generic_args.parenthesized { self.s.word("(")?; - self.commasep(Inconsistent, parameters.inputs(), |s, ty| s.print_type(&ty))?; + self.commasep(Inconsistent, generic_args.inputs(), |s, ty| s.print_type(&ty))?; self.s.word(")")?; self.space_if_not_bol()?; self.word_space("->")?; - self.print_type(¶meters.bindings[0].ty)?; + self.print_type(&generic_args.bindings[0].ty)?; } else { let start = if colons_before_params { "::<" } else { "<" }; let empty = Cell::new(true); @@ -1731,16 +1727,31 @@ impl<'a> State<'a> { } }; - if !parameters.lifetimes.iter().all(|lt| lt.is_elided()) { - for lifetime in ¶meters.lifetimes { - start_or_comma(self)?; - self.print_lifetime(lifetime)?; + let mut types = vec![]; + let mut elide_lifetimes = true; + for arg in &generic_args.args { + match arg { + GenericArg::Lifetime(lt) => { + if !lt.is_elided() { + elide_lifetimes = false; + } + } + GenericArg::Type(ty) => { + types.push(ty); + } } } - - if !parameters.types.is_empty() { + if !elide_lifetimes { + start_or_comma(self)?; + self.commasep(Inconsistent, &generic_args.args, |s, generic_arg| { + match generic_arg { + GenericArg::Lifetime(lt) => s.print_lifetime(lt), + GenericArg::Type(ty) => s.print_type(ty), + } + })?; + } else if !types.is_empty() { start_or_comma(self)?; - self.commasep(Inconsistent, ¶meters.types, |s, ty| s.print_type(&ty))?; + self.commasep(Inconsistent, &types, |s, ty| s.print_type(&ty))?; } // FIXME(eddyb) This would leak into error messages, e.g.: @@ -1750,7 +1761,7 @@ impl<'a> State<'a> { self.s.word("..")?; } - for binding in parameters.bindings.iter() { + for binding in generic_args.bindings.iter() { start_or_comma(self)?; self.print_name(binding.name)?; self.s.space()?; @@ -2060,7 +2071,7 @@ impl<'a> State<'a> { } } - pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::TyParamBound]) -> io::Result<()> { + pub fn print_bounds(&mut self, prefix: &str, bounds: &[hir::GenericBound]) -> io::Result<()> { if !bounds.is_empty() { self.s.word(prefix)?; let mut first = true; @@ -2075,13 +2086,13 @@ impl<'a> State<'a> { } match bound { - TraitTyParamBound(tref, modifier) => { + GenericBound::Trait(tref, modifier) => { if modifier == &TraitBoundModifier::Maybe { self.s.word("?")?; } self.print_poly_trait_ref(tref)?; } - RegionTyParamBound(lt) => { + GenericBound::Outlives(lt) => { self.print_lifetime(lt)?; } } @@ -2090,30 +2101,12 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> { - self.print_name(lifetime.name.name()) - } - - pub fn print_lifetime_def(&mut self, lifetime: &hir::LifetimeDef) -> io::Result<()> { - self.print_lifetime(&lifetime.lifetime)?; - let mut sep = ":"; - for v in &lifetime.bounds { - self.s.word(sep)?; - self.print_lifetime(v)?; - sep = "+"; - } - Ok(()) - } - - pub fn print_generic_params(&mut self, generic_params: &[hir::GenericParam]) -> io::Result<()> { + pub fn print_generic_params(&mut self, generic_params: &[GenericParam]) -> io::Result<()> { if !generic_params.is_empty() { self.s.word("<")?; self.commasep(Inconsistent, generic_params, |s, param| { - match *param { - hir::GenericParam::Lifetime(ref ld) => s.print_lifetime_def(ld), - hir::GenericParam::Type(ref tp) => s.print_ty_param(tp), - } + s.print_generic_param(param) })?; self.s.word(">")?; @@ -2121,19 +2114,41 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_ty_param(&mut self, param: &hir::TyParam) -> io::Result<()> { - self.print_name(param.name)?; - self.print_bounds(":", ¶m.bounds)?; - match param.default { - Some(ref default) => { - self.s.space()?; - self.word_space("=")?; - self.print_type(&default) + pub fn print_generic_param(&mut self, param: &GenericParam) -> io::Result<()> { + self.print_name(param.name.name())?; + match param.kind { + GenericParamKind::Lifetime { .. } => { + let mut sep = ":"; + for bound in ¶m.bounds { + match bound { + GenericBound::Outlives(lt) => { + self.s.word(sep)?; + self.print_lifetime(lt)?; + sep = "+"; + } + _ => bug!(), + } + } + Ok(()) + } + GenericParamKind::Type { ref default, .. } => { + self.print_bounds(":", ¶m.bounds)?; + match default { + Some(default) => { + self.s.space()?; + self.word_space("=")?; + self.print_type(&default) + } + _ => Ok(()), + } } - _ => Ok(()), } } + pub fn print_lifetime(&mut self, lifetime: &hir::Lifetime) -> io::Result<()> { + self.print_name(lifetime.name.name()) + } + pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Result<()> { if where_clause.predicates.is_empty() { return Ok(()); @@ -2165,7 +2180,12 @@ impl<'a> State<'a> { self.s.word(":")?; for (i, bound) in bounds.iter().enumerate() { - self.print_lifetime(bound)?; + match bound { + GenericBound::Outlives(lt) => { + self.print_lifetime(lt)?; + } + _ => bug!(), + } if i != 0 { self.s.word(":")?; diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index ed259b2854511..882194ae64e79 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -142,12 +142,16 @@ impl<'a> HashStable> for hir::ImplItemId { } } +impl_stable_hash_for!(enum hir::ParamName { + Plain(name), + Fresh(index) +}); + impl_stable_hash_for!(enum hir::LifetimeName { + Param(param_name), Implicit, Underscore, - Fresh(index), Static, - Name(name) }); impl_stable_hash_for!(struct hir::Label { @@ -161,13 +165,6 @@ impl_stable_hash_for!(struct hir::Lifetime { name }); -impl_stable_hash_for!(struct hir::LifetimeDef { - lifetime, - bounds, - pure_wrt_drop, - in_band -}); - impl_stable_hash_for!(struct hir::Path { span, def, @@ -177,19 +174,23 @@ impl_stable_hash_for!(struct hir::Path { impl_stable_hash_for!(struct hir::PathSegment { name, infer_types, - parameters + args }); -impl_stable_hash_for!(struct hir::PathParameters { - lifetimes, - types, +impl_stable_hash_for!(enum hir::GenericArg { + Lifetime(lt), + Type(ty) +}); + +impl_stable_hash_for!(struct hir::GenericArgs { + args, bindings, parenthesized }); -impl_stable_hash_for!(enum hir::TyParamBound { - TraitTyParamBound(poly_trait_ref, trait_bound_modifier), - RegionTyParamBound(lifetime) +impl_stable_hash_for!(enum hir::GenericBound { + Trait(poly_trait_ref, trait_bound_modifier), + Outlives(lifetime) }); impl_stable_hash_for!(enum hir::TraitBoundModifier { @@ -197,21 +198,32 @@ impl_stable_hash_for!(enum hir::TraitBoundModifier { Maybe }); -impl_stable_hash_for!(struct hir::TyParam { - name, +impl_stable_hash_for!(struct hir::GenericParam { id, - bounds, - default, + name, span, pure_wrt_drop, - synthetic, - attrs + attrs, + bounds, + kind }); -impl_stable_hash_for!(enum hir::GenericParam { - Lifetime(lifetime_def), - Type(ty_param) -}); +impl<'a> HashStable> for hir::GenericParamKind { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { + mem::discriminant(self).hash_stable(hcx, hasher); + match self { + hir::GenericParamKind::Lifetime { in_band } => { + in_band.hash_stable(hcx, hasher); + } + hir::GenericParamKind::Type { ref default, synthetic } => { + default.hash_stable(hcx, hasher); + synthetic.hash_stable(hcx, hasher); + } + } + } +} impl_stable_hash_for!(struct hir::Generics { params, diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 4bde363672dcc..4d6f2fb41b05d 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -1036,15 +1036,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Get the `hir::TyParam` to verify whether it already has any bounds. // We do this to avoid suggesting code that ends up as `T: 'a'b`, // instead we suggest `T: 'a + 'b` in that case. - let has_lifetimes = if let hir_map::NodeTyParam(ref p) = hir.get(id) { - p.bounds.len() > 0 - } else { - false - }; + let mut has_bounds = false; + if let hir_map::NodeGenericParam(ref param) = hir.get(id) { + has_bounds = !param.bounds.is_empty(); + } let sp = hir.span(id); // `sp` only covers `T`, change it so that it covers // `T:` when appropriate - let sp = if has_lifetimes { + let sp = if has_bounds { sp.to(self.tcx .sess .codemap() @@ -1052,7 +1051,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } else { sp }; - (sp, has_lifetimes) + (sp, has_bounds) }) } else { None diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 40cf78edaecae..7f81af7e46c7d 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -20,7 +20,7 @@ use hir::map as hir_map; use hir::def::Def; use hir::def_id::{DefId, CrateNum}; use rustc_data_structures::sync::Lrc; -use ty::{self, TyCtxt}; +use ty::{self, TyCtxt, GenericParamDefKind}; use ty::query::Providers; use middle::privacy; use session::config; @@ -37,21 +37,30 @@ use hir::intravisit; // Returns true if the given set of generics implies that the item it's // associated with must be inlined. -fn generics_require_inlining(generics: &hir::Generics) -> bool { - generics.params.iter().any(|param| param.is_type_param()) +fn generics_require_inlining(generics: &ty::Generics) -> bool { + for param in &generics.params { + match param.kind { + GenericParamDefKind::Lifetime { .. } => {} + GenericParamDefKind::Type { .. } => return true, + } + } + false } // Returns true if the given item must be inlined because it may be // monomorphized or it was marked with `#[inline]`. This will only return // true for functions. -fn item_might_be_inlined(item: &hir::Item, attrs: CodegenFnAttrs) -> bool { +fn item_might_be_inlined(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item: &hir::Item, + attrs: CodegenFnAttrs) -> bool { if attrs.requests_inline() { return true } match item.node { - hir::ItemImpl(_, _, _, ref generics, ..) | - hir::ItemFn(.., ref generics, _) => { + hir::ItemImpl(..) | + hir::ItemFn(..) => { + let generics = tcx.generics_of(tcx.hir.local_def_id(item.id)); generics_require_inlining(generics) } _ => false, @@ -62,14 +71,14 @@ fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item: &hir::ImplItem, impl_src: DefId) -> bool { let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id()); - if codegen_fn_attrs.requests_inline() || - generics_require_inlining(&impl_item.generics) { + let generics = tcx.generics_of(tcx.hir.local_def_id(impl_item.id)); + if codegen_fn_attrs.requests_inline() || generics_require_inlining(generics) { return true } if let Some(impl_node_id) = tcx.hir.as_local_node_id(impl_src) { match tcx.hir.find(impl_node_id) { Some(hir_map::NodeItem(item)) => - item_might_be_inlined(&item, codegen_fn_attrs), + item_might_be_inlined(tcx, &item, codegen_fn_attrs), Some(..) | None => span_bug!(impl_item.span, "impl did is not an item") } @@ -163,7 +172,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { Some(hir_map::NodeItem(item)) => { match item.node { hir::ItemFn(..) => - item_might_be_inlined(&item, self.tcx.codegen_fn_attrs(def_id)), + item_might_be_inlined(self.tcx, &item, self.tcx.codegen_fn_attrs(def_id)), _ => false, } } @@ -180,7 +189,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::ImplItemKind::Const(..) => true, hir::ImplItemKind::Method(..) => { let attrs = self.tcx.codegen_fn_attrs(def_id); - if generics_require_inlining(&impl_item.generics) || + let generics = self.tcx.generics_of(def_id); + if generics_require_inlining(&generics) || attrs.requests_inline() { true } else { @@ -192,8 +202,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // does too. let impl_node_id = self.tcx.hir.as_local_node_id(impl_did).unwrap(); match self.tcx.hir.expect_item(impl_node_id).node { - hir::ItemImpl(_, _, _, ref generics, ..) => { - generics_require_inlining(generics) + hir::ItemImpl(..) => { + let generics = self.tcx.generics_of(impl_did); + generics_require_inlining(&generics) } _ => false } @@ -251,7 +262,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { match item.node { hir::ItemFn(.., body) => { let def_id = self.tcx.hir.local_def_id(item.id); - if item_might_be_inlined(&item, self.tcx.codegen_fn_attrs(def_id)) { + if item_might_be_inlined(self.tcx, + &item, + self.tcx.codegen_fn_attrs(def_id)) { self.visit_nested_body(body); } } diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index f251a3d5f3838..091662966ea8f 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -18,8 +18,7 @@ use hir::def::Def; use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use hir::map::Map; -use hir::ItemLocalId; -use hir::LifetimeName; +use hir::{GenericArg, GenericParam, ItemLocalId, LifetimeName, ParamName}; use ty::{self, TyCtxt, GenericParamDefKind}; use errors::DiagnosticBuilder; @@ -28,15 +27,15 @@ use rustc_data_structures::sync::Lrc; use session::Session; use std::cell::Cell; use std::mem::replace; -use std::slice; use syntax::ast; use syntax::attr; use syntax::ptr::P; +use syntax::symbol::keywords; use syntax_pos::Span; use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap, NodeSet}; use hir::intravisit::{self, NestedVisitorMap, Visitor}; -use hir::{self, GenericParamsExt}; +use hir::{self, GenericParamKind}; /// The origin of a named lifetime definition. /// @@ -50,11 +49,16 @@ pub enum LifetimeDefOrigin { } impl LifetimeDefOrigin { - fn from_is_in_band(is_in_band: bool) -> Self { - if is_in_band { - LifetimeDefOrigin::InBand - } else { - LifetimeDefOrigin::Explicit + fn from_param(param: &GenericParam) -> Self { + match param.kind { + GenericParamKind::Lifetime { in_band } => { + if in_band { + LifetimeDefOrigin::InBand + } else { + LifetimeDefOrigin::Explicit + } + } + _ => bug!("expected a lifetime param"), } } } @@ -84,31 +88,27 @@ pub enum Region { } impl Region { - fn early( - hir_map: &Map, - index: &mut u32, - def: &hir::LifetimeDef, - ) -> (hir::LifetimeName, Region) { + fn early(hir_map: &Map, index: &mut u32, param: &GenericParam) -> (ParamName, Region) { let i = *index; *index += 1; - let def_id = hir_map.local_def_id(def.lifetime.id); - let origin = LifetimeDefOrigin::from_is_in_band(def.in_band); + let def_id = hir_map.local_def_id(param.id); + let origin = LifetimeDefOrigin::from_param(param); debug!("Region::early: index={} def_id={:?}", i, def_id); - (def.lifetime.name, Region::EarlyBound(i, def_id, origin)) + (param.name, Region::EarlyBound(i, def_id, origin)) } - fn late(hir_map: &Map, def: &hir::LifetimeDef) -> (hir::LifetimeName, Region) { + fn late(hir_map: &Map, param: &GenericParam) -> (ParamName, Region) { let depth = ty::INNERMOST; - let def_id = hir_map.local_def_id(def.lifetime.id); - let origin = LifetimeDefOrigin::from_is_in_band(def.in_band); + let def_id = hir_map.local_def_id(param.id); + let origin = LifetimeDefOrigin::from_param(param); debug!( - "Region::late: def={:?} depth={:?} def_id={:?} origin={:?}", - def, + "Region::late: param={:?} depth={:?} def_id={:?} origin={:?}", + param, depth, def_id, origin, ); - (def.lifetime.name, Region::LateBound(depth, def_id, origin)) + (param.name, Region::LateBound(depth, def_id, origin)) } fn late_anon(index: &Cell) -> Region { @@ -155,11 +155,10 @@ impl Region { } } - fn subst(self, params: &[hir::Lifetime], map: &NamedRegionMap) -> Option { + fn subst<'a, L>(self, mut params: L, map: &NamedRegionMap) -> Option + where L: Iterator { if let Region::EarlyBound(index, _, _) = self { - params - .get(index as usize) - .and_then(|lifetime| map.defs.get(&lifetime.id).cloned()) + params.nth(index as usize).and_then(|lifetime| map.defs.get(&lifetime.id).cloned()) } else { Some(self) } @@ -270,7 +269,7 @@ enum Scope<'a> { /// it should be shifted by the number of `Binder`s in between the /// declaration `Binder` and the location it's referenced from. Binder { - lifetimes: FxHashMap, + lifetimes: FxHashMap, /// if we extend this scope with another scope, what is the next index /// we should use for an early-bound region? @@ -524,14 +523,19 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } else { 0 }; - let lifetimes = generics - .lifetimes() - .map(|def| Region::early(&self.tcx.hir, &mut index, def)) - .collect(); - let next_early_index = index + generics.ty_params().count() as u32; + let mut type_count = 0; + let lifetimes = generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + Some(Region::early(&self.tcx.hir, &mut index, param)) + } + GenericParamKind::Type { .. } => { + type_count += 1; + None + } + }).collect(); let scope = Scope::Binder { lifetimes, - next_early_index, + next_early_index: index + type_count, abstract_type_parent: true, track_lifetime_uses, s: ROOT_SCOPE, @@ -568,10 +572,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let was_in_fn_syntax = self.is_in_fn_syntax; self.is_in_fn_syntax = true; let scope = Scope::Binder { - lifetimes: c.generic_params - .lifetimes() - .map(|def| Region::late(&self.tcx.hir, def)) - .collect(), + lifetimes: c.generic_params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + Some(Region::late(&self.tcx.hir, param)) + } + _ => None, + }).collect(), s: self.scope, next_early_index, track_lifetime_uses: true, @@ -603,9 +609,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // resolved the same as the `'_` in `&'_ Foo`. // // cc #48468 - self.resolve_elided_lifetimes(slice::from_ref(lifetime), false) + self.resolve_elided_lifetimes(vec![lifetime], false) } - LifetimeName::Fresh(_) | LifetimeName::Static | LifetimeName::Name(_) => { + LifetimeName::Param(_) | LifetimeName::Static => { // If the user wrote an explicit name, use that. self.visit_lifetime(lifetime); } @@ -676,18 +682,29 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let mut elision = None; let mut lifetimes = FxHashMap(); - for lt_def in generics.lifetimes() { - let (lt_name, region) = Region::early(&self.tcx.hir, &mut index, <_def); - if let hir::LifetimeName::Underscore = lt_name { - // Pick the elided lifetime "definition" if one exists and use it to make - // an elision scope. - elision = Some(region); - } else { - lifetimes.insert(lt_name, region); + let mut type_count = 0; + for param in &generics.params { + match param.kind { + GenericParamKind::Lifetime { .. } => { + let (name, reg) = Region::early(&self.tcx.hir, &mut index, ¶m); + if let hir::ParamName::Plain(param_name) = name { + if param_name == keywords::UnderscoreLifetime.name() { + // Pick the elided lifetime "definition" if one exists + // and use it to make an elision scope. + elision = Some(reg); + } else { + lifetimes.insert(name, reg); + } + } else { + lifetimes.insert(name, reg); + } + } + GenericParamKind::Type { .. } => { + type_count += 1; + } } } - - let next_early_index = index + generics.ty_params().count() as u32; + let next_early_index = index + type_count; if let Some(elision_region) = elision { let scope = Scope::Elision { @@ -705,7 +722,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { this.with(scope, |_old_scope, this| { this.visit_generics(generics); for bound in bounds { - this.visit_ty_param_bound(bound); + this.visit_param_bound(bound); } }); }); @@ -720,7 +737,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.with(scope, |_old_scope, this| { this.visit_generics(generics); for bound in bounds { - this.visit_ty_param_bound(bound); + this.visit_param_bound(bound); } }); } @@ -745,15 +762,19 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let generics = &trait_item.generics; let mut index = self.next_early_index(); debug!("visit_ty: index = {}", index); - let lifetimes = generics - .lifetimes() - .map(|lt_def| Region::early(&self.tcx.hir, &mut index, lt_def)) - .collect(); - - let next_early_index = index + generics.ty_params().count() as u32; + let mut type_count = 0; + let lifetimes = generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + Some(Region::early(&self.tcx.hir, &mut index, param)) + } + GenericParamKind::Type { .. } => { + type_count += 1; + None + } + }).collect(); let scope = Scope::Binder { lifetimes, - next_early_index, + next_early_index: index + type_count, s: self.scope, track_lifetime_uses: true, abstract_type_parent: true, @@ -761,7 +782,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.with(scope, |_old_scope, this| { this.visit_generics(generics); for bound in bounds { - this.visit_ty_param_bound(bound); + this.visit_param_bound(bound); } if let Some(ty) = ty { this.visit_ty(ty); @@ -791,13 +812,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { Type(ref ty) => { let generics = &impl_item.generics; let mut index = self.next_early_index(); + let mut next_early_index = index; debug!("visit_ty: index = {}", index); - let lifetimes = generics - .lifetimes() - .map(|lt_def| Region::early(&self.tcx.hir, &mut index, lt_def)) - .collect(); - - let next_early_index = index + generics.ty_params().count() as u32; + let lifetimes = generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + Some(Region::early(&self.tcx.hir, &mut index, param)) + } + GenericParamKind::Type { .. } => { + next_early_index += 1; + None + } + }).collect(); let scope = Scope::Binder { lifetimes, next_early_index, @@ -820,7 +845,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { if lifetime_ref.is_elided() { - self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref), false); + self.resolve_elided_lifetimes(vec![lifetime_ref], false); return; } if lifetime_ref.is_static() { @@ -833,8 +858,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) { for (i, segment) in path.segments.iter().enumerate() { let depth = path.segments.len() - i - 1; - if let Some(ref parameters) = segment.parameters { - self.visit_segment_parameters(path.def, depth, parameters); + if let Some(ref args) = segment.args { + self.visit_segment_args(path.def, depth, args); } } } @@ -848,14 +873,16 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { - check_mixed_explicit_and_in_band_defs( - self.tcx, - &generics.lifetimes().cloned().collect::>(), - ); - for ty_param in generics.ty_params() { - walk_list!(self, visit_ty_param_bound, &ty_param.bounds); - if let Some(ref ty) = ty_param.default { - self.visit_ty(&ty); + check_mixed_explicit_and_in_band_defs(self.tcx, &generics.params); + for param in &generics.params { + match param.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { ref default, .. } => { + walk_list!(self, visit_param_bound, ¶m.bounds); + if let Some(ref ty) = default { + self.visit_ty(&ty); + } + } } } for predicate in &generics.where_clause.predicates { @@ -866,14 +893,18 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { ref bound_generic_params, .. }) => { - if bound_generic_params.iter().any(|p| p.is_lifetime_param()) { + let lifetimes: FxHashMap<_, _> = bound_generic_params.iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + Some(Region::late(&self.tcx.hir, param)) + } + _ => None, + }).collect(); + if !lifetimes.is_empty() { self.trait_ref_hack = true; let next_early_index = self.next_early_index(); let scope = Scope::Binder { - lifetimes: bound_generic_params - .lifetimes() - .map(|def| Region::late(&self.tcx.hir, def)) - .collect(), + lifetimes, s: self.scope, next_early_index, track_lifetime_uses: true, @@ -882,13 +913,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let result = self.with(scope, |old_scope, this| { this.check_lifetime_params(old_scope, &bound_generic_params); this.visit_ty(&bounded_ty); - walk_list!(this, visit_ty_param_bound, bounds); + walk_list!(this, visit_param_bound, bounds); }); self.trait_ref_hack = false; result } else { self.visit_ty(&bounded_ty); - walk_list!(self, visit_ty_param_bound, bounds); + walk_list!(self, visit_param_bound, bounds); } } &hir::WherePredicate::RegionPredicate(hir::WhereRegionPredicate { @@ -897,9 +928,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { .. }) => { self.visit_lifetime(lifetime); - for bound in bounds { - self.visit_lifetime(bound); - } + walk_list!(self, visit_param_bound, bounds); } &hir::WherePredicate::EqPredicate(hir::WhereEqPredicate { ref lhs_ty, @@ -924,7 +953,10 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { || trait_ref .bound_generic_params .iter() - .any(|p| p.is_lifetime_param()) + .any(|param| match param.kind { + GenericParamKind::Lifetime { .. } => true, + _ => false, + }) { if self.trait_ref_hack { span_err!( @@ -936,11 +968,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } let next_early_index = self.next_early_index(); let scope = Scope::Binder { - lifetimes: trait_ref - .bound_generic_params - .lifetimes() - .map(|def| Region::late(&self.tcx.hir, def)) - .collect(), + lifetimes: trait_ref.bound_generic_params.iter() + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + Some(Region::late(&self.tcx.hir, param)) + } + _ => None, + }).collect(), s: self.scope, next_early_index, track_lifetime_uses: true, @@ -989,10 +1023,10 @@ fn original_lifetime(span: Span) -> Original { span: span, } } -fn shadower_lifetime(l: &hir::Lifetime) -> Shadower { +fn shadower_lifetime(param: &hir::GenericParam) -> Shadower { Shadower { kind: ShadowKind::Lifetime, - span: l.span, + span: param.span, } } @@ -1007,23 +1041,27 @@ impl ShadowKind { fn check_mixed_explicit_and_in_band_defs( tcx: TyCtxt<'_, '_, '_>, - lifetime_defs: &[hir::LifetimeDef], + params: &P<[hir::GenericParam]>, ) { - let oob_def = lifetime_defs.iter().find(|lt| !lt.in_band); - let in_band_def = lifetime_defs.iter().find(|lt| lt.in_band); - - if let (Some(oob_def), Some(in_band_def)) = (oob_def, in_band_def) { + let in_bands: Vec<_> = params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { in_band, .. } => Some((in_band, param.span)), + _ => None, + }).collect(); + let out_of_band = in_bands.iter().find(|(in_band, _)| !in_band); + let in_band = in_bands.iter().find(|(in_band, _)| *in_band); + + if let (Some((_, out_of_band_span)), Some((_, in_band_span))) + = (out_of_band, in_band) { struct_span_err!( tcx.sess, - in_band_def.lifetime.span, + *in_band_span, E0688, "cannot mix in-band and explicit lifetime definitions" ).span_label( - in_band_def.lifetime.span, + *in_band_span, "in-band lifetime definition here", - ) - .span_label(oob_def.lifetime.span, "explicit lifetime definition here") - .emit(); + ).span_label(*out_of_band_span, "explicit lifetime definition here") + .emit(); } } @@ -1138,7 +1176,8 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body) { ref lifetimes, s, .. } => { // FIXME (#24278): non-hygienic comparison - if let Some(def) = lifetimes.get(&hir::LifetimeName::Name(label)) { + let param_name = hir::ParamName::Plain(label); + if let Some(def) = lifetimes.get(¶m_name) { let node_id = tcx.hir.as_local_node_id(def.id().unwrap()).unwrap(); signal_shadowing_problem( @@ -1176,14 +1215,18 @@ fn compute_object_lifetime_defaults( .map(|set| match *set { Set1::Empty => "BaseDefault".to_string(), Set1::One(Region::Static) => "'static".to_string(), - Set1::One(Region::EarlyBound(i, _, _)) => generics - .lifetimes() - .nth(i as usize) - .unwrap() - .lifetime - .name - .name() - .to_string(), + Set1::One(Region::EarlyBound(mut i, _, _)) => { + generics.params.iter().find_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + if i == 0 { + return Some(param.name.name().to_string()); + } + i -= 1; + None + } + _ => None, + }).unwrap() + } Set1::One(_) => bug!(), Set1::Many => "Ambiguous".to_string(), }) @@ -1207,17 +1250,17 @@ fn object_lifetime_defaults_for_item( tcx: TyCtxt<'_, '_, '_>, generics: &hir::Generics, ) -> Vec { - fn add_bounds(set: &mut Set1, bounds: &[hir::TyParamBound]) { + fn add_bounds(set: &mut Set1, bounds: &[hir::GenericBound]) { for bound in bounds { - if let hir::RegionTyParamBound(ref lifetime) = *bound { + if let hir::GenericBound::Outlives(ref lifetime) = *bound { set.insert(lifetime.name); } } } - generics - .ty_params() - .map(|param| { + generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => None, + GenericParamKind::Type { .. } => { let mut set = Set1::Empty; add_bounds(&mut set, ¶m.bounds); @@ -1246,27 +1289,35 @@ fn object_lifetime_defaults_for_item( } } - match set { + Some(match set { Set1::Empty => Set1::Empty, Set1::One(name) => { if name == hir::LifetimeName::Static { Set1::One(Region::Static) } else { - generics - .lifetimes() - .enumerate() - .find(|&(_, def)| def.lifetime.name == name) - .map_or(Set1::Many, |(i, def)| { - let def_id = tcx.hir.local_def_id(def.lifetime.id); - let origin = LifetimeDefOrigin::from_is_in_band(def.in_band); - Set1::One(Region::EarlyBound(i as u32, def_id, origin)) - }) + generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + Some(( + param.id, + hir::LifetimeName::Param(param.name), + LifetimeDefOrigin::from_param(param), + )) + } + _ => None, + }) + .enumerate() + .find(|&(_, (_, lt_name, _))| lt_name == name) + .map_or(Set1::Many, |(i, (id, _, origin))| { + let def_id = tcx.hir.local_def_id(id); + Set1::One(Region::EarlyBound(i as u32, def_id, origin)) + }) } } Set1::Many => Set1::Many, - } - }) - .collect() + }) + } + }) + .collect() } impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { @@ -1346,25 +1397,22 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Some(LifetimeUseSet::One(_)) => { let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); debug!("node id first={:?}", node_id); - if let hir::map::NodeLifetime(hir_lifetime) = self.tcx.hir.get(node_id) { - let span = hir_lifetime.span; - let id = hir_lifetime.id; - debug!( - "id ={:?} span = {:?} hir_lifetime = {:?}", - node_id, span, hir_lifetime - ); - - self.tcx - .struct_span_lint_node( - lint::builtin::SINGLE_USE_LIFETIMES, - id, - span, - &format!( - "lifetime parameter `{}` only used once", - hir_lifetime.name.name() - ), - ) - .emit(); + if let Some((id, span, name)) = match self.tcx.hir.get(node_id) { + hir::map::NodeLifetime(hir_lifetime) => { + Some((hir_lifetime.id, hir_lifetime.span, hir_lifetime.name.name())) + } + hir::map::NodeGenericParam(param) => { + Some((param.id, param.span, param.name.name())) + } + _ => None, + } { + debug!("id = {:?} span = {:?} name = {:?}", node_id, span, name); + self.tcx.struct_span_lint_node( + lint::builtin::SINGLE_USE_LIFETIMES, + id, + span, + &format!("lifetime parameter `{}` only used once", name), + ).emit(); } } Some(LifetimeUseSet::Many) => { @@ -1372,21 +1420,22 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } None => { let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); - if let hir::map::NodeLifetime(hir_lifetime) = self.tcx.hir.get(node_id) { - let span = hir_lifetime.span; - let id = hir_lifetime.id; - - self.tcx - .struct_span_lint_node( - lint::builtin::UNUSED_LIFETIMES, - id, - span, - &format!( - "lifetime parameter `{}` never used", - hir_lifetime.name.name() - ), - ) - .emit(); + if let Some((id, span, name)) = match self.tcx.hir.get(node_id) { + hir::map::NodeLifetime(hir_lifetime) => { + Some((hir_lifetime.id, hir_lifetime.span, hir_lifetime.name.name())) + } + hir::map::NodeGenericParam(param) => { + Some((param.id, param.span, param.name.name())) + } + _ => None, + } { + debug!("id ={:?} span = {:?} name = {:?}", node_id, span, name); + self.tcx.struct_span_lint_node( + lint::builtin::UNUSED_LIFETIMES, + id, + span, + &format!("lifetime parameter `{}` never used", name) + ).emit(); } } } @@ -1438,18 +1487,21 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } - let lifetimes = generics - .lifetimes() - .map(|def| { - if self.map.late_bound.contains(&def.lifetime.id) { - Region::late(&self.tcx.hir, def) + let mut type_count = 0; + let lifetimes = generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + if self.map.late_bound.contains(¶m.id) { + Some(Region::late(&self.tcx.hir, param)) } else { - Region::early(&self.tcx.hir, &mut index, def) + Some(Region::early(&self.tcx.hir, &mut index, param)) } - }) - .collect(); - - let next_early_index = index + generics.ty_params().count() as u32; + } + GenericParamKind::Type { .. } => { + type_count += 1; + None + } + }).collect(); + let next_early_index = index + type_count; let scope = Scope::Binder { lifetimes, @@ -1521,10 +1573,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { break None; } - Scope::Binder { - ref lifetimes, s, .. - } => { - if let Some(&def) = lifetimes.get(&lifetime_ref.name) { + Scope::Binder { ref lifetimes, s, .. } => { + let name = match lifetime_ref.name { + LifetimeName::Param(param_name) => param_name, + _ => bug!("expected LifetimeName::Param"), + }; + if let Some(&def) = lifetimes.get(&name) { break Some(def.shifted(late_depth)); } else { late_depth += 1; @@ -1599,26 +1653,35 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } - fn visit_segment_parameters( + fn visit_segment_args( &mut self, def: Def, depth: usize, - params: &'tcx hir::PathParameters, + generic_args: &'tcx hir::GenericArgs, ) { - if params.parenthesized { + if generic_args.parenthesized { let was_in_fn_syntax = self.is_in_fn_syntax; self.is_in_fn_syntax = true; - self.visit_fn_like_elision(params.inputs(), Some(¶ms.bindings[0].ty)); + self.visit_fn_like_elision(generic_args.inputs(), + Some(&generic_args.bindings[0].ty)); self.is_in_fn_syntax = was_in_fn_syntax; return; } - if params.lifetimes.iter().all(|l| l.is_elided()) { - self.resolve_elided_lifetimes(¶ms.lifetimes, true); - } else { - for l in ¶ms.lifetimes { - self.visit_lifetime(l); + let mut elide_lifetimes = true; + let lifetimes = generic_args.args.iter().filter_map(|arg| match arg { + hir::GenericArg::Lifetime(lt) => { + if !lt.is_elided() { + elide_lifetimes = false; + } + Some(lt) } + _ => None, + }).collect(); + if elide_lifetimes { + self.resolve_elided_lifetimes(lifetimes, true); + } else { + lifetimes.iter().for_each(|lt| self.visit_lifetime(lt)); } // Figure out if this is a type/trait segment, @@ -1680,33 +1743,45 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }).collect() }) }; - unsubst - .iter() - .map(|set| match *set { - Set1::Empty => if in_body { - None - } else { - Some(Region::Static) - }, - Set1::One(r) => r.subst(¶ms.lifetimes, map), - Set1::Many => None, - }) - .collect() + unsubst.iter() + .map(|set| match *set { + Set1::Empty => if in_body { + None + } else { + Some(Region::Static) + }, + Set1::One(r) => { + let lifetimes = generic_args.args.iter().filter_map(|arg| match arg { + GenericArg::Lifetime(lt) => Some(lt), + _ => None, + }); + r.subst(lifetimes, map) + } + Set1::Many => None, + }) + .collect() }); - for (i, ty) in params.types.iter().enumerate() { - if let Some(<) = object_lifetime_defaults.get(i) { - let scope = Scope::ObjectLifetimeDefault { - lifetime: lt, - s: self.scope, - }; - self.with(scope, |_, this| this.visit_ty(ty)); - } else { - self.visit_ty(ty); + let mut i = 0; + for arg in &generic_args.args { + match arg { + GenericArg::Lifetime(_) => {} + GenericArg::Type(ty) => { + if let Some(<) = object_lifetime_defaults.get(i) { + let scope = Scope::ObjectLifetimeDefault { + lifetime: lt, + s: self.scope, + }; + self.with(scope, |_, this| this.visit_ty(ty)); + } else { + self.visit_ty(ty); + } + i += 1; + } } } - for b in ¶ms.bindings { + for b in &generic_args.bindings { self.visit_assoc_type_binding(b); } } @@ -1944,7 +2019,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } fn visit_generic_param(&mut self, param: &hir::GenericParam) { - if let hir::GenericParam::Lifetime(_) = *param { + if let hir::GenericParamKind::Lifetime { .. } = param.kind { // FIXME(eddyb) Do we want this? It only makes a difference // if this `for<'a>` lifetime parameter is never used. self.have_bound_regions = true; @@ -1981,7 +2056,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } - fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime], deprecated: bool) { + fn resolve_elided_lifetimes(&mut self, + lifetime_refs: Vec<&'tcx hir::Lifetime>, + deprecated: bool) { if lifetime_refs.is_empty() { return; } @@ -2159,100 +2236,99 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } fn check_lifetime_params(&mut self, old_scope: ScopeRef, params: &'tcx [hir::GenericParam]) { - for (i, lifetime_i) in params.lifetimes().enumerate() { - match lifetime_i.lifetime.name { - hir::LifetimeName::Static | hir::LifetimeName::Underscore => { - let lifetime = lifetime_i.lifetime; - let name = lifetime.name.name(); + let lifetimes: Vec<_> = params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => Some((param, param.name)), + _ => None, + }).collect(); + for (i, (lifetime_i, lifetime_i_name)) in lifetimes.iter().enumerate() { + if let hir::ParamName::Plain(_) = lifetime_i_name { + let name = lifetime_i_name.name(); + if name == keywords::UnderscoreLifetime.name() || + name == keywords::StaticLifetime.name() { let mut err = struct_span_err!( self.tcx.sess, - lifetime.span, + lifetime_i.span, E0262, "invalid lifetime parameter name: `{}`", name ); err.span_label( - lifetime.span, + lifetime_i.span, format!("{} is a reserved lifetime name", name), ); err.emit(); } - hir::LifetimeName::Fresh(_) - | hir::LifetimeName::Implicit - | hir::LifetimeName::Name(_) => {} } // It is a hard error to shadow a lifetime within the same scope. - for lifetime_j in params.lifetimes().skip(i + 1) { - if lifetime_i.lifetime.name == lifetime_j.lifetime.name { + for (lifetime_j, lifetime_j_name) in lifetimes.iter().skip(i + 1) { + if lifetime_i_name == lifetime_j_name { struct_span_err!( self.tcx.sess, - lifetime_j.lifetime.span, + lifetime_j.span, E0263, "lifetime name `{}` declared twice in the same scope", - lifetime_j.lifetime.name.name() - ).span_label(lifetime_j.lifetime.span, "declared twice") - .span_label(lifetime_i.lifetime.span, "previous declaration here") - .emit(); + lifetime_j.name.name() + ).span_label(lifetime_j.span, "declared twice") + .span_label(lifetime_i.span, "previous declaration here") + .emit(); } } // It is a soft error to shadow a lifetime within a parent scope. - self.check_lifetime_def_for_shadowing(old_scope, &lifetime_i.lifetime); + self.check_lifetime_param_for_shadowing(old_scope, &lifetime_i); for bound in &lifetime_i.bounds { - match bound.name { - hir::LifetimeName::Underscore => { - let mut err = struct_span_err!( - self.tcx.sess, - bound.span, - E0637, - "invalid lifetime bound name: `'_`" - ); - err.span_label(bound.span, "`'_` is a reserved lifetime name"); - err.emit(); - } - hir::LifetimeName::Static => { - self.insert_lifetime(bound, Region::Static); - self.tcx - .sess - .struct_span_warn( - lifetime_i.lifetime.span.to(bound.span), + match bound { + hir::GenericBound::Outlives(lt) => match lt.name { + hir::LifetimeName::Underscore => { + let mut err = struct_span_err!( + self.tcx.sess, + lt.span, + E0637, + "invalid lifetime bound name: `'_`" + ); + err.span_label(lt.span, "`'_` is a reserved lifetime name"); + err.emit(); + } + hir::LifetimeName::Static => { + self.insert_lifetime(lt, Region::Static); + self.tcx.sess.struct_span_warn( + lifetime_i.span.to(lt.span), &format!( "unnecessary lifetime parameter `{}`", - lifetime_i.lifetime.name.name() + lifetime_i.name.name(), ), - ) - .help(&format!( + ).help(&format!( "you can use the `'static` lifetime directly, in place \ - of `{}`", - lifetime_i.lifetime.name.name() - )) - .emit(); - } - hir::LifetimeName::Fresh(_) - | hir::LifetimeName::Implicit - | hir::LifetimeName::Name(_) => { - self.resolve_lifetime_ref(bound); + of `{}`", + lifetime_i.name.name(), + )).emit(); + } + hir::LifetimeName::Param(_) + | hir::LifetimeName::Implicit => { + self.resolve_lifetime_ref(lt); + } } + _ => bug!(), } } } } - fn check_lifetime_def_for_shadowing( + fn check_lifetime_param_for_shadowing( &self, mut old_scope: ScopeRef, - lifetime: &'tcx hir::Lifetime, + param: &'tcx hir::GenericParam, ) { for &(label, label_span) in &self.labels_in_fn { // FIXME (#24278): non-hygienic comparison - if lifetime.name.name() == label { + if param.name.name() == label { signal_shadowing_problem( self.tcx, label, original_label(label_span), - shadower_lifetime(&lifetime), + shadower_lifetime(¶m), ); return; } @@ -2273,14 +2349,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Binder { ref lifetimes, s, .. } => { - if let Some(&def) = lifetimes.get(&lifetime.name) { + if let Some(&def) = lifetimes.get(¶m.name) { let node_id = self.tcx.hir.as_local_node_id(def.id().unwrap()).unwrap(); signal_shadowing_problem( self.tcx, - lifetime.name.name(), + param.name.name(), original_lifetime(self.tcx.hir.span(node_id)), - shadower_lifetime(&lifetime), + shadower_lifetime(¶m), ); return; } @@ -2428,14 +2504,14 @@ fn insert_late_bound_lifetimes( appears_in_where_clause.visit_generics(generics); for param in &generics.params { - match *param { - hir::GenericParam::Lifetime(ref lifetime_def) => { - if !lifetime_def.bounds.is_empty() { + match param.kind { + hir::GenericParamKind::Lifetime { .. } => { + if !param.bounds.is_empty() { // `'a: 'b` means both `'a` and `'b` are referenced - appears_in_where_clause.regions.insert(lifetime_def.lifetime.name); + appears_in_where_clause.regions.insert(hir::LifetimeName::Param(param.name)); } } - hir::GenericParam::Type(_) => {} + hir::GenericParamKind::Type { .. } => {} } } @@ -2448,33 +2524,26 @@ fn insert_late_bound_lifetimes( // - appear in the inputs // - do not appear in the where-clauses // - are not implicitly captured by `impl Trait` - for lifetime in generics.lifetimes() { - let name = lifetime.lifetime.name; - + for param in &generics.params { + let lt_name = hir::LifetimeName::Param(param.name); // appears in the where clauses? early-bound. - if appears_in_where_clause.regions.contains(&name) { + if appears_in_where_clause.regions.contains(<_name) { continue; } // does not appear in the inputs, but appears in the return type? early-bound. - if !constrained_by_input.regions.contains(&name) - && appears_in_output.regions.contains(&name) + if !constrained_by_input.regions.contains(<_name) + && appears_in_output.regions.contains(<_name) { continue; } - debug!( - "insert_late_bound_lifetimes: \ - lifetime {:?} with id {:?} is late-bound", - lifetime.lifetime.name, lifetime.lifetime.id - ); + debug!("insert_late_bound_lifetimes: lifetime {:?} with id {:?} is late-bound", + param.name.name(), + param.id); - let inserted = map.late_bound.insert(lifetime.lifetime.id); - assert!( - inserted, - "visited lifetime {:?} twice", - lifetime.lifetime.id - ); + let inserted = map.late_bound.insert(param.id); + assert!(inserted, "visited lifetime {:?} twice", param.id); } return; diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index 227cba40d1463..f48739799203f 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -224,11 +224,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let names_map: FxHashSet = generics .params .iter() - .filter_map(|param| { - match param.kind { - ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()), - _ => None - } + .filter_map(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()), + _ => None }) .collect(); diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index d858ba7acf786..479fbe2673b97 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -215,7 +215,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { data @ DefPathData::ValueNs(..) | data @ DefPathData::Module(..) | data @ DefPathData::TypeParam(..) | - data @ DefPathData::LifetimeDef(..) | + data @ DefPathData::LifetimeParam(..) | data @ DefPathData::EnumVariant(..) | data @ DefPathData::Field(..) | data @ DefPathData::AnonConst | diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 883882dfe6837..3252a2cd6ab0f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -287,7 +287,7 @@ impl PrintContext { DefPathData::MacroDef(_) | DefPathData::ClosureExpr | DefPathData::TypeParam(_) | - DefPathData::LifetimeDef(_) | + DefPathData::LifetimeParam(_) | DefPathData::Field(_) | DefPathData::StructCtor | DefPathData::AnonConst | @@ -336,12 +336,10 @@ impl PrintContext { if !verbose { let mut type_params = - generics.params.iter().rev().filter_map(|param| { - match param.kind { - GenericParamDefKind::Type { has_default, .. } => { - Some((param.def_id, has_default)) - } - GenericParamDefKind::Lifetime => None, + generics.params.iter().rev().filter_map(|param| match param.kind { + GenericParamDefKind::Lifetime => None, + GenericParamDefKind::Type { has_default, .. } => { + Some((param.def_id, has_default)) } }).peekable(); let has_default = { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index f1ad14237eec2..67720e61e91af 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -677,14 +677,20 @@ impl<'a> ReplaceBodyWithLoop<'a> { ast::TyKind::Paren(ref subty) => involves_impl_trait(subty), ast::TyKind::Tup(ref tys) => any_involves_impl_trait(tys.iter()), ast::TyKind::Path(_, ref path) => path.segments.iter().any(|seg| { - match seg.parameters.as_ref().map(|p| &**p) { + match seg.args.as_ref().map(|generic_arg| &**generic_arg) { None => false, - Some(&ast::PathParameters::AngleBracketed(ref data)) => - any_involves_impl_trait(data.types.iter()) || - any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty)), - Some(&ast::PathParameters::Parenthesized(ref data)) => + Some(&ast::GenericArgs::AngleBracketed(ref data)) => { + let types = data.args.iter().filter_map(|arg| match arg { + ast::GenericArg::Type(ty) => Some(ty), + _ => None, + }); + any_involves_impl_trait(types.into_iter()) || + any_involves_impl_trait(data.bindings.iter().map(|b| &b.ty)) + }, + Some(&ast::GenericArgs::Parenthesized(ref data)) => { any_involves_impl_trait(data.inputs.iter()) || - any_involves_impl_trait(data.output.iter()), + any_involves_impl_trait(data.output.iter()) + } } }), _ => false, diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index dbf756f80ca38..8f8fe04fd8e01 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -18,7 +18,7 @@ use syntax::ast; use syntax::attr; use syntax_pos::Span; -use rustc::hir::{self, PatKind}; +use rustc::hir::{self, GenericParamKind, PatKind}; use rustc::hir::intravisit::FnKind; #[derive(PartialEq)] @@ -147,9 +147,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCamelCaseTypes { } fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) { - if let hir::GenericParam::Type(ref gen) = *param { - if gen.synthetic.is_none() { - self.check_case(cx, "type parameter", gen.name, gen.span); + match param.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { synthetic, .. } => { + if synthetic.is_none() { + self.check_case(cx, "type parameter", param.name.name(), param.span); + } } } } @@ -253,13 +256,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) { - if let hir::GenericParam::Lifetime(ref ld) = *param { - self.check_snake_case( - cx, - "lifetime", - &ld.lifetime.name.name().as_str(), - Some(ld.lifetime.span) - ); + match param.kind { + GenericParamKind::Lifetime { .. } => { + let name = param.name.name().as_str(); + self.check_snake_case(cx, "lifetime", &name, Some(param.span)); + } + GenericParamKind::Type { .. } => {} } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 79796d788719a..941fabe26a6ed 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -49,7 +49,7 @@ use syntax_pos::{BytePos, Span, SyntaxContext}; use syntax::symbol::keywords; use syntax::errors::{Applicability, DiagnosticBuilder}; -use rustc::hir::{self, PatKind}; +use rustc::hir::{self, GenericParamKind, PatKind}; use rustc::hir::intravisit::FnKind; use bad_style::{MethodLateContext, method_context}; @@ -1196,15 +1196,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems { } err.emit(); } - if generics.is_type_parameterized() { - let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, - it.span, - "functions generic over \ - types must be mangled"); - err.span_suggestion_short(no_mangle_attr.span, - "remove this attribute", - "".to_owned()); - err.emit(); + for param in &generics.params { + match param.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { .. } => { + let mut err = cx.struct_span_lint(NO_MANGLE_GENERIC_ITEMS, + it.span, + "functions generic over \ + types must be mangled"); + err.span_suggestion_short(no_mangle_attr.span, + "remove this attribute", + "".to_owned()); + err.emit(); + break; + } + } } } } @@ -1531,10 +1537,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds { } // The parameters must not have bounds for param in type_alias_generics.params.iter() { - let spans : Vec<_> = match param { - &hir::GenericParam::Lifetime(ref l) => l.bounds.iter().map(|b| b.span).collect(), - &hir::GenericParam::Type(ref ty) => ty.bounds.iter().map(|b| b.span()).collect(), - }; + let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); if !spans.is_empty() { let mut err = cx.struct_span_lint( TYPE_ALIAS_BOUNDS, diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 2abe361233fd0..50492ae073720 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -810,52 +810,63 @@ impl LintPass for VariantSizeDifferences { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { fn check_item(&mut self, cx: &LateContext, it: &hir::Item) { - if let hir::ItemEnum(ref enum_definition, ref gens) = it.node { - if gens.params.iter().all(|param| param.is_lifetime_param()) { - // sizes only make sense for non-generic types - let item_def_id = cx.tcx.hir.local_def_id(it.id); - let t = cx.tcx.type_of(item_def_id); - let ty = cx.tcx.erase_regions(&t); - let layout = cx.layout_of(ty).unwrap_or_else(|e| { - bug!("failed to get layout for `{}`: {}", t, e) - }); - - if let layout::Variants::Tagged { ref variants, ref tag, .. } = layout.variants { - let discr_size = tag.value.size(cx.tcx).bytes(); - - debug!("enum `{}` is {} bytes large with layout:\n{:#?}", - t, layout.size.bytes(), layout); - - let (largest, slargest, largest_index) = enum_definition.variants - .iter() - .zip(variants) - .map(|(variant, variant_layout)| { - // Subtract the size of the enum discriminant - let bytes = variant_layout.size.bytes() - .saturating_sub(discr_size); - - debug!("- variant `{}` is {} bytes large", variant.node.name, bytes); - bytes - }) - .enumerate() - .fold((0, 0, 0), |(l, s, li), (idx, size)| if size > l { - (size, l, idx) - } else if size > s { - (l, size, li) - } else { - (l, s, li) - }); - - // we only warn if the largest variant is at least thrice as large as - // the second-largest. - if largest > slargest * 3 && slargest > 0 { - cx.span_lint(VARIANT_SIZE_DIFFERENCES, - enum_definition.variants[largest_index].span, - &format!("enum variant is more than three times larger \ - ({} bytes) than the next largest", - largest)); + if let hir::ItemEnum(ref enum_definition, _) = it.node { + let item_def_id = cx.tcx.hir.local_def_id(it.id); + let generics = cx.tcx.generics_of(item_def_id); + for param in &generics.params { + match param.kind { + ty::GenericParamDefKind::Lifetime { .. } => {}, + ty::GenericParamDefKind::Type { .. } => return, + } + } + // Sizes only make sense for non-generic types. + let t = cx.tcx.type_of(item_def_id); + let ty = cx.tcx.erase_regions(&t); + match cx.layout_of(ty) { + Ok(layout) => { + let variants = &layout.variants; + if let layout::Variants::Tagged { ref variants, ref tag, .. } = variants { + let discr_size = tag.value.size(cx.tcx).bytes(); + + debug!("enum `{}` is {} bytes large with layout:\n{:#?}", + t, layout.size.bytes(), layout); + + let (largest, slargest, largest_index) = enum_definition.variants + .iter() + .zip(variants) + .map(|(variant, variant_layout)| { + // Subtract the size of the enum discriminant. + let bytes = variant_layout.size.bytes().saturating_sub(discr_size); + + debug!("- variant `{}` is {} bytes large", + variant.node.name, + bytes); + bytes + }) + .enumerate() + .fold((0, 0, 0), |(l, s, li), (idx, size)| if size > l { + (size, l, idx) + } else if size > s { + (l, size, li) + } else { + (l, s, li) + }); + + // We only warn if the largest variant is at least thrice as large as + // the second-largest. + if largest > slargest * 3 && slargest > 0 { + cx.span_lint(VARIANT_SIZE_DIFFERENCES, + enum_definition.variants[largest_index].span, + &format!("enum variant is more than three times \ + larger ({} bytes) than the next largest", + largest)); + } } } + Err(ty::layout::LayoutError::Unknown(_)) => return, + Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => { + bug!("failed to get layout for `{}`: {}", t, err); + } } } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 33d4df1c3a5dc..cbe9615c69397 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1235,10 +1235,14 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { self.encode_optimized_mir(def_id) } hir::ItemConst(..) => self.encode_optimized_mir(def_id), - hir::ItemFn(_, _, constness, _, ref generics, _) => { - let has_tps = generics.ty_params().next().is_some(); + hir::ItemFn(_, _, constness, ..) => { + let generics = tcx.generics_of(def_id); + let has_types = generics.params.iter().any(|param| match param.kind { + ty::GenericParamDefKind::Type { .. } => true, + _ => false, + }); let needs_inline = - (has_tps || tcx.codegen_fn_attrs(def_id).requests_inline()) && + (has_types || tcx.codegen_fn_attrs(def_id).requests_inline()) && !self.metadata_output_only(); let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; if needs_inline || constness == hir::Constness::Const || always_encode_mir { @@ -1645,11 +1649,15 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { } fn encode_info_for_generics(&mut self, generics: &hir::Generics) { - for ty_param in generics.ty_params() { - let def_id = self.tcx.hir.local_def_id(ty_param.id); - let has_default = Untracked(ty_param.default.is_some()); - self.record(def_id, IsolatedEncoder::encode_info_for_ty_param, (def_id, has_default)); - } + generics.params.iter().for_each(|param| match param.kind { + hir::GenericParamKind::Lifetime { .. } => {} + hir::GenericParamKind::Type { ref default, .. } => { + let def_id = self.tcx.hir.local_def_id(param.id); + let has_default = Untracked(default.is_some()); + let encode_info = IsolatedEncoder::encode_info_for_ty_param; + self.record(def_id, encode_info, (def_id, has_default)); + } + }); } fn encode_info_for_ty(&mut self, ty: &hir::Ty) { diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 7cef8a75aa6ba..2c58bd8e79b08 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -295,7 +295,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { ); let label_msg = match pat.node { PatKind::Path(hir::QPath::Resolved(None, ref path)) - if path.segments.len() == 1 && path.segments[0].parameters.is_none() => { + if path.segments.len() == 1 && path.segments[0].args.is_none() => { format!("interpreted as a {} pattern, not new variable", path.def.kind_name()) } _ => format!("pattern `{}` not covered", pattern_string), diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 96aeb969d89f9..ef69cb574e07e 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1099,14 +1099,12 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &'tcx hir::Item, output: &mut Vec>) { match item.node { - hir::ItemImpl(_, - _, - _, - ref generics, - .., - ref impl_item_refs) => { - if generics.is_type_parameterized() { - return + hir::ItemImpl(_, _, _, ref generics, .., ref impl_item_refs) => { + for param in &generics.params { + match param.kind { + hir::GenericParamKind::Lifetime { .. } => {} + hir::GenericParamKind::Type { .. } => return, + } } let impl_def_id = tcx.hir.local_def_id(item.id); diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 39e0a5392580b..fc54d323b0f96 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -99,9 +99,9 @@ impl<'a> AstValidator<'a> { } } - fn no_questions_in_bounds(&self, bounds: &TyParamBounds, where_: &str, is_trait: bool) { + fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: bool) { for bound in bounds { - if let TraitTyParamBound(ref poly, TraitBoundModifier::Maybe) = *bound { + if let GenericBound::Trait(ref poly, TraitBoundModifier::Maybe) = *bound { let mut err = self.err_handler().struct_span_err(poly.span, &format!("`?Trait` is not permitted in {}", where_)); if is_trait { @@ -139,29 +139,22 @@ impl<'a> AstValidator<'a> { } fn check_late_bound_lifetime_defs(&self, params: &Vec) { - // Check: Only lifetime parameters - let non_lifetime_param_spans : Vec<_> = params.iter() - .filter_map(|param| match *param { - GenericParam::Lifetime(_) => None, - GenericParam::Type(ref t) => Some(t.ident.span), - }).collect(); - if !non_lifetime_param_spans.is_empty() { - self.err_handler().span_err(non_lifetime_param_spans, - "only lifetime parameters can be used in this context"); - } - - // Check: No bounds on lifetime parameters - for param in params.iter() { - match *param { - GenericParam::Lifetime(ref l) => { - if !l.bounds.is_empty() { - let spans: Vec<_> = l.bounds.iter().map(|b| b.ident.span).collect(); - self.err_handler().span_err(spans, - "lifetime bounds cannot be used in this context"); + // Check only lifetime parameters are present and that the lifetime + // parameters that are present have no bounds. + let non_lt_param_spans: Vec<_> = params.iter().filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + if !param.bounds.is_empty() { + let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); + self.err_handler() + .span_err(spans, "lifetime bounds cannot be used in this context"); } + None } - GenericParam::Type(_) => {} - } + _ => Some(param.ident.span), + }).collect(); + if !non_lt_param_spans.is_empty() { + self.err_handler().span_err(non_lt_param_spans, + "only lifetime parameters can be used in this context"); } } } @@ -197,7 +190,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { TyKind::TraitObject(ref bounds, ..) => { let mut any_lifetime_bounds = false; for bound in bounds { - if let RegionTyParamBound(ref lifetime) = *bound { + if let GenericBound::Outlives(ref lifetime) = *bound { if any_lifetime_bounds { span_err!(self.session, lifetime.ident.span, E0226, "only a single explicit lifetime bound is permitted"); @@ -210,7 +203,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } TyKind::ImplTrait(ref bounds) => { if !bounds.iter() - .any(|b| if let TraitTyParamBound(..) = *b { true } else { false }) { + .any(|b| if let GenericBound::Trait(..) = *b { true } else { false }) { self.err_handler().span_err(ty.span, "at least one trait must be specified"); } } @@ -230,9 +223,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // } // foo!(bar::baz); use_tree.prefix.segments.iter().find(|segment| { - segment.parameters.is_some() + segment.args.is_some() }).map(|segment| { - self.err_handler().span_err(segment.parameters.as_ref().unwrap().span(), + self.err_handler().span_err(segment.args.as_ref().unwrap().span(), "generic arguments in import path"); }); @@ -300,7 +293,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ItemKind::Trait(is_auto, _, ref generics, ref bounds, ref trait_items) => { if is_auto == IsAuto::Yes { // Auto traits cannot have generics, super traits nor contain items. - if generics.is_parameterized() { + if !generics.params.is_empty() { struct_span_err!(self.session, item.span, E0567, "auto traits cannot have generic parameters").emit(); } @@ -335,22 +328,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::TraitAlias(Generics { ref params, .. }, ..) => { for param in params { - if let GenericParam::Type(TyParam { - ident, - ref bounds, - ref default, - .. - }) = *param - { - if !bounds.is_empty() { - self.err_handler().span_err(ident.span, - "type parameters on the left side of a \ - trait alias cannot be bounded"); - } - if !default.is_none() { - self.err_handler().span_err(ident.span, - "type parameters on the left side of a \ - trait alias cannot have defaults"); + match param.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { ref default, .. } => { + if !param.bounds.is_empty() { + self.err_handler() + .span_err(param.ident.span, "type parameters on the left \ + side of a trait alias cannot be bounded"); + } + if !default.is_none() { + self.err_handler() + .span_err(param.ident.span, "type parameters on the left \ + side of a trait alias cannot have defaults"); + } } } } @@ -398,8 +388,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_vis(&mut self, vis: &'a Visibility) { match vis.node { VisibilityKind::Restricted { ref path, .. } => { - path.segments.iter().find(|segment| segment.parameters.is_some()).map(|segment| { - self.err_handler().span_err(segment.parameters.as_ref().unwrap().span(), + path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| { + self.err_handler().span_err(segment.args.as_ref().unwrap().span(), "generic arguments in visibility path"); }); } @@ -409,41 +399,40 @@ impl<'a> Visitor<'a> for AstValidator<'a> { visit::walk_vis(self, vis) } - fn visit_generics(&mut self, g: &'a Generics) { + fn visit_generics(&mut self, generics: &'a Generics) { let mut seen_non_lifetime_param = false; let mut seen_default = None; - for param in &g.params { - match (param, seen_non_lifetime_param) { - (&GenericParam::Lifetime(ref ld), true) => { + for param in &generics.params { + match (¶m.kind, seen_non_lifetime_param) { + (GenericParamKind::Lifetime { .. }, true) => { self.err_handler() - .span_err(ld.lifetime.ident.span, "lifetime parameters must be leading"); + .span_err(param.ident.span, "lifetime parameters must be leading"); }, - (&GenericParam::Lifetime(_), false) => {} - _ => { + (GenericParamKind::Lifetime { .. }, false) => {} + (GenericParamKind::Type { ref default, .. }, _) => { seen_non_lifetime_param = true; + if default.is_some() { + seen_default = Some(param.ident.span); + } else if let Some(span) = seen_default { + self.err_handler() + .span_err(span, "type parameters with a default must be trailing"); + break; + } } } - - if let GenericParam::Type(ref ty_param @ TyParam { default: Some(_), .. }) = *param { - seen_default = Some(ty_param.ident.span); - } else if let Some(span) = seen_default { - self.err_handler() - .span_err(span, "type parameters with a default must be trailing"); - break - } } - for predicate in &g.where_clause.predicates { + for predicate in &generics.where_clause.predicates { if let WherePredicate::EqPredicate(ref predicate) = *predicate { self.err_handler().span_err(predicate.span, "equality constraints are not yet \ supported in where clauses (#20041)"); } } - visit::walk_generics(self, g) + visit::walk_generics(self, generics) } fn visit_generic_param(&mut self, param: &'a GenericParam) { - if let GenericParam::Lifetime(ref ld) = *param { - self.check_lifetime(ld.lifetime.ident); + if let GenericParamKind::Lifetime { .. } = param.kind { + self.check_lifetime(param.ident); } visit::walk_generic_param(self, param); } @@ -521,23 +510,24 @@ impl<'a> Visitor<'a> for NestedImplTraitVisitor<'a> { visit::walk_ty(self, t); } } - fn visit_path_parameters(&mut self, _: Span, path_parameters: &'a PathParameters) { - match *path_parameters { - PathParameters::AngleBracketed(ref params) => { - for type_ in ¶ms.types { - self.visit_ty(type_); - } - for type_binding in ¶ms.bindings { + fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) { + match *generic_args { + GenericArgs::AngleBracketed(ref data) => { + data.args.iter().for_each(|arg| match arg { + GenericArg::Type(ty) => self.visit_ty(ty), + _ => {} + }); + for type_binding in &data.bindings { // Type bindings such as `Item=impl Debug` in `Iterator` // are allowed to contain nested `impl Trait`. self.with_impl_trait(None, |this| visit::walk_ty(this, &type_binding.ty)); } } - PathParameters::Parenthesized(ref params) => { - for type_ in ¶ms.inputs { + GenericArgs::Parenthesized(ref data) => { + for type_ in &data.inputs { self.visit_ty(type_); } - if let Some(ref type_) = params.output { + if let Some(ref type_) = data.output { // `-> Foo` syntax is essentially an associated type binding, // so it is also allowed to contain nested `impl Trait`. self.with_impl_trait(None, |this| visit::walk_ty(this, type_)); @@ -590,7 +580,7 @@ impl<'a> Visitor<'a> for ImplTraitProjectionVisitor<'a> { // // To implement this, we disallow `impl Trait` from `qself` // (for cases like `::Foo>`) - // but we allow `impl Trait` in `PathParameters` + // but we allow `impl Trait` in `GenericArgs` // iff there are no more PathSegments. if let Some(ref qself) = *qself { // `impl Trait` in `qself` is always illegal diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index ba0be974b2771..e7b2869dfe61e 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -203,9 +203,9 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_impl_item(self, ii) } - fn visit_ty_param_bound(&mut self, bounds: &'v hir::TyParamBound) { - self.record("TyParamBound", Id::None, bounds); - hir_visit::walk_ty_param_bound(self, bounds) + fn visit_param_bound(&mut self, bounds: &'v hir::GenericBound) { + self.record("GenericBound", Id::None, bounds); + hir_visit::walk_param_bound(self, bounds) } fn visit_struct_field(&mut self, s: &'v hir::StructField) { @@ -322,9 +322,9 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_impl_item(self, ii) } - fn visit_ty_param_bound(&mut self, bounds: &'v ast::TyParamBound) { - self.record("TyParamBound", Id::None, bounds); - ast_visit::walk_ty_param_bound(self, bounds) + fn visit_param_bound(&mut self, bounds: &'v ast::GenericBound) { + self.record("GenericBound", Id::None, bounds); + ast_visit::walk_param_bound(self, bounds) } fn visit_struct_field(&mut self, s: &'v ast::StructField) { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 291092015b57f..de087049267b1 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -22,7 +22,7 @@ extern crate rustc_typeck; extern crate syntax_pos; extern crate rustc_data_structures; -use rustc::hir::{self, PatKind}; +use rustc::hir::{self, GenericParamKind, PatKind}; use rustc::hir::def::Def; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId}; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; @@ -1037,9 +1037,8 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { self.access_levels.is_public(trait_id) } - fn check_ty_param_bound(&mut self, - ty_param_bound: &hir::TyParamBound) { - if let hir::TraitTyParamBound(ref trait_ref, _) = *ty_param_bound { + fn check_generic_bound(&mut self, bound: &hir::GenericBound) { + if let hir::GenericBound::Trait(ref trait_ref, _) = *bound { if self.path_is_private_type(&trait_ref.trait_ref.path) { self.old_error_set.insert(trait_ref.trait_ref.ref_id); } @@ -1101,7 +1100,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } for bound in bounds.iter() { - self.check_ty_param_bound(bound) + self.check_generic_bound(bound) } } @@ -1268,16 +1267,19 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { - for ty_param in generics.ty_params() { - for bound in ty_param.bounds.iter() { - self.check_ty_param_bound(bound) + generics.params.iter().for_each(|param| match param.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { .. } => { + for bound in ¶m.bounds { + self.check_generic_bound(bound); + } } - } + }); for predicate in &generics.where_clause.predicates { match predicate { &hir::WherePredicate::BoundPredicate(ref bound_pred) => { for bound in bound_pred.bounds.iter() { - self.check_ty_param_bound(bound) + self.check_generic_bound(bound) } } &hir::WherePredicate::RegionPredicate(_) => {} diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index a2b2096ccaa47..e311701ac0589 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -56,7 +56,7 @@ use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit::{self, FnKind, Visitor}; use syntax::attr; use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind}; -use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParam, Generics}; +use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamKind, Generics}; use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path}; use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind}; @@ -797,31 +797,41 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { // put all the parameters on the ban list and then remove // them one by one as they are processed and become available. let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind); + let mut found_default = false; default_ban_rib.bindings.extend(generics.params.iter() - .filter_map(|p| if let GenericParam::Type(ref tp) = *p { Some(tp) } else { None }) - .skip_while(|p| p.default.is_none()) - .map(|p| (Ident::with_empty_ctxt(p.ident.name), Def::Err))); + .filter_map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => None, + GenericParamKind::Type { ref default, .. } => { + if found_default || default.is_some() { + found_default = true; + return Some((Ident::with_empty_ctxt(param.ident.name), Def::Err)); + } + None + } + })); for param in &generics.params { - match *param { - GenericParam::Lifetime(_) => self.visit_generic_param(param), - GenericParam::Type(ref ty_param) => { - for bound in &ty_param.bounds { - self.visit_ty_param_bound(bound); + match param.kind { + GenericParamKind::Lifetime { .. } => self.visit_generic_param(param), + GenericParamKind::Type { ref default, .. } => { + for bound in ¶m.bounds { + self.visit_param_bound(bound); } - if let Some(ref ty) = ty_param.default { + if let Some(ref ty) = default { self.ribs[TypeNS].push(default_ban_rib); self.visit_ty(ty); default_ban_rib = self.ribs[TypeNS].pop().unwrap(); } // Allow all following defaults to refer to this type parameter. - default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(ty_param.ident.name)); + default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name)); } } } - for p in &generics.where_clause.predicates { self.visit_where_predicate(p); } + for p in &generics.where_clause.predicates { + self.visit_where_predicate(p); + } } } @@ -2066,7 +2076,7 @@ impl<'a> Resolver<'a> { let local_def_id = this.definitions.local_def_id(item.id); this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| { this.visit_generics(generics); - walk_list!(this, visit_ty_param_bound, bounds); + walk_list!(this, visit_param_bound, bounds); for trait_item in trait_items { this.check_proc_macro_attrs(&trait_item.attrs); @@ -2109,7 +2119,7 @@ impl<'a> Resolver<'a> { let local_def_id = this.definitions.local_def_id(item.id); this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| { this.visit_generics(generics); - walk_list!(this, visit_ty_param_bound, bounds); + walk_list!(this, visit_param_bound, bounds); }); }); } @@ -2197,10 +2207,11 @@ impl<'a> Resolver<'a> { HasTypeParameters(generics, rib_kind) => { let mut function_type_rib = Rib::new(rib_kind); let mut seen_bindings = FxHashMap(); - for param in &generics.params { - if let GenericParam::Type(ref type_parameter) = *param { - let ident = type_parameter.ident.modern(); - debug!("with_type_parameter_rib: {}", type_parameter.id); + generics.params.iter().for_each(|param| match param.kind { + GenericParamKind::Lifetime { .. } => {} + GenericParamKind::Type { .. } => { + let ident = param.ident.modern(); + debug!("with_type_parameter_rib: {}", param.id); if seen_bindings.contains_key(&ident) { let span = seen_bindings.get(&ident).unwrap(); @@ -2208,17 +2219,16 @@ impl<'a> Resolver<'a> { ident.name, span, ); - resolve_error(self, type_parameter.ident.span, err); + resolve_error(self, param.ident.span, err); } - seen_bindings.entry(ident).or_insert(type_parameter.ident.span); + seen_bindings.entry(ident).or_insert(param.ident.span); - // plain insert (no renaming) - let def_id = self.definitions.local_def_id(type_parameter.id); - let def = Def::TyParam(def_id); + // Plain insert (no renaming). + let def = Def::TyParam(self.definitions.local_def_id(param.id)); function_type_rib.bindings.insert(ident, def); - self.record_def(type_parameter.id, PathResolution::new(def)); + self.record_def(param.id, PathResolution::new(def)); } - } + }); self.ribs[TypeNS].push(function_type_rib); } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index de7a3dc5ceeb2..649e8858b0971 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -437,8 +437,8 @@ impl<'a> Resolver<'a> { let def = self.resolve_macro_to_def_inner(scope, path, kind, force); if def != Err(Determinacy::Undetermined) { // Do not report duplicated errors on every undetermined resolution. - path.segments.iter().find(|segment| segment.parameters.is_some()).map(|segment| { - self.session.span_err(segment.parameters.as_ref().unwrap().span(), + path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| { + self.session.span_err(segment.args.as_ref().unwrap().span(), "generic arguments in macro path"); }); } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 279ee403cc625..7da5b1668b3d8 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -370,35 +370,38 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { id: NodeId, ) { for param in &generics.params { - if let ast::GenericParam::Type(ref ty_param) = *param { - let param_ss = ty_param.ident.span; - let name = escape(self.span.snippet(param_ss)); - // Append $id to name to make sure each one is unique - let qualname = format!("{}::{}${}", prefix, name, id); - if !self.span.filter_generated(Some(param_ss), full_span) { - let id = ::id_from_node_id(ty_param.id, &self.save_ctxt); - let span = self.span_from_span(param_ss); + match param.kind { + ast::GenericParamKind::Lifetime { .. } => {} + ast::GenericParamKind::Type { .. } => { + let param_ss = param.ident.span; + let name = escape(self.span.snippet(param_ss)); + // Append $id to name to make sure each one is unique. + let qualname = format!("{}::{}${}", prefix, name, id); + if !self.span.filter_generated(Some(param_ss), full_span) { + let id = ::id_from_node_id(param.id, &self.save_ctxt); + let span = self.span_from_span(param_ss); - self.dumper.dump_def( - &Access { - public: false, - reachable: false, - }, - Def { - kind: DefKind::Type, - id, - span, - name, - qualname, - value: String::new(), - parent: None, - children: vec![], - decl_id: None, - docs: String::new(), - sig: None, - attributes: vec![], - }, - ); + self.dumper.dump_def( + &Access { + public: false, + reachable: false, + }, + Def { + kind: DefKind::Type, + id, + span, + name, + qualname, + value: String::new(), + parent: None, + children: vec![], + decl_id: None, + docs: String::new(), + sig: None, + attributes: vec![], + }, + ); + } } } } @@ -715,7 +718,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { &mut self, item: &'l ast::Item, generics: &'l ast::Generics, - trait_refs: &'l ast::TyParamBounds, + trait_refs: &'l ast::GenericBounds, methods: &'l [ast::TraitItem], ) { let name = item.ident.to_string(); @@ -758,10 +761,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { // super-traits for super_bound in trait_refs.iter() { let trait_ref = match *super_bound { - ast::TraitTyParamBound(ref trait_ref, _) => trait_ref, - ast::RegionTyParamBound(..) => { - continue; - } + ast::GenericBound::Trait(ref trait_ref, _) => trait_ref, + ast::GenericBound::Outlives(..) => continue, }; let trait_ref = &trait_ref.trait_ref; @@ -818,14 +819,17 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } self.dump_path_ref(id, path); - // Type parameters + // Type arguments for seg in &path.segments { - if let Some(ref params) = seg.parameters { - match **params { - ast::PathParameters::AngleBracketed(ref data) => for t in &data.types { - self.visit_ty(t); - }, - ast::PathParameters::Parenthesized(ref data) => { + if let Some(ref generic_args) = seg.args { + match **generic_args { + ast::GenericArgs::AngleBracketed(ref data) => { + data.args.iter().for_each(|arg| match arg { + ast::GenericArg::Type(ty) => self.visit_ty(ty), + _ => {} + }); + } + ast::GenericArgs::Parenthesized(ref data) => { for t in &data.inputs { self.visit_ty(t); } @@ -905,11 +909,12 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { } // Explicit types in the turbo-fish. - if let Some(ref params) = seg.parameters { - if let ast::PathParameters::AngleBracketed(ref data) = **params { - for t in &data.types { - self.visit_ty(t); - } + if let Some(ref generic_args) = seg.args { + if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args { + data.args.iter().for_each(|arg| match arg { + ast::GenericArg::Type(ty) => self.visit_ty(ty), + _ => {} + }); } } @@ -1478,18 +1483,19 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc } fn visit_generics(&mut self, generics: &'l ast::Generics) { - for param in &generics.params { - if let ast::GenericParam::Type(ref ty_param) = *param { - for bound in ty_param.bounds.iter() { - if let ast::TraitTyParamBound(ref trait_ref, _) = *bound { + generics.params.iter().for_each(|param| match param.kind { + ast::GenericParamKind::Lifetime { .. } => {} + ast::GenericParamKind::Type { ref default, .. } => { + for bound in ¶m.bounds { + if let ast::GenericBound::Trait(ref trait_ref, _) = *bound { self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path) } } - if let Some(ref ty) = ty_param.default { + if let Some(ref ty) = default { self.visit_ty(&ty); } } - } + }); } fn visit_ty(&mut self, t: &'l ast::Ty) { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index f9510970e43d4..453500d5ab7bd 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -692,8 +692,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { if path.segments.len() != 1 { return false; } - if let Some(ref params) = path.segments[0].parameters { - if let ast::PathParameters::Parenthesized(_) = **params { + if let Some(ref generic_args) = path.segments[0].args { + if let ast::GenericArgs::Parenthesized(_) = **generic_args { return true; } } @@ -934,10 +934,7 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String { sig.push_str(&generics .params .iter() - .map(|param| match *param { - ast::GenericParam::Lifetime(ref l) => l.lifetime.ident.name.to_string(), - ast::GenericParam::Type(ref t) => t.ident.to_string(), - }) + .map(|param| param.ident.to_string()) .collect::>() .join(", ")); sig.push_str("> "); diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index e3545e8f1a9b8..7f2f0b0c83716 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -104,7 +104,7 @@ pub fn assoc_const_signature( pub fn assoc_type_signature( id: NodeId, ident: ast::Ident, - bounds: Option<&ast::TyParamBounds>, + bounds: Option<&ast::GenericBounds>, default: Option<&ast::Ty>, scx: &SaveContext, ) -> Option { @@ -223,9 +223,9 @@ impl Sig for ast::Ty { text.push_str("for<"); text.push_str(&f.generic_params .iter() - .filter_map(|p| match *p { - ast::GenericParam::Lifetime(ref l) => { - Some(l.lifetime.ident.to_string()) + .filter_map(|param| match param.kind { + ast::GenericParamKind::Lifetime { .. } => { + Some(param.ident.to_string()) } _ => None, }) @@ -617,45 +617,34 @@ impl Sig for ast::Generics { let mut defs = vec![]; for param in &self.params { - match *param { - ast::GenericParam::Lifetime(ref l) => { - let mut l_text = l.lifetime.ident.to_string(); - defs.push(SigElement { - id: id_from_node_id(l.lifetime.id, scx), - start: offset + text.len(), - end: offset + text.len() + l_text.len(), - }); - - if !l.bounds.is_empty() { - l_text.push_str(": "); - let bounds = l.bounds - .iter() - .map(|l| l.ident.to_string()) + let mut param_text = param.ident.to_string(); + defs.push(SigElement { + id: id_from_node_id(param.id, scx), + start: offset + text.len(), + end: offset + text.len() + param_text.len(), + }); + if !param.bounds.is_empty() { + param_text.push_str(": "); + match param.kind { + ast::GenericParamKind::Lifetime { .. } => { + let bounds = param.bounds.iter() + .map(|bound| match bound { + ast::GenericBound::Outlives(lt) => lt.ident.to_string(), + _ => panic!(), + }) .collect::>() .join(" + "); - l_text.push_str(&bounds); + param_text.push_str(&bounds); // FIXME add lifetime bounds refs. } - text.push_str(&l_text); - text.push(','); - } - ast::GenericParam::Type(ref t) => { - let mut t_text = t.ident.to_string(); - defs.push(SigElement { - id: id_from_node_id(t.id, scx), - start: offset + text.len(), - end: offset + text.len() + t_text.len(), - }); - - if !t.bounds.is_empty() { - t_text.push_str(": "); - t_text.push_str(&pprust::bounds_to_string(&t.bounds)); + ast::GenericParamKind::Type { .. } => { + param_text.push_str(&pprust::bounds_to_string(¶m.bounds)); // FIXME descend properly into bounds. } - text.push_str(&t_text); - text.push(','); } } + text.push_str(¶m_text); + text.push(','); } text.push('>'); @@ -852,7 +841,7 @@ fn name_and_generics( fn make_assoc_type_signature( id: NodeId, ident: ast::Ident, - bounds: Option<&ast::TyParamBounds>, + bounds: Option<&ast::GenericBounds>, default: Option<&ast::Ty>, scx: &SaveContext, ) -> Result { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 18911b47ed1d0..f3912c3042d7f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -13,7 +13,7 @@ //! is parameterized by an instance of `AstConv`. use rustc_data_structures::accumulate_vec::AccumulateVec; -use hir; +use hir::{self, GenericArg}; use hir::def::Def; use hir::def_id::DefId; use middle::resolve_lifetime as rl; @@ -177,11 +177,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { { let (substs, assoc_bindings) = - item_segment.with_parameters(|parameters| { + item_segment.with_generic_args(|generic_args| { self.create_substs_for_ast_path( span, def_id, - parameters, + generic_args, item_segment.infer_types, None) }); @@ -199,7 +199,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn create_substs_for_ast_path(&self, span: Span, def_id: DefId, - parameters: &hir::PathParameters, + generic_args: &hir::GenericArgs, infer_types: bool, self_ty: Option>) -> (&'tcx Substs<'tcx>, Vec>) @@ -207,16 +207,26 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let tcx = self.tcx(); debug!("create_substs_for_ast_path(def_id={:?}, self_ty={:?}, \ - parameters={:?})", - def_id, self_ty, parameters); + generic_args={:?})", + def_id, self_ty, generic_args); // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). - let decl_generics = tcx.generics_of(def_id); - let ty_provided = parameters.types.len(); - let lt_provided = parameters.lifetimes.len(); + // FIXME(varkor): Separating out the parameters is messy. + let lifetimes: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg { + GenericArg::Lifetime(lt) => Some(lt), + _ => None, + }).collect(); + let types: Vec<_> = generic_args.args.iter().filter_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + _ => None, + }).collect(); + let lt_provided = lifetimes.len(); + let ty_provided = types.len(); + + let decl_generics = tcx.generics_of(def_id); let mut lt_accepted = 0; let mut ty_params = ParamRange { required: 0, accepted: 0 }; for param in &decl_generics.params { @@ -269,8 +279,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { match param.kind { GenericParamDefKind::Lifetime => { let i = param.index as usize - own_self; - if let Some(lifetime) = parameters.lifetimes.get(i) { - self.ast_region_to_region(lifetime, Some(param)).into() + if let Some(lt) = lifetimes.get(i) { + self.ast_region_to_region(lt, Some(param)).into() } else { tcx.types.re_static.into() } @@ -286,7 +296,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let i = i - (lt_accepted + own_self); if i < ty_provided { // A provided type parameter. - self.ast_ty_to_ty(¶meters.types[i]).into() + self.ast_ty_to_ty(&types[i]).into() } else if infer_types { // No type parameters were provided, we can infer all. if !default_needs_object_self(param) { @@ -330,7 +340,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } }); - let assoc_bindings = parameters.bindings.iter().map(|binding| { + let assoc_bindings = generic_args.bindings.iter().map(|binding| { ConvertedBinding { item_name: binding.name, ty: self.ast_ty_to_ty(&binding.ty), @@ -355,7 +365,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { - self.prohibit_type_params(trait_ref.path.segments.split_last().unwrap().1); + self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1); let trait_def_id = self.trait_def_id(trait_ref); self.ast_path_to_mono_trait_ref(trait_ref.path.span, @@ -389,7 +399,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("ast_path_to_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id); - self.prohibit_type_params(trait_ref.path.segments.split_last().unwrap().1); + self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1); let (substs, assoc_bindings) = self.create_substs_for_ast_trait_ref(trait_ref.path.span, @@ -451,7 +461,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let trait_def = self.tcx().trait_def(trait_def_id); if !self.tcx().features().unboxed_closures && - trait_segment.with_parameters(|p| p.parenthesized) != trait_def.paren_sugar { + trait_segment.with_generic_args(|generic_args| generic_args.parenthesized) + != trait_def.paren_sugar { // For now, require that parenthetical notation be used only with `Fn()` etc. let msg = if trait_def.paren_sugar { "the precise format of `Fn`-family traits' type parameters is subject to change. \ @@ -463,10 +474,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span, GateIssue::Language, msg); } - trait_segment.with_parameters(|parameters| { + trait_segment.with_generic_args(|generic_args| { self.create_substs_for_ast_path(span, trait_def_id, - parameters, + generic_args, trait_segment.infer_types, Some(self_ty)) }) @@ -866,7 +877,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name); - self.prohibit_type_params(slice::from_ref(item_segment)); + self.prohibit_generics(slice::from_ref(item_segment)); // Find the type of the associated item, and the trait where the associated // item is declared. @@ -943,7 +954,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let tcx = self.tcx(); let trait_def_id = tcx.parent_def_id(item_def_id).unwrap(); - self.prohibit_type_params(slice::from_ref(item_segment)); + self.prohibit_generics(slice::from_ref(item_segment)); let self_ty = if let Some(ty) = opt_self_ty { ty @@ -968,25 +979,37 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.normalize_ty(span, tcx.mk_projection(item_def_id, trait_ref.substs)) } - pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) { + pub fn prohibit_generics(&self, segments: &[hir::PathSegment]) { for segment in segments { - segment.with_parameters(|parameters| { - for typ in ¶meters.types { - struct_span_err!(self.tcx().sess, typ.span, E0109, - "type parameters are not allowed on this type") - .span_label(typ.span, "type parameter not allowed") - .emit(); - break; - } - for lifetime in ¶meters.lifetimes { - struct_span_err!(self.tcx().sess, lifetime.span, E0110, - "lifetime parameters are not allowed on this type") - .span_label(lifetime.span, - "lifetime parameter not allowed on this type") - .emit(); - break; + segment.with_generic_args(|generic_args| { + let (mut err_for_lt, mut err_for_ty) = (false, false); + for arg in &generic_args.args { + let (mut span_err, span, kind) = match arg { + hir::GenericArg::Lifetime(lt) => { + if err_for_lt { continue } + err_for_lt = true; + (struct_span_err!(self.tcx().sess, lt.span, E0110, + "lifetime parameters are not allowed on \ + this type"), + lt.span, + "lifetime") + } + hir::GenericArg::Type(ty) => { + if err_for_ty { continue } + err_for_ty = true; + (struct_span_err!(self.tcx().sess, ty.span, E0109, + "type parameters are not allowed on this type"), + ty.span, + "type") + } + }; + span_err.span_label(span, format!("{} parameter not allowed", kind)) + .emit(); + if err_for_lt && err_for_ty { + break; + } } - for binding in ¶meters.bindings { + for binding in &generic_args.bindings { self.prohibit_projection(binding.span); break; } @@ -1016,21 +1039,21 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) | Def::Union(did) | Def::TyForeign(did) => { assert_eq!(opt_self_ty, None); - self.prohibit_type_params(path.segments.split_last().unwrap().1); + self.prohibit_generics(path.segments.split_last().unwrap().1); self.ast_path_to_ty(span, did, path.segments.last().unwrap()) } Def::Variant(did) if permit_variants => { // Convert "variant type" as if it were a real type. // The resulting `Ty` is type of the variant's enum for now. assert_eq!(opt_self_ty, None); - self.prohibit_type_params(path.segments.split_last().unwrap().1); + self.prohibit_generics(path.segments.split_last().unwrap().1); self.ast_path_to_ty(span, tcx.parent_def_id(did).unwrap(), path.segments.last().unwrap()) } Def::TyParam(did) => { assert_eq!(opt_self_ty, None); - self.prohibit_type_params(&path.segments); + self.prohibit_generics(&path.segments); let node_id = tcx.hir.as_local_node_id(did).unwrap(); let item_id = tcx.hir.get_parent_node(node_id); @@ -1043,18 +1066,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Self in impl (we know the concrete type). assert_eq!(opt_self_ty, None); - self.prohibit_type_params(&path.segments); + self.prohibit_generics(&path.segments); tcx.at(span).type_of(def_id) } Def::SelfTy(Some(_), None) => { // Self in trait. assert_eq!(opt_self_ty, None); - self.prohibit_type_params(&path.segments); + self.prohibit_generics(&path.segments); tcx.mk_self_type() } Def::AssociatedTy(def_id) => { - self.prohibit_type_params(&path.segments[..path.segments.len()-2]); + self.prohibit_generics(&path.segments[..path.segments.len()-2]); self.qpath_to_ty(span, opt_self_ty, def_id, @@ -1063,7 +1086,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } Def::PrimTy(prim_ty) => { assert_eq!(opt_self_ty, None); - self.prohibit_type_params(&path.segments); + self.prohibit_generics(&path.segments); match prim_ty { hir::TyBool => tcx.types.bool, hir::TyChar => tcx.types.char, diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 808c134e99448..5f8955612e10c 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::hir::{self, ImplItemKind, TraitItemKind}; +use rustc::hir::{self, GenericParamKind, ImplItemKind, TraitItemKind}; use rustc::infer::{self, InferOk}; use rustc::ty::{self, TyCtxt, GenericParamDefKind}; use rustc::ty::util::ExplicitSelf; @@ -728,11 +728,9 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut error_found = false; let impl_m_generics = tcx.generics_of(impl_m.def_id); let trait_m_generics = tcx.generics_of(trait_m.def_id); - let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| { - match param.kind { - GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)), - GenericParamDefKind::Lifetime => None, - } + let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind { + GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)), + GenericParamDefKind::Lifetime => None, }); let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| { match param.kind { @@ -843,19 +841,19 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let span = visitor.0?; - let param = impl_m.generics.params.iter().filter_map(|param| { - match param { - hir::GenericParam::Type(param) => { + let bounds = impl_m.generics.params.iter().find_map(|param| { + match param.kind { + GenericParamKind::Lifetime { .. } => None, + GenericParamKind::Type { .. } => { if param.id == impl_node_id { - Some(param) + Some(¶m.bounds) } else { None } - }, - hir::GenericParam::Lifetime(..) => None, + } } - }).next()?; - let bounds = param.bounds.first()?.span().to(param.bounds.last()?.span()); + })?; + let bounds = bounds.first()?.span().to(bounds.last()?.span()); let bounds = tcx .sess .codemap() diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index f3a3c30fe5ad9..36ce01bcd08b3 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -12,6 +12,7 @@ use super::{probe, MethodCallee}; use astconv::AstConv; use check::{FnCtxt, PlaceOp, callee, Needs}; +use hir::GenericArg; use hir::def_id::DefId; use rustc::ty::subst::Substs; use rustc::traits; @@ -59,7 +60,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "confirm(unadjusted_self_ty={:?}, pick={:?}, generic_args={:?})", unadjusted_self_ty, pick, - segment.parameters, + segment.args, ); let mut confirm_cx = ConfirmContext::new(self, span, self_expr, call_expr); @@ -316,36 +317,44 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { let method_generics = self.tcx.generics_of(pick.item.def_id); let mut fn_segment = Some((segment, method_generics)); let supress_mismatch = self.fcx.check_impl_trait(self.span, fn_segment); - self.fcx.check_path_parameter_count(self.span, &mut fn_segment, true, supress_mismatch); + self.fcx.check_generic_arg_count(self.span, &mut fn_segment, true, supress_mismatch); // Create subst for early-bound lifetime parameters, combining // parameters from the type and those from the method. assert_eq!(method_generics.parent_count, parent_substs.len()); - let provided = &segment.parameters; + let provided = &segment.args; let own_counts = method_generics.own_counts(); Substs::for_item(self.tcx, pick.item.def_id, |param, _| { - let i = param.index as usize; + let mut i = param.index as usize; if i < parent_substs.len() { parent_substs[i] } else { - match param.kind { - GenericParamDefKind::Lifetime => { - if let Some(lifetime) = provided.as_ref().and_then(|p| { - p.lifetimes.get(i - parent_substs.len()) - }) { - return AstConv::ast_region_to_region( - self.fcx, lifetime, Some(param)).into(); - } - } - GenericParamDefKind::Type {..} => { - if let Some(ast_ty) = provided.as_ref().and_then(|p| { - p.types.get(i - parent_substs.len() - own_counts.lifetimes) - }) { - return self.to_ty(ast_ty).into(); + let (is_lt, is_ty) = match param.kind { + GenericParamDefKind::Lifetime => (true, false), + GenericParamDefKind::Type { .. } => (false, true), + }; + provided.as_ref().and_then(|data| { + for arg in &data.args { + match arg { + GenericArg::Lifetime(lt) if is_lt => { + if i == parent_substs.len() { + return Some(AstConv::ast_region_to_region( + self.fcx, lt, Some(param)).into()); + } + i -= 1; + } + GenericArg::Lifetime(_) => {} + GenericArg::Type(ty) if is_ty => { + if i == parent_substs.len() + own_counts.lifetimes { + return Some(self.to_ty(ty).into()); + } + i -= 1; + } + GenericArg::Type(_) => {} } } - } - self.var_for_def(self.span, param) + None + }).unwrap_or_else(|| self.var_for_def(self.span, param)) } }) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b70b61d191594..366420cfcabb1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -85,6 +85,7 @@ use self::method::MethodCallee; use self::TupleArgumentsFlag::*; use astconv::AstConv; +use hir::GenericArg; use hir::def::Def; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use std::slice; @@ -1260,10 +1261,11 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item hir::ItemUnion(..) => { check_union(tcx, it.id, it.span); } - hir::ItemTy(_, ref generics) => { + hir::ItemTy(..) => { let def_id = tcx.hir.local_def_id(it.id); let pty_ty = tcx.type_of(def_id); - check_bounds_are_used(tcx, generics, pty_ty); + let generics = tcx.generics_of(def_id); + check_bounds_are_used(tcx, &generics, pty_ty); } hir::ItemForeignMod(ref m) => { check_abi(tcx, it.span, m.abi); @@ -4740,8 +4742,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { Def::Fn(def_id) | Def::Const(def_id) | Def::Static(def_id, _) => { - fn_segment = Some((segments.last().unwrap(), - self.tcx.generics_of(def_id))); + fn_segment = Some((segments.last().unwrap(), self.tcx.generics_of(def_id))); } // Case 3. Reference to a method or associated const. @@ -4781,7 +4782,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // errors if type parameters are provided in an inappropriate place. let poly_segments = type_segment.is_some() as usize + fn_segment.is_some() as usize; - AstConv::prohibit_type_params(self, &segments[..segments.len() - poly_segments]); + AstConv::prohibit_generics(self, &segments[..segments.len() - poly_segments]); match def { Def::Local(nid) | Def::Upvar(nid, ..) => { @@ -4800,8 +4801,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // to add defaults. If the user provided *too many* types, that's // a problem. let supress_mismatch = self.check_impl_trait(span, fn_segment); - self.check_path_parameter_count(span, &mut type_segment, false, supress_mismatch); - self.check_path_parameter_count(span, &mut fn_segment, false, supress_mismatch); + self.check_generic_arg_count(span, &mut type_segment, false, supress_mismatch); + self.check_generic_arg_count(span, &mut fn_segment, false, supress_mismatch); let (fn_start, has_self) = match (type_segment, fn_segment) { (_, Some((_, generics))) => { @@ -4812,11 +4813,42 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } (None, None) => (0, false) }; + // FIXME(varkor): Separating out the parameters is messy. + let mut lifetimes_type_seg = vec![]; + let mut types_type_seg = vec![]; + let mut infer_types_type_seg = true; + if let Some((seg, _)) = type_segment { + if let Some(ref data) = seg.args { + for arg in &data.args { + match arg { + GenericArg::Lifetime(lt) => lifetimes_type_seg.push(lt), + GenericArg::Type(ty) => types_type_seg.push(ty), + } + } + } + infer_types_type_seg = seg.infer_types; + } + + let mut lifetimes_fn_seg = vec![]; + let mut types_fn_seg = vec![]; + let mut infer_types_fn_seg = true; + if let Some((seg, _)) = fn_segment { + if let Some(ref data) = seg.args { + for arg in &data.args { + match arg { + GenericArg::Lifetime(lt) => lifetimes_fn_seg.push(lt), + GenericArg::Type(ty) => types_fn_seg.push(ty), + } + } + } + infer_types_fn_seg = seg.infer_types; + } + let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| { let mut i = param.index as usize; - let segment = if i < fn_start { - if let GenericParamDefKind::Type {..} = param.kind { + let (segment, lifetimes, types, infer_types) = if i < fn_start { + if let GenericParamDefKind::Type { .. } = param.kind { // Handle Self first, so we can adjust the index to match the AST. if has_self && i == 0 { return opt_self_ty.map(|ty| ty.into()).unwrap_or_else(|| { @@ -4825,29 +4857,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } i -= has_self as usize; - type_segment + (type_segment, &lifetimes_type_seg, &types_type_seg, infer_types_type_seg) } else { i -= fn_start; - fn_segment + (fn_segment, &lifetimes_fn_seg, &types_fn_seg, infer_types_fn_seg) }; match param.kind { GenericParamDefKind::Lifetime => { - let lifetimes = segment.map_or(&[][..], |(s, _)| { - s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..]) - }); - if let Some(lifetime) = lifetimes.get(i) { AstConv::ast_region_to_region(self, lifetime, Some(param)).into() } else { self.re_infer(span, Some(param)).unwrap().into() } } - GenericParamDefKind::Type {..} => { - let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| { - (s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types) - }); - + GenericParamDefKind::Type { .. } => { // Skip over the lifetimes in the same segment. if let Some((_, generics)) = segment { i -= generics.own_counts().lifetimes; @@ -4955,25 +4979,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } /// Report errors if the provided parameters are too few or too many. - fn check_path_parameter_count(&self, - span: Span, - segment: &mut Option<(&hir::PathSegment, &ty::Generics)>, - is_method_call: bool, - supress_mismatch_error: bool) { + fn check_generic_arg_count(&self, + span: Span, + segment: &mut Option<(&hir::PathSegment, &ty::Generics)>, + is_method_call: bool, + supress_mismatch_error: bool) { let (lifetimes, types, infer_types, bindings) = segment.map_or( - (&[][..], &[][..], true, &[][..]), - |(s, _)| s.parameters.as_ref().map_or( - (&[][..], &[][..], s.infer_types, &[][..]), - |p| (&p.lifetimes[..], &p.types[..], - s.infer_types, &p.bindings[..]))); - let infer_lifetimes = lifetimes.len() == 0; - - let count_lifetime_params = |n| { - format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" }) - }; - let count_type_params = |n| { - format!("{} type parameter{}", n, if n == 1 { "" } else { "s" }) - }; + (vec![], vec![], true, &[][..]), + |(s, _)| { + s.args.as_ref().map_or( + (vec![], vec![], s.infer_types, &[][..]), + |data| { + let (mut lifetimes, mut types) = (vec![], vec![]); + data.args.iter().for_each(|arg| match arg { + GenericArg::Lifetime(lt) => lifetimes.push(lt), + GenericArg::Type(ty) => types.push(ty), + }); + (lifetimes, types, s.infer_types, &data.bindings[..]) + } + ) + }); // Check provided parameters. let ((ty_required, ty_accepted), lt_accepted) = @@ -4987,9 +5012,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut ty_params = ParamRange { required: 0, accepted: 0 }; for param in &generics.params { match param.kind { - GenericParamDefKind::Lifetime => { - lt_accepted += 1; - } + GenericParamDefKind::Lifetime => lt_accepted += 1, GenericParamDefKind::Type { has_default, .. } => { ty_params.accepted += 1; if !has_default { @@ -5006,36 +5029,37 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ((ty_params.required, ty_params.accepted), lt_accepted) }); - if types.len() > ty_accepted { - let span = types[ty_accepted].span; - let expected_text = count_type_params(ty_accepted); - let actual_text = count_type_params(types.len()); - struct_span_err!(self.tcx.sess, span, E0087, - "too many type parameters provided: \ - expected at most {}, found {}", - expected_text, actual_text) - .span_label(span, format!("expected {}", expected_text)) - .emit(); - + let count_type_params = |n| { + format!("{} type parameter{}", n, if n == 1 { "" } else { "s" }) + }; + let expected_text = count_type_params(ty_accepted); + let actual_text = count_type_params(types.len()); + if let Some((mut err, span)) = if types.len() > ty_accepted { // To prevent derived errors to accumulate due to extra // type parameters, we force instantiate_value_path to // use inference variables instead of the provided types. *segment = None; + let span = types[ty_accepted].span; + Some((struct_span_err!(self.tcx.sess, span, E0087, + "too many type parameters provided: \ + expected at most {}, found {}", + expected_text, actual_text), span)) } else if types.len() < ty_required && !infer_types && !supress_mismatch_error { - let expected_text = count_type_params(ty_required); - let actual_text = count_type_params(types.len()); - struct_span_err!(self.tcx.sess, span, E0089, - "too few type parameters provided: \ - expected {}, found {}", - expected_text, actual_text) - .span_label(span, format!("expected {}", expected_text)) - .emit(); + Some((struct_span_err!(self.tcx.sess, span, E0089, + "too few type parameters provided: \ + expected {}, found {}", + expected_text, actual_text), span)) + } else { + None + } { + err.span_label(span, format!("expected {}", expected_text)).emit(); } if !bindings.is_empty() { AstConv::prohibit_projection(self, bindings[0].span); } + let infer_lifetimes = lifetimes.len() == 0; // Prohibit explicit lifetime arguments if late bound lifetime parameters are present. let has_late_bound_lifetime_defs = segment.map_or(None, |(_, generics)| generics.has_late_bound_regions); @@ -5059,25 +5083,26 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return; } - if lifetimes.len() > lt_accepted { + let count_lifetime_params = |n| { + format!("{} lifetime parameter{}", n, if n == 1 { "" } else { "s" }) + }; + let expected_text = count_lifetime_params(lt_accepted); + let actual_text = count_lifetime_params(lifetimes.len()); + if let Some((mut err, span)) = if lifetimes.len() > lt_accepted { let span = lifetimes[lt_accepted].span; - let expected_text = count_lifetime_params(lt_accepted); - let actual_text = count_lifetime_params(lifetimes.len()); - struct_span_err!(self.tcx.sess, span, E0088, - "too many lifetime parameters provided: \ - expected at most {}, found {}", - expected_text, actual_text) - .span_label(span, format!("expected {}", expected_text)) - .emit(); + Some((struct_span_err!(self.tcx.sess, span, E0088, + "too many lifetime parameters provided: \ + expected at most {}, found {}", + expected_text, actual_text), span)) } else if lifetimes.len() < lt_accepted && !infer_lifetimes { - let expected_text = count_lifetime_params(lt_accepted); - let actual_text = count_lifetime_params(lifetimes.len()); - struct_span_err!(self.tcx.sess, span, E0090, - "too few lifetime parameters provided: \ - expected {}, found {}", - expected_text, actual_text) - .span_label(span, format!("expected {}", expected_text)) - .emit(); + Some((struct_span_err!(self.tcx.sess, span, E0090, + "too few lifetime parameters provided: \ + expected {}, found {}", + expected_text, actual_text), span)) + } else { + None + } { + err.span_label(span, format!("expected {}", expected_text)).emit(); } } @@ -5088,13 +5113,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { -> bool { let segment = segment.map(|(path_segment, generics)| { let explicit = !path_segment.infer_types; - let impl_trait = generics.params.iter().any(|param| { - match param.kind { - ty::GenericParamDefKind::Type { - synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), .. - } => true, - _ => false, - } + let impl_trait = generics.params.iter().any(|param| match param.kind { + ty::GenericParamDefKind::Type { + synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), .. + } => true, + _ => false, }); if explicit && impl_trait { @@ -5155,34 +5178,39 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - generics: &hir::Generics, + generics: &ty::Generics, ty: Ty<'tcx>) { - debug!("check_bounds_are_used(n_tps={}, ty={:?})", - generics.ty_params().count(), ty); - - // make a vector of booleans initially false, set to true when used - if generics.ty_params().next().is_none() { return; } - let mut tps_used = vec![false; generics.ty_params().count()]; + let own_counts = generics.own_counts(); + debug!("check_bounds_are_used(n_tps={}, ty={:?})", own_counts.types, ty); - let lifetime_count = generics.lifetimes().count(); + if own_counts.types == 0 { + return; + } + // Make a vector of booleans initially false, set to true when used. + let mut types_used = vec![false; own_counts.types]; for leaf_ty in ty.walk() { - if let ty::TyParam(ty::ParamTy {idx, ..}) = leaf_ty.sty { + if let ty::TyParam(ty::ParamTy { idx, .. }) = leaf_ty.sty { debug!("Found use of ty param num {}", idx); - tps_used[idx as usize - lifetime_count] = true; + types_used[idx as usize - own_counts.lifetimes] = true; } else if let ty::TyError = leaf_ty.sty { - // If there already another error, do not emit an error for not using a type Parameter + // If there is already another error, do not emit + // an error for not using a type Parameter. assert!(tcx.sess.err_count() > 0); return; } } - for (&used, param) in tps_used.iter().zip(generics.ty_params()) { + let types = generics.params.iter().filter(|param| match param.kind { + ty::GenericParamDefKind::Type { .. } => true, + _ => false, + }); + for (&used, param) in types_used.iter().zip(types) { if !used { - struct_span_err!(tcx.sess, param.span, E0091, - "type parameter `{}` is unused", - param.name) - .span_label(param.span, "unused type parameter") + let id = tcx.hir.as_local_node_id(param.def_id).unwrap(); + let span = tcx.hir.span(id); + struct_span_err!(tcx.sess, span, E0091, "type parameter `{}` is unused", param.name) + .span_label(span, "unused type parameter") .emit(); } } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 7a2c38468e044..b61f09cbaea6d 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -602,8 +602,8 @@ fn check_method_receiver<'fcx, 'gcx, 'tcx>(fcx: &FnCtxt<'fcx, 'gcx, 'tcx>, } fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - item: &hir::Item, - ast_generics: &hir::Generics) + item: &hir::Item, + hir_generics: &hir::Generics) { let item_def_id = tcx.hir.local_def_id(item.id); let ty = tcx.type_of(item_def_id); @@ -631,11 +631,8 @@ fn check_variances_for_type_defn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, continue; } - let (span, name) = match ast_generics.params[index] { - hir::GenericParam::Lifetime(ref ld) => (ld.lifetime.span, ld.lifetime.name.name()), - hir::GenericParam::Type(ref tp) => (tp.span, tp.name), - }; - report_bivariance(tcx, span, name); + let param = &hir_generics.params[index]; + report_bivariance(tcx, param.span, param.name.name()); } } @@ -663,17 +660,12 @@ fn report_bivariance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn reject_shadowing_parameters(tcx: TyCtxt, def_id: DefId) { let generics = tcx.generics_of(def_id); let parent = tcx.generics_of(generics.parent.unwrap()); - let impl_params: FxHashMap<_, _> = - parent.params.iter() - .flat_map(|param| { - match param.kind { - GenericParamDefKind::Lifetime => None, - GenericParamDefKind::Type {..} => Some((param.name, param.def_id)), - } - }) - .collect(); - - for method_param in generics.params.iter() { + let impl_params: FxHashMap<_, _> = parent.params.iter().flat_map(|param| match param.kind { + GenericParamDefKind::Lifetime => None, + GenericParamDefKind::Type {..} => Some((param.name, param.def_id)), + }).collect(); + + for method_param in &generics.params { match method_param.kind { // Shadowing is checked in resolve_lifetime. GenericParamDefKind::Lifetime => continue, diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index 4aa876e85b69a..5a442881a6315 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -35,7 +35,9 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { Some(trait_ref) => { let trait_def = self.tcx.trait_def(trait_ref.def_id); - let unsafe_attr = impl_generics.and_then(|g| g.carries_unsafe_attr()); + let unsafe_attr = impl_generics.and_then(|generics| { + generics.params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle") + }); match (trait_def.unsafety, unsafe_attr, unsafety, polarity) { (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => { span_err!(self.tcx.sess, @@ -53,13 +55,14 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> { trait_ref); } - (Unsafety::Normal, Some(g), Unsafety::Normal, hir::ImplPolarity::Positive) => + (Unsafety::Normal, Some(attr_name), Unsafety::Normal, + hir::ImplPolarity::Positive) => { span_err!(self.tcx.sess, item.span, E0569, "requires an `unsafe impl` declaration due to `#[{}]` attribute", - g.attr_name()); + attr_name); } (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 58e804fc13f2d..7a4fbc73c2e7d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -49,6 +49,7 @@ use syntax::feature_gate; use syntax_pos::{Span, DUMMY_SP}; use rustc::hir::{self, map as hir_map, CodegenFnAttrs, CodegenFnAttrFlags, Unsafety}; +use rustc::hir::GenericParamKind; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; @@ -113,10 +114,14 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { - for param in generics.ty_params() { - if param.default.is_some() { - let def_id = self.tcx.hir.local_def_id(param.id); - self.tcx.type_of(def_id); + for param in &generics.params { + match param.kind { + hir::GenericParamKind::Lifetime { .. } => {} + hir::GenericParamKind::Type { default: Some(_), .. } => { + let def_id = self.tcx.hir.local_def_id(param.id); + self.tcx.type_of(def_id); + } + hir::GenericParamKind::Type { .. } => {} } } intravisit::walk_generics(self, generics); @@ -308,9 +313,12 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { -> Vec> { let from_ty_params = - ast_generics.ty_params() - .filter(|p| p.id == param_id) - .flat_map(|p| p.bounds.iter()) + ast_generics.params.iter() + .filter_map(|param| match param.kind { + GenericParamKind::Type { .. } if param.id == param_id => Some(¶m.bounds), + _ => None + }) + .flat_map(|bounds| bounds.iter()) .flat_map(|b| predicates_from_bound(self, ty, b)); let from_where_clauses = @@ -739,10 +747,15 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, outer_index: ty::INNERMOST, has_late_bound_regions: None, }; - for lifetime in generics.lifetimes() { - let hir_id = tcx.hir.node_to_hir_id(lifetime.lifetime.id); - if tcx.is_late_bound(hir_id) { - return Some(lifetime.lifetime.span); + for param in &generics.params { + match param.kind { + GenericParamKind::Lifetime { .. } => { + let hir_id = tcx.hir.node_to_hir_id(param.id); + if tcx.is_late_bound(hir_id) { + return Some(param.span); + } + } + _ => {}, } } visitor.visit_fn_decl(decl); @@ -883,12 +896,12 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut params: Vec<_> = opt_self.into_iter().collect(); let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics); - params.extend(early_lifetimes.enumerate().map(|(i, l)| { + params.extend(early_lifetimes.enumerate().map(|(i, param)| { ty::GenericParamDef { - name: l.lifetime.name.name().as_interned_str(), + name: param.name.name().as_interned_str(), index: own_start + i as u32, - def_id: tcx.hir.local_def_id(l.lifetime.id), - pure_wrt_drop: l.pure_wrt_drop, + def_id: tcx.hir.local_def_id(param.id), + pure_wrt_drop: param.pure_wrt_drop, kind: ty::GenericParamDefKind::Lifetime, } })); @@ -898,34 +911,40 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Now create the real type parameters. let type_start = own_start - has_self as u32 + params.len() as u32; - params.extend(ast_generics.ty_params().enumerate().map(|(i, p)| { - if p.name == keywords::SelfType.name() { - span_bug!(p.span, "`Self` should not be the name of a regular parameter"); - } - - if !allow_defaults && p.default.is_some() { - if !tcx.features().default_type_parameter_fallback { - tcx.lint_node( - lint::builtin::INVALID_TYPE_PARAM_DEFAULT, - p.id, - p.span, - &format!("defaults for type parameters are only allowed in `struct`, \ - `enum`, `type`, or `trait` definitions.")); + let mut i = 0; + params.extend(ast_generics.params.iter().filter_map(|param| match param.kind { + GenericParamKind::Type { ref default, synthetic, .. } => { + if param.name.name() == keywords::SelfType.name() { + span_bug!(param.span, "`Self` should not be the name of a regular parameter"); } - } - ty::GenericParamDef { - index: type_start + i as u32, - name: p.name.as_interned_str(), - def_id: tcx.hir.local_def_id(p.id), - pure_wrt_drop: p.pure_wrt_drop, - kind: ty::GenericParamDefKind::Type { - has_default: p.default.is_some(), - object_lifetime_default: - object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]), - synthetic: p.synthetic, - }, + if !allow_defaults && default.is_some() { + if !tcx.features().default_type_parameter_fallback { + tcx.lint_node( + lint::builtin::INVALID_TYPE_PARAM_DEFAULT, + param.id, + param.span, + &format!("defaults for type parameters are only allowed in \ + `struct`, `enum`, `type`, or `trait` definitions.")); + } + } + + let ty_param = ty::GenericParamDef { + index: type_start + i as u32, + name: param.name.name().as_interned_str(), + def_id: tcx.hir.local_def_id(param.id), + pure_wrt_drop: param.pure_wrt_drop, + kind: ty::GenericParamDefKind::Type { + has_default: default.is_some(), + object_lifetime_default: + object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]), + synthetic, + }, + }; + i += 1; + Some(ty_param) } + _ => None, })); // provide junk type parameter defs - the only place that @@ -1119,8 +1138,13 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }, - NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => { - icx.to_ty(ty) + NodeGenericParam(param) => { + match param.kind { + hir::GenericParamKind::Type { default: Some(ref ty), .. } => { + icx.to_ty(ty) + } + _ => bug!("unexpected non-type NodeGenericParam"), + } } x => { @@ -1225,7 +1249,7 @@ fn impl_polarity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Is it marked with ?Sized fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, - ast_bounds: &[hir::TyParamBound], + ast_bounds: &[hir::GenericBound], span: Span) -> bool { let tcx = astconv.tcx(); @@ -1233,7 +1257,7 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, // Try to find an unbound in bounds. let mut unbound = None; for ab in ast_bounds { - if let &hir::TraitTyParamBound(ref ptr, hir::TraitBoundModifier::Maybe) = ab { + if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab { if unbound.is_none() { unbound = Some(ptr.trait_ref.clone()); } else { @@ -1274,15 +1298,16 @@ fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, /// `resolve_lifetime::early_bound_lifetimes`. fn early_bound_lifetimes_from_generics<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - ast_generics: &'a hir::Generics) - -> impl Iterator + Captures<'tcx> + generics: &'a hir::Generics) + -> impl Iterator + Captures<'tcx> { - ast_generics - .lifetimes() - .filter(move |l| { - let hir_id = tcx.hir.node_to_hir_id(l.lifetime.id); + generics.params.iter().filter(move |param| match param.kind { + GenericParamKind::Lifetime { .. } => { + let hir_id = tcx.hir.node_to_hir_id(param.id); !tcx.is_late_bound(hir_id) - }) + } + _ => false, + }) } fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -1410,31 +1435,42 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut index = parent_count + has_own_self as u32; for param in early_bound_lifetimes_from_generics(tcx, ast_generics) { let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { - def_id: tcx.hir.local_def_id(param.lifetime.id), + def_id: tcx.hir.local_def_id(param.id), index, - name: param.lifetime.name.name().as_interned_str(), + name: param.name.name().as_interned_str(), })); index += 1; - for bound in ¶m.bounds { - let bound_region = AstConv::ast_region_to_region(&icx, bound, None); - let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound_region)); - predicates.push(outlives.to_predicate()); + match param.kind { + GenericParamKind::Lifetime { .. } => { + param.bounds.iter().for_each(|bound| match bound { + hir::GenericBound::Outlives(lt) => { + let bound = AstConv::ast_region_to_region(&icx, <, None); + let outlives = ty::Binder::bind(ty::OutlivesPredicate(region, bound)); + predicates.push(outlives.to_predicate()); + } + _ => bug!(), + }); + }, + _ => bug!(), } } // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). - for param in ast_generics.ty_params() { - let param_ty = ty::ParamTy::new(index, param.name.as_interned_str()).to_ty(tcx); - index += 1; - - let bounds = compute_bounds(&icx, - param_ty, - ¶m.bounds, - SizedByDefault::Yes, - param.span); - predicates.extend(bounds.predicates(tcx, param_ty)); + for param in &ast_generics.params { + match param.kind { + GenericParamKind::Type { .. } => { + let name = param.name.name().as_interned_str(); + let param_ty = ty::ParamTy::new(index, name).to_ty(tcx); + index += 1; + + let sized = SizedByDefault::Yes; + let bounds = compute_bounds(&icx, param_ty, ¶m.bounds, sized, param.span); + predicates.extend(bounds.predicates(tcx, param_ty)); + } + _ => {} + } } // Add in the bounds that appear in the where-clause @@ -1446,7 +1482,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for bound in bound_pred.bounds.iter() { match bound { - &hir::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => { + &hir::GenericBound::Trait(ref poly_trait_ref, _) => { let mut projections = Vec::new(); let trait_ref = @@ -1462,7 +1498,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - &hir::TyParamBound::RegionTyParamBound(ref lifetime) => { + &hir::GenericBound::Outlives(ref lifetime) => { let region = AstConv::ast_region_to_region(&icx, lifetime, None); @@ -1476,7 +1512,12 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, &hir::WherePredicate::RegionPredicate(ref region_pred) => { let r1 = AstConv::ast_region_to_region(&icx, ®ion_pred.lifetime, None); for bound in ®ion_pred.bounds { - let r2 = AstConv::ast_region_to_region(&icx, bound, None); + let r2 = match bound { + hir::GenericBound::Outlives(lt) => { + AstConv::ast_region_to_region(&icx, lt, None) + } + _ => bug!(), + }; let pred = ty::Binder::bind(ty::OutlivesPredicate(r1, r2)); predicates.push(ty::Predicate::RegionOutlives(pred)) } @@ -1541,7 +1582,7 @@ pub enum SizedByDefault { Yes, No, } /// built-in trait (formerly known as kind): Send. pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, param_ty: Ty<'tcx>, - ast_bounds: &[hir::TyParamBound], + ast_bounds: &[hir::GenericBound], sized_by_default: SizedByDefault, span: Span) -> Bounds<'tcx> @@ -1550,22 +1591,16 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, let mut trait_bounds = vec![]; for ast_bound in ast_bounds { match *ast_bound { - hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => { - trait_bounds.push(b); - } - hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {} - hir::RegionTyParamBound(ref l) => { - region_bounds.push(l); - } + hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => trait_bounds.push(b), + hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {} + hir::GenericBound::Outlives(ref l) => region_bounds.push(l), } } let mut projection_bounds = vec![]; let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| { - astconv.instantiate_poly_trait_ref(bound, - param_ty, - &mut projection_bounds) + astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds) }).collect(); let region_bounds = region_bounds.into_iter().map(|r| { @@ -1588,18 +1623,18 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, } } -/// Converts a specific TyParamBound from the AST into a set of +/// Converts a specific GenericBound from the AST into a set of /// predicates that apply to the self-type. A vector is returned /// because this can be anywhere from 0 predicates (`T:?Sized` adds no /// predicates) to 1 (`T:Foo`) to many (`T:Bar` adds `T:Bar` /// and `::X == i32`). fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, param_ty: Ty<'tcx>, - bound: &hir::TyParamBound) + bound: &hir::GenericBound) -> Vec> { match *bound { - hir::TraitTyParamBound(ref tr, hir::TraitBoundModifier::None) => { + hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => { let mut projections = Vec::new(); let pred = astconv.instantiate_poly_trait_ref(tr, param_ty, @@ -1609,14 +1644,12 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, .chain(Some(pred.to_predicate())) .collect() } - hir::RegionTyParamBound(ref lifetime) => { + hir::GenericBound::Outlives(ref lifetime) => { let region = astconv.ast_region_to_region(lifetime, None); let pred = ty::Binder::bind(ty::OutlivesPredicate(param_ty, region)); vec![ty::Predicate::TypeOutlives(pred)] } - hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => { - Vec::new() - } + hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => vec![], } } diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index da54eeabdb97b..3f7e3529e9648 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1501,12 +1501,12 @@ struct Foo { "##, E0131: r##" -It is not possible to define `main` with type parameters, or even with function -parameters. When `main` is present, it must take no arguments and return `()`. +It is not possible to define `main` with generic parameters. +When `main` is present, it must take no arguments and return `()`. Erroneous code example: ```compile_fail,E0131 -fn main() { // error: main function is not allowed to have type parameters +fn main() { // error: main function is not allowed to have generic parameters } ``` "##, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 80f57adf580bf..dcc5fa53d2f42 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -76,6 +76,7 @@ This API is completely unstable and subject to change. #![feature(crate_visibility_modifier)] #![feature(from_ref)] #![feature(exhaustive_patterns)] +#![feature(iterator_find_map)] #![feature(quote)] #![feature(refcell_replace_swap)] #![feature(rustc_diagnostic_macros)] @@ -190,16 +191,9 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, hir::ItemFn(.., ref generics, _) => { let mut error = false; if !generics.params.is_empty() { - let param_type = if generics.is_lt_parameterized() { - "lifetime" - } else { - "type" - }; - let msg = - format!("`main` function is not allowed to have {} parameters", - param_type); - let label = - format!("`main` cannot have {} parameters", param_type); + let msg = format!("`main` function is not allowed to have generic \ + parameters"); + let label = format!("`main` cannot have generic parameters"); struct_span_err!(tcx.sess, generics.span, E0131, "{}", msg) .span_label(generics.span, label) .emit(); diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index da749fca2a953..5c09da90491d0 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -244,34 +244,32 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { None } - fn generics_to_path_params(&self, generics: ty::Generics) -> hir::PathParameters { - let mut lifetimes = vec![]; - let mut types = vec![]; + fn generics_to_path_params(&self, generics: ty::Generics) -> hir::GenericArgs { + let mut args = vec![]; for param in generics.params.iter() { match param.kind { ty::GenericParamDefKind::Lifetime => { let name = if param.name == "" { - hir::LifetimeName::Static + hir::ParamName::Plain(keywords::StaticLifetime.name()) } else { - hir::LifetimeName::Name(param.name.as_symbol()) + hir::ParamName::Plain(param.name.as_symbol()) }; - lifetimes.push(hir::Lifetime { + args.push(hir::GenericArg::Lifetime(hir::Lifetime { id: ast::DUMMY_NODE_ID, span: DUMMY_SP, - name, - }); + name: hir::LifetimeName::Param(name), + })); } ty::GenericParamDefKind::Type {..} => { - types.push(P(self.ty_param_to_ty(param.clone()))); + args.push(hir::GenericArg::Type(P(self.ty_param_to_ty(param.clone())))); } } } - hir::PathParameters { - lifetimes: HirVec::from_vec(lifetimes), - types: HirVec::from_vec(types), + hir::GenericArgs { + args: HirVec::from_vec(args), bindings: HirVec::new(), parenthesized: false, } @@ -488,11 +486,8 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { .iter() .flat_map(|(name, lifetime)| { let empty = Vec::new(); - let bounds: FxHashSet = finished - .get(name) - .unwrap_or(&empty) - .iter() - .map(|region| self.get_lifetime(region, names_map)) + let bounds: FxHashSet = finished.get(name).unwrap_or(&empty).iter() + .map(|region| GenericBound::Outlives(self.get_lifetime(region, names_map))) .collect(); if bounds.is_empty() { @@ -523,7 +518,10 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // We only care about late bound regions, as we need to add them // to the 'for<>' section &ty::ReLateBound(_, ty::BoundRegion::BrNamed(_, name)) => { - Some(GenericParamDef::Lifetime(Lifetime(name.to_string()))) + Some(GenericParamDef { + name: name.to_string(), + kind: GenericParamDefKind::Lifetime, + }) } &ty::ReVar(_) | &ty::ReEarlyBound(_) => None, _ => panic!("Unexpected region type {:?}", r), @@ -535,9 +533,9 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { fn make_final_bounds<'b, 'c, 'cx>( &self, - ty_to_bounds: FxHashMap>, + ty_to_bounds: FxHashMap>, ty_to_fn: FxHashMap, Option)>, - lifetime_to_bounds: FxHashMap>, + lifetime_to_bounds: FxHashMap>, ) -> Vec { ty_to_bounds .into_iter() @@ -555,9 +553,9 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { let mut new_path = path.clone(); let last_segment = new_path.segments.pop().unwrap(); - let (old_input, old_output) = match last_segment.params { - PathParameters::AngleBracketed { types, .. } => (types, None), - PathParameters::Parenthesized { inputs, output, .. } => { + let (old_input, old_output) = match last_segment.args { + GenericArgs::AngleBracketed { types, .. } => (types, None), + GenericArgs::Parenthesized { inputs, output, .. } => { (inputs, output) } }; @@ -569,14 +567,14 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { ); } - let new_params = PathParameters::Parenthesized { + let new_params = GenericArgs::Parenthesized { inputs: old_input, output, }; new_path.segments.push(PathSegment { name: last_segment.name, - params: new_params, + args: new_params, }); Type::ResolvedPath { @@ -588,7 +586,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { } _ => panic!("Unexpected data: {:?}, {:?}", ty, data), }; - bounds.insert(TyParamBound::TraitBound( + bounds.insert(GenericBound::TraitBound( PolyTrait { trait_: new_ty, generic_params: poly_trait.generic_params, @@ -614,7 +612,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { .filter(|&(_, ref bounds)| !bounds.is_empty()) .map(|(lifetime, bounds)| { let mut bounds_vec = bounds.into_iter().collect(); - self.sort_where_lifetimes(&mut bounds_vec); + self.sort_where_bounds(&mut bounds_vec); WherePredicate::RegionPredicate { lifetime, bounds: bounds_vec, @@ -731,7 +729,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // later let is_fn = match &mut b { - &mut TyParamBound::TraitBound(ref mut p, _) => { + &mut GenericBound::TraitBound(ref mut p, _) => { // Insert regions into the for_generics hash map first, to ensure // that we don't end up with duplicate bounds (e.g. for<'b, 'b>) for_generics.extend(p.generic_params.clone()); @@ -793,13 +791,13 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // FIXME: Remove this scope when NLL lands { - let params = - &mut new_trait_path.segments.last_mut().unwrap().params; + let args = + &mut new_trait_path.segments.last_mut().unwrap().args; - match params { + match args { // Convert somethiung like ' = u8' // to 'T: Iterator' - &mut PathParameters::AngleBracketed { + &mut GenericArgs::AngleBracketed { ref mut bindings, .. } => { @@ -808,7 +806,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { ty: rhs, }); } - &mut PathParameters::Parenthesized { .. } => { + &mut GenericArgs::Parenthesized { .. } => { existing_predicates.push( WherePredicate::EqPredicate { lhs: lhs.clone(), @@ -825,7 +823,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { .entry(*ty.clone()) .or_insert_with(|| FxHashSet()); - bounds.insert(TyParamBound::TraitBound( + bounds.insert(GenericBound::TraitBound( PolyTrait { trait_: Type::ResolvedPath { path: new_trait_path, @@ -842,7 +840,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // that we don't see a // duplicate bound like `T: Iterator + Iterator` // on the docs page. - bounds.remove(&TyParamBound::TraitBound( + bounds.remove(&GenericBound::TraitBound( PolyTrait { trait_: *trait_.clone(), generic_params: Vec::new(), @@ -869,19 +867,17 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { existing_predicates.extend(final_bounds); - for p in generic_params.iter_mut() { - match p { - &mut GenericParamDef::Type(ref mut ty) => { - // We never want something like 'impl' - ty.default.take(); - - let generic_ty = Type::Generic(ty.name.clone()); - + for param in generic_params.iter_mut() { + match param.kind { + GenericParamDefKind::Type { ref mut default, ref mut bounds, .. } => { + // We never want something like `impl`. + default.take(); + let generic_ty = Type::Generic(param.name.clone()); if !has_sized.contains(&generic_ty) { - ty.bounds.insert(0, TyParamBound::maybe_sized(self.cx)); + bounds.insert(0, GenericBound::maybe_sized(self.cx)); } } - GenericParamDef::Lifetime(_) => {} + GenericParamDefKind::Lifetime => {} } } @@ -912,15 +908,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // both for visual consistency between 'rustdoc' runs, and to // make writing tests much easier #[inline] - fn sort_where_bounds(&self, mut bounds: &mut Vec) { - // We should never have identical bounds - and if we do, - // they're visually identical as well. Therefore, using - // an unstable sort is fine. - self.unstable_debug_sort(&mut bounds); - } - - #[inline] - fn sort_where_lifetimes(&self, mut bounds: &mut Vec) { + fn sort_where_bounds(&self, mut bounds: &mut Vec) { // We should never have identical bounds - and if we do, // they're visually identical as well. Therefore, using // an unstable sort is fine. @@ -940,7 +928,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // to end users, it makes writing tests much more difficult, as predicates // can appear in any order in the final result. // - // To solve this problem, we sort WherePredicates and TyParamBounds + // To solve this problem, we sort WherePredicates and GenericBounds // by their Debug string. The thing to keep in mind is that we don't really // care what the final order is - we're synthesizing an impl or bound // ourselves, so any order can be considered equally valid. By sorting the @@ -950,7 +938,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { // Using the Debug impementation for sorting prevents us from needing to // write quite a bit of almost entirely useless code (e.g. how should two // Types be sorted relative to each other). It also allows us to solve the - // problem for both WherePredicates and TyParamBounds at the same time. This + // problem for both WherePredicates and GenericBounds at the same time. This // approach is probably somewhat slower, but the small number of items // involved (impls rarely have more than a few bounds) means that it // shouldn't matter in practice. diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 80eb2d1e214fb..114cb0e455d9a 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -374,8 +374,8 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { let polarity = tcx.impl_polarity(did); let trait_ = associated_trait.clean(cx).map(|bound| { match bound { - clean::TraitBound(polyt, _) => polyt.trait_, - clean::RegionBound(..) => unreachable!(), + clean::GenericBound::TraitBound(polyt, _) => polyt.trait_, + clean::GenericBound::Outlives(..) => unreachable!(), } }); if trait_.def_id() == tcx.lang_items().deref_trait() { @@ -387,9 +387,9 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec) { let provided = trait_.def_id().map(|did| { tcx.provided_trait_methods(did) - .into_iter() - .map(|meth| meth.name.to_string()) - .collect() + .into_iter() + .map(|meth| meth.name.to_string()) + .collect() }).unwrap_or(FxHashSet()); ret.push(clean::Item { @@ -474,7 +474,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: } if *s == "Self" => { bounds.retain(|bound| { match *bound { - clean::TyParamBound::TraitBound(clean::PolyTrait { + clean::GenericBound::TraitBound(clean::PolyTrait { trait_: clean::ResolvedPath { did, .. }, .. }, _) => did != trait_did, @@ -505,7 +505,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: /// the metadata for a crate, so we want to separate those out and create a new /// list of explicit supertrait bounds to render nicely. fn separate_supertrait_bounds(mut g: clean::Generics) - -> (clean::Generics, Vec) { + -> (clean::Generics, Vec) { let mut ty_bounds = Vec::new(); g.where_predicates.retain(|pred| { match *pred { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 852a4479199df..0979c3d85587d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -14,7 +14,6 @@ pub use self::Type::*; pub use self::Mutability::*; pub use self::ItemEnum::*; -pub use self::TyParamBound::*; pub use self::SelfTy::*; pub use self::FunctionRetTy::*; pub use self::Visibility::{Public, Inherited}; @@ -36,12 +35,12 @@ use rustc::middle::resolve_lifetime as rl; use rustc::ty::fold::TypeFolder; use rustc::middle::lang_items; use rustc::mir::interpret::GlobalId; -use rustc::hir::{self, HirVec}; +use rustc::hir::{self, GenericArg, HirVec}; use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::hir::def_id::DefIndexAddressSpace; use rustc::ty::subst::Substs; -use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind, GenericParamCount}; +use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::middle::stability; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_typeck::hir_ty_to_ty; @@ -532,7 +531,7 @@ pub enum ItemEnum { MacroItem(Macro), PrimitiveItem(PrimitiveType), AssociatedConstItem(Type, Option), - AssociatedTypeItem(Vec, Option), + AssociatedTypeItem(Vec, Option), /// An item that has been stripped by a rustdoc pass StrippedItem(Box), KeywordItem(String), @@ -1458,61 +1457,19 @@ impl Clean for [ast::Attribute] { } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] -pub struct TyParam { - pub name: String, - pub did: DefId, - pub bounds: Vec, - pub default: Option, - pub synthetic: Option, -} - -impl Clean for hir::TyParam { - fn clean(&self, cx: &DocContext) -> TyParam { - TyParam { - name: self.name.clean(cx), - did: cx.tcx.hir.local_def_id(self.id), - bounds: self.bounds.clean(cx), - default: self.default.clean(cx), - synthetic: self.synthetic, - } - } +pub enum GenericBound { + TraitBound(PolyTrait, hir::TraitBoundModifier), + Outlives(Lifetime), } -impl<'tcx> Clean for ty::GenericParamDef { - fn clean(&self, cx: &DocContext) -> TyParam { - cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx)); - let has_default = match self.kind { - ty::GenericParamDefKind::Type { has_default, .. } => has_default, - _ => panic!("tried to convert a non-type GenericParamDef as a type") - }; - TyParam { - name: self.name.clean(cx), - did: self.def_id, - bounds: vec![], // these are filled in from the where-clauses - default: if has_default { - Some(cx.tcx.type_of(self.def_id).clean(cx)) - } else { - None - }, - synthetic: None, - } - } -} - -#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] -pub enum TyParamBound { - RegionBound(Lifetime), - TraitBound(PolyTrait, hir::TraitBoundModifier) -} - -impl TyParamBound { - fn maybe_sized(cx: &DocContext) -> TyParamBound { +impl GenericBound { + fn maybe_sized(cx: &DocContext) -> GenericBound { let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem); let empty = cx.tcx.intern_substs(&[]); let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, vec![], empty); inline::record_extern_fqn(cx, did, TypeKind::Trait); - TraitBound(PolyTrait { + GenericBound::TraitBound(PolyTrait { trait_: ResolvedPath { path, typarams: None, @@ -1525,7 +1482,7 @@ impl TyParamBound { fn is_sized_bound(&self, cx: &DocContext) -> bool { use rustc::hir::TraitBoundModifier as TBM; - if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self { + if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self { if trait_.def_id() == cx.tcx.lang_items().sized_trait() { return true; } @@ -1534,7 +1491,7 @@ impl TyParamBound { } fn get_poly_trait(&self) -> Option { - if let TyParamBound::TraitBound(ref p, _) = *self { + if let GenericBound::TraitBound(ref p, _) = *self { return Some(p.clone()) } None @@ -1542,24 +1499,26 @@ impl TyParamBound { fn get_trait_type(&self) -> Option { - if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self { + if let GenericBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self { return Some(trait_.clone()); } None } } -impl Clean for hir::TyParamBound { - fn clean(&self, cx: &DocContext) -> TyParamBound { +impl Clean for hir::GenericBound { + fn clean(&self, cx: &DocContext) -> GenericBound { match *self { - hir::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)), - hir::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier), + hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)), + hir::GenericBound::Trait(ref t, modifier) => { + GenericBound::TraitBound(t.clean(cx), modifier) + } } } } -fn external_path_params(cx: &DocContext, trait_did: Option, has_self: bool, - bindings: Vec, substs: &Substs) -> PathParameters { +fn external_generic_args(cx: &DocContext, trait_did: Option, has_self: bool, + bindings: Vec, substs: &Substs) -> GenericArgs { let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect(); let types = substs.types().skip(has_self as usize).collect::>(); @@ -1570,7 +1529,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option, has_self: boo let inputs = match types[0].sty { ty::TyTuple(ref tys) => tys.iter().map(|t| t.clean(cx)).collect(), _ => { - return PathParameters::AngleBracketed { + return GenericArgs::AngleBracketed { lifetimes, types: types.clean(cx), bindings, @@ -1583,13 +1542,13 @@ fn external_path_params(cx: &DocContext, trait_did: Option, has_self: boo // ty::TyTuple(ref v) if v.is_empty() => None, // -> () // _ => Some(types[1].clean(cx)) // }; - PathParameters::Parenthesized { + GenericArgs::Parenthesized { inputs, output, } }, _ => { - PathParameters::AngleBracketed { + GenericArgs::AngleBracketed { lifetimes, types: types.clean(cx), bindings, @@ -1607,13 +1566,13 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option, has_self def: Def::Err, segments: vec![PathSegment { name: name.to_string(), - params: external_path_params(cx, trait_did, has_self, bindings, substs) + args: external_generic_args(cx, trait_did, has_self, bindings, substs) }], } } -impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec) { - fn clean(&self, cx: &DocContext) -> TyParamBound { +impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec) { + fn clean(&self, cx: &DocContext) -> GenericBound { let (trait_ref, ref bounds) = *self; inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait); let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id).as_str(), @@ -1629,8 +1588,11 @@ impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec if let ty::TyRef(ref reg, _, _) = ty_s.sty { if let &ty::RegionKind::ReLateBound(..) = *reg { debug!(" hit an ReLateBound {:?}", reg); - if let Some(lt) = reg.clean(cx) { - late_bounds.push(GenericParamDef::Lifetime(lt)); + if let Some(Lifetime(name)) = reg.clean(cx) { + late_bounds.push(GenericParamDef { + name, + kind: GenericParamDefKind::Lifetime, + }); } } } @@ -1638,7 +1600,7 @@ impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec } } - TraitBound( + GenericBound::TraitBound( PolyTrait { trait_: ResolvedPath { path, @@ -1653,18 +1615,17 @@ impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec } } -impl<'tcx> Clean for ty::TraitRef<'tcx> { - fn clean(&self, cx: &DocContext) -> TyParamBound { +impl<'tcx> Clean for ty::TraitRef<'tcx> { + fn clean(&self, cx: &DocContext) -> GenericBound { (self, vec![]).clean(cx) } } -impl<'tcx> Clean>> for Substs<'tcx> { - fn clean(&self, cx: &DocContext) -> Option> { +impl<'tcx> Clean>> for Substs<'tcx> { + fn clean(&self, cx: &DocContext) -> Option> { let mut v = Vec::new(); - v.extend(self.regions().filter_map(|r| r.clean(cx)) - .map(RegionBound)); - v.extend(self.types().map(|t| TraitBound(PolyTrait { + v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives)); + v.extend(self.types().map(|t| GenericBound::TraitBound(PolyTrait { trait_: t.clean(cx), generic_params: Vec::new(), }, hir::TraitBoundModifier::None))); @@ -1707,18 +1668,26 @@ impl Clean for hir::Lifetime { } } -impl Clean for hir::LifetimeDef { +impl Clean for hir::GenericParam { fn clean(&self, _: &DocContext) -> Lifetime { - if self.bounds.len() > 0 { - let mut s = format!("{}: {}", - self.lifetime.name.name(), - self.bounds[0].name.name()); - for bound in self.bounds.iter().skip(1) { - s.push_str(&format!(" + {}", bound.name.name())); + match self.kind { + hir::GenericParamKind::Lifetime { .. } => { + if self.bounds.len() > 0 { + let mut bounds = self.bounds.iter().map(|bound| match bound { + hir::GenericBound::Outlives(lt) => lt, + _ => panic!(), + }); + let name = bounds.next().unwrap().name.name(); + let mut s = format!("{}: {}", self.name.name(), name); + for bound in bounds { + s.push_str(&format!(" + {}", bound.name.name())); + } + Lifetime(s) + } else { + Lifetime(self.name.name().to_string()) + } } - Lifetime(s) - } else { - Lifetime(self.lifetime.name.name().to_string()) + _ => panic!(), } } } @@ -1751,8 +1720,8 @@ impl Clean> for ty::RegionKind { #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] pub enum WherePredicate { - BoundPredicate { ty: Type, bounds: Vec }, - RegionPredicate { lifetime: Lifetime, bounds: Vec}, + BoundPredicate { ty: Type, bounds: Vec }, + RegionPredicate { lifetime: Lifetime, bounds: Vec }, EqPredicate { lhs: Type, rhs: Type }, } @@ -1822,7 +1791,7 @@ impl<'tcx> Clean for ty::OutlivesPredicate, ty: let ty::OutlivesPredicate(ref a, ref b) = *self; WherePredicate::RegionPredicate { lifetime: a.clean(cx).unwrap(), - bounds: vec![b.clean(cx).unwrap()] + bounds: vec![GenericBound::Outlives(b.clean(cx).unwrap())] } } } @@ -1833,7 +1802,7 @@ impl<'tcx> Clean for ty::OutlivesPredicate, ty::Region< WherePredicate::BoundPredicate { ty: ty.clean(cx), - bounds: vec![TyParamBound::RegionBound(lt.clean(cx).unwrap())] + bounds: vec![GenericBound::Outlives(lt.clean(cx).unwrap())] } } } @@ -1850,10 +1819,8 @@ impl<'tcx> Clean for ty::ProjectionPredicate<'tcx> { impl<'tcx> Clean for ty::ProjectionTy<'tcx> { fn clean(&self, cx: &DocContext) -> Type { let trait_ = match self.trait_ref(cx.tcx).clean(cx) { - TyParamBound::TraitBound(t, _) => t.trait_, - TyParamBound::RegionBound(_) => { - panic!("cleaning a trait got a region") - } + GenericBound::TraitBound(t, _) => t.trait_, + GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"), }; Type::QPath { name: cx.tcx.associated_item(self.item_def_id).name.clean(cx), @@ -1864,25 +1831,95 @@ impl<'tcx> Clean for ty::ProjectionTy<'tcx> { } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] -pub enum GenericParamDef { - Lifetime(Lifetime), - Type(TyParam), +pub enum GenericParamDefKind { + Lifetime, + Type { + did: DefId, + bounds: Vec, + default: Option, + synthetic: Option, + }, +} + +#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] +pub struct GenericParamDef { + pub name: String, + + pub kind: GenericParamDefKind, } impl GenericParamDef { pub fn is_synthetic_type_param(&self) -> bool { - match self { - GenericParamDef::Type(ty) => ty.synthetic.is_some(), - GenericParamDef::Lifetime(_) => false, + match self.kind { + GenericParamDefKind::Lifetime => false, + GenericParamDefKind::Type { ref synthetic, .. } => synthetic.is_some(), + } + } +} + +impl<'tcx> Clean for ty::GenericParamDef { + fn clean(&self, cx: &DocContext) -> GenericParamDef { + let (name, kind) = match self.kind { + ty::GenericParamDefKind::Lifetime => { + (self.name.to_string(), GenericParamDefKind::Lifetime) + } + ty::GenericParamDefKind::Type { has_default, .. } => { + cx.renderinfo.borrow_mut().external_typarams + .insert(self.def_id, self.name.clean(cx)); + let default = if has_default { + Some(cx.tcx.type_of(self.def_id).clean(cx)) + } else { + None + }; + (self.name.clean(cx), GenericParamDefKind::Type { + did: self.def_id, + bounds: vec![], // These are filled in from the where-clauses. + default, + synthetic: None, + }) + } + }; + + GenericParamDef { + name, + kind, } } } impl Clean for hir::GenericParam { fn clean(&self, cx: &DocContext) -> GenericParamDef { - match *self { - hir::GenericParam::Lifetime(ref l) => GenericParamDef::Lifetime(l.clean(cx)), - hir::GenericParam::Type(ref t) => GenericParamDef::Type(t.clean(cx)), + let (name, kind) = match self.kind { + hir::GenericParamKind::Lifetime { .. } => { + let name = if self.bounds.len() > 0 { + let mut bounds = self.bounds.iter().map(|bound| match bound { + hir::GenericBound::Outlives(lt) => lt, + _ => panic!(), + }); + let name = bounds.next().unwrap().name.name(); + let mut s = format!("{}: {}", self.name.name(), name); + for bound in bounds { + s.push_str(&format!(" + {}", bound.name.name())); + } + s + } else { + self.name.name().to_string() + }; + (name, GenericParamDefKind::Lifetime) + } + hir::GenericParamKind::Type { ref default, synthetic, .. } => { + (self.name.name().clean(cx), GenericParamDefKind::Type { + did: cx.tcx.hir.local_def_id(self.id), + bounds: self.bounds.clean(cx), + default: default.clean(cx), + synthetic: synthetic, + }) + } + }; + + GenericParamDef { + name, + kind, } } } @@ -1900,25 +1937,25 @@ impl Clean for hir::Generics { // In order for normal parameters to be able to refer to synthetic ones, // scans them first. fn is_impl_trait(param: &hir::GenericParam) -> bool { - if let hir::GenericParam::Type(ref tp) = param { - tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) - } else { - false + match param.kind { + hir::GenericParamKind::Type { synthetic, .. } => { + synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) + } + _ => false, } } let impl_trait_params = self.params .iter() - .filter(|p| is_impl_trait(p)) - .map(|p| { - let p = p.clean(cx); - if let GenericParamDef::Type(ref tp) = p { - cx.impl_trait_bounds - .borrow_mut() - .insert(tp.did, tp.bounds.clone()); - } else { - unreachable!() + .filter(|param| is_impl_trait(param)) + .map(|param| { + let param: GenericParamDef = param.clean(cx); + match param.kind { + GenericParamDefKind::Lifetime => unreachable!(), + GenericParamDefKind::Type { did, ref bounds, .. } => { + cx.impl_trait_bounds.borrow_mut().insert(did, bounds.clone()); + } } - p + param }) .collect::>(); @@ -1929,23 +1966,26 @@ impl Clean for hir::Generics { } params.extend(impl_trait_params); - let mut g = Generics { + let mut generics = Generics { params, - where_predicates: self.where_clause.predicates.clean(cx) + where_predicates: self.where_clause.predicates.clean(cx), }; // Some duplicates are generated for ?Sized bounds between type params and where // predicates. The point in here is to move the bounds definitions from type params // to where predicates when such cases occur. - for where_pred in &mut g.where_predicates { + for where_pred in &mut generics.where_predicates { match *where_pred { WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => { if bounds.is_empty() { - for param in &mut g.params { - if let GenericParamDef::Type(ref mut type_param) = *param { - if &type_param.name == name { - mem::swap(bounds, &mut type_param.bounds); - break + for param in &mut generics.params { + match param.kind { + GenericParamDefKind::Lifetime => {} + GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => { + if ¶m.name == name { + mem::swap(bounds, ty_bounds); + break + } } } } @@ -1954,7 +1994,7 @@ impl Clean for hir::Generics { _ => continue, } } - g + generics } } @@ -1968,18 +2008,16 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, // Bounds in the type_params and lifetimes fields are repeated in the // predicates field (see rustc_typeck::collect::ty_generics), so remove // them. - let stripped_typarams = gens.params.iter().filter_map(|param| { - if let ty::GenericParamDefKind::Type {..} = param.kind { + let stripped_typarams = gens.params.iter().filter_map(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => None, + ty::GenericParamDefKind::Type { .. } => { if param.name == keywords::SelfType.name().as_str() { assert_eq!(param.index, 0); - None - } else { - Some(param.clean(cx)) + return None; } - } else { - None + Some(param.clean(cx)) } - }).collect::>(); + }).collect::>(); let mut where_predicates = preds.predicates.to_vec().clean(cx); @@ -2011,7 +2049,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, if !sized_params.contains(&tp.name) { where_predicates.push(WP::BoundPredicate { ty: Type::Generic(tp.name.clone()), - bounds: vec![TyParamBound::maybe_sized(cx)], + bounds: vec![GenericBound::maybe_sized(cx)], }) } } @@ -2023,17 +2061,10 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, Generics { params: gens.params .iter() - .flat_map(|param| { - if let ty::GenericParamDefKind::Lifetime = param.kind { - Some(GenericParamDef::Lifetime(param.clean(cx))) - } else { - None - } - }).chain( - simplify::ty_params(stripped_typarams) - .into_iter() - .map(|tp| GenericParamDef::Type(tp)) - ) + .flat_map(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)), + ty::GenericParamDefKind::Type { .. } => None, + }).chain(simplify::ty_params(stripped_typarams).into_iter()) .collect(), where_predicates: simplify::where_clauses(cx, where_predicates), } @@ -2259,7 +2290,7 @@ pub struct Trait { pub unsafety: hir::Unsafety, pub items: Vec, pub generics: Generics, - pub bounds: Vec, + pub bounds: Vec, pub is_spotlight: bool, pub is_auto: bool, } @@ -2481,7 +2512,7 @@ impl<'tcx> Clean for ty::AssociatedItem { // at the end. match bounds.iter().position(|b| b.is_sized_bound(cx)) { Some(i) => { bounds.remove(i); } - None => bounds.push(TyParamBound::maybe_sized(cx)), + None => bounds.push(GenericBound::maybe_sized(cx)), } let ty = if self.defaultness.has_value() { @@ -2536,7 +2567,7 @@ pub enum Type { /// structs/enums/traits (most that'd be an hir::TyPath) ResolvedPath { path: Path, - typarams: Option>, + typarams: Option>, did: DefId, /// true if is a `T::Name` path for associated types is_generic: bool, @@ -2572,7 +2603,7 @@ pub enum Type { Infer, // impl TraitA+TraitB - ImplTrait(Vec), + ImplTrait(Vec), } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)] @@ -2656,7 +2687,7 @@ impl Type { match *self { ResolvedPath { ref path, .. } => { path.segments.last().and_then(|seg| { - if let PathParameters::AngleBracketed { ref types, .. } = seg.params { + if let GenericArgs::AngleBracketed { ref types, .. } = seg.args { Some(&**types) } else { None @@ -2851,31 +2882,55 @@ impl Clean for hir::Ty { let provided_params = &path.segments.last().unwrap(); let mut ty_substs = FxHashMap(); let mut lt_substs = FxHashMap(); - provided_params.with_parameters(|provided_params| { - let mut indices = GenericParamCount { + provided_params.with_generic_args(|generic_args| { + let mut indices = ty::GenericParamCount { lifetimes: 0, types: 0 }; for param in generics.params.iter() { - match param { - hir::GenericParam::Lifetime(lt_param) => { - if let Some(lt) = provided_params.lifetimes - .get(indices.lifetimes).cloned() { + match param.kind { + hir::GenericParamKind::Lifetime { .. } => { + let mut j = 0; + let lifetime = generic_args.args.iter().find_map(|arg| { + match arg { + GenericArg::Lifetime(lt) => { + if indices.lifetimes == j { + return Some(lt); + } + j += 1; + None + } + _ => None, + } + }); + if let Some(lt) = lifetime.cloned() { if !lt.is_elided() { let lt_def_id = - cx.tcx.hir.local_def_id(lt_param.lifetime.id); + cx.tcx.hir.local_def_id(param.id); lt_substs.insert(lt_def_id, lt.clean(cx)); } } indices.lifetimes += 1; } - hir::GenericParam::Type(ty_param) => { + hir::GenericParamKind::Type { ref default, .. } => { let ty_param_def = - Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id)); - if let Some(ty) = provided_params.types - .get(indices.types).cloned() { + Def::TyParam(cx.tcx.hir.local_def_id(param.id)); + let mut j = 0; + let type_ = generic_args.args.iter().find_map(|arg| { + match arg { + GenericArg::Type(ty) => { + if indices.types == j { + return Some(ty); + } + j += 1; + None + } + _ => None, + } + }); + if let Some(ty) = type_.cloned() { ty_substs.insert(ty_param_def, ty.into_inner().clean(cx)); - } else if let Some(default) = ty_param.default.clone() { + } else if let Some(default) = default.clone() { ty_substs.insert(ty_param_def, default.into_inner().clean(cx)); } @@ -2922,18 +2977,14 @@ impl Clean for hir::Ty { TyTraitObject(ref bounds, ref lifetime) => { match bounds[0].clean(cx).trait_ { ResolvedPath { path, typarams: None, did, is_generic } => { - let mut bounds: Vec<_> = bounds[1..].iter().map(|bound| { - TraitBound(bound.clean(cx), hir::TraitBoundModifier::None) + let mut bounds: Vec = bounds[1..].iter().map(|bound| { + self::GenericBound::TraitBound(bound.clean(cx), + hir::TraitBoundModifier::None) }).collect(); if !lifetime.is_elided() { - bounds.push(RegionBound(lifetime.clean(cx))); - } - ResolvedPath { - path, - typarams: Some(bounds), - did, - is_generic, + bounds.push(self::GenericBound::Outlives(lifetime.clean(cx))); } + ResolvedPath { path, typarams: Some(bounds), did, is_generic, } } _ => Infer // shouldn't happen } @@ -3030,13 +3081,13 @@ impl<'tcx> Clean for Ty<'tcx> { inline::record_extern_fqn(cx, did, TypeKind::Trait); let mut typarams = vec![]; - reg.clean(cx).map(|b| typarams.push(RegionBound(b))); + reg.clean(cx).map(|b| typarams.push(GenericBound::Outlives(b))); for did in obj.auto_traits() { let empty = cx.tcx.intern_substs(&[]); let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, vec![], empty); inline::record_extern_fqn(cx, did, TypeKind::Trait); - let bound = TraitBound(PolyTrait { + let bound = GenericBound::TraitBound(PolyTrait { trait_: ResolvedPath { path, typarams: None, @@ -3087,7 +3138,9 @@ impl<'tcx> Clean for Ty<'tcx> { tr } else if let ty::Predicate::TypeOutlives(pred) = *predicate { // these should turn up at the end - pred.skip_binder().1.clean(cx).map(|r| regions.push(RegionBound(r))); + pred.skip_binder().1.clean(cx).map(|r| { + regions.push(GenericBound::Outlives(r)) + }); return None; } else { return None; @@ -3100,7 +3153,6 @@ impl<'tcx> Clean for Ty<'tcx> { } } - let bounds = bounds.predicates.iter().filter_map(|pred| if let ty::Predicate::Projection(proj) = *pred { let proj = proj.skip_binder(); @@ -3122,7 +3174,7 @@ impl<'tcx> Clean for Ty<'tcx> { }).collect::>(); bounds.extend(regions); if !has_sized && !bounds.is_empty() { - bounds.insert(0, TyParamBound::maybe_sized(cx)); + bounds.insert(0, GenericBound::maybe_sized(cx)); } ImplTrait(bounds) } @@ -3447,7 +3499,7 @@ impl Path { def: Def::Err, segments: vec![PathSegment { name, - params: PathParameters::AngleBracketed { + args: GenericArgs::AngleBracketed { lifetimes: Vec::new(), types: Vec::new(), bindings: Vec::new(), @@ -3472,7 +3524,7 @@ impl Clean for hir::Path { } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] -pub enum PathParameters { +pub enum GenericArgs { AngleBracketed { lifetimes: Vec, types: Vec, @@ -3484,22 +3536,33 @@ pub enum PathParameters { } } -impl Clean for hir::PathParameters { - fn clean(&self, cx: &DocContext) -> PathParameters { +impl Clean for hir::GenericArgs { + fn clean(&self, cx: &DocContext) -> GenericArgs { if self.parenthesized { let output = self.bindings[0].ty.clean(cx); - PathParameters::Parenthesized { + GenericArgs::Parenthesized { inputs: self.inputs().clean(cx), output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None } } } else { - PathParameters::AngleBracketed { - lifetimes: if self.lifetimes.iter().all(|lt| lt.is_elided()) { - vec![] - } else { - self.lifetimes.clean(cx) - }, - types: self.types.clean(cx), + let (mut lifetimes, mut types) = (vec![], vec![]); + let mut elided_lifetimes = true; + for arg in &self.args { + match arg { + GenericArg::Lifetime(lt) => { + if !lt.is_elided() { + elided_lifetimes = false; + } + lifetimes.push(lt.clean(cx)); + } + GenericArg::Type(ty) => { + types.push(ty.clean(cx)); + } + } + } + GenericArgs::AngleBracketed { + lifetimes: if elided_lifetimes { vec![] } else { lifetimes }, + types, bindings: self.bindings.clean(cx), } } @@ -3509,14 +3572,14 @@ impl Clean for hir::PathParameters { #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)] pub struct PathSegment { pub name: String, - pub params: PathParameters, + pub args: GenericArgs, } impl Clean for hir::PathSegment { fn clean(&self, cx: &DocContext) -> PathSegment { PathSegment { name: self.name.clean(cx), - params: self.with_parameters(|parameters| parameters.clean(cx)) + args: self.with_generic_args(|generic_args| generic_args.clean(cx)) } } } @@ -3550,7 +3613,7 @@ fn strip_path(path: &Path) -> Path { let segments = path.segments.iter().map(|s| { PathSegment { name: s.name.clone(), - params: PathParameters::AngleBracketed { + args: GenericArgs::AngleBracketed { lifetimes: Vec::new(), types: Vec::new(), bindings: Vec::new(), @@ -4365,7 +4428,7 @@ where F: Fn(DefId) -> Def { def: def_ctor(def_id), segments: hir::HirVec::from_vec(apb.names.iter().map(|s| hir::PathSegment { name: ast::Name::intern(&s), - parameters: None, + args: None, infer_types: false, }).collect()) } @@ -4388,8 +4451,8 @@ struct RegionDeps<'tcx> { #[derive(Eq, PartialEq, Hash, Debug)] enum SimpleBound { - RegionBound(Lifetime), - TraitBound(Vec, Vec, Vec, hir::TraitBoundModifier) + TraitBound(Vec, Vec, Vec, hir::TraitBoundModifier), + Outlives(Lifetime), } enum AutoTraitResult { @@ -4407,11 +4470,11 @@ impl AutoTraitResult { } } -impl From for SimpleBound { - fn from(bound: TyParamBound) -> Self { +impl From for SimpleBound { + fn from(bound: GenericBound) -> Self { match bound.clone() { - TyParamBound::RegionBound(l) => SimpleBound::RegionBound(l), - TyParamBound::TraitBound(t, mod_) => match t.trait_ { + GenericBound::Outlives(l) => SimpleBound::Outlives(l), + GenericBound::TraitBound(t, mod_) => match t.trait_ { Type::ResolvedPath { path, typarams, .. } => { SimpleBound::TraitBound(path.segments, typarams diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index b7767606a6aa4..30a55bf0d1809 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -27,7 +27,7 @@ use std::collections::BTreeMap; use rustc::hir::def_id::DefId; use rustc::ty; -use clean::PathParameters as PP; +use clean::GenericArgs as PP; use clean::WherePredicate as WP; use clean; use core::DocContext; @@ -83,8 +83,8 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec) -> Vec { }; !bounds.iter_mut().any(|b| { let trait_ref = match *b { - clean::TraitBound(ref mut tr, _) => tr, - clean::RegionBound(..) => return false, + clean::GenericBound::TraitBound(ref mut tr, _) => tr, + clean::GenericBound::Outlives(..) => return false, }; let (did, path) = match trait_ref.trait_ { clean::ResolvedPath { did, ref mut path, ..} => (did, path), @@ -97,7 +97,7 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec) -> Vec { return false } let last = path.segments.last_mut().unwrap(); - match last.params { + match last.args { PP::AngleBracketed { ref mut bindings, .. } => { bindings.push(clean::TypeBinding { name: name.clone(), @@ -135,14 +135,19 @@ pub fn where_clauses(cx: &DocContext, clauses: Vec) -> Vec { clauses } -pub fn ty_params(mut params: Vec) -> Vec { +pub fn ty_params(mut params: Vec) -> Vec { for param in &mut params { - param.bounds = ty_bounds(mem::replace(&mut param.bounds, Vec::new())); + match param.kind { + clean::GenericParamDefKind::Type { ref mut bounds, .. } => { + *bounds = ty_bounds(mem::replace(bounds, Vec::new())); + } + _ => panic!("expected only type parameters"), + } } params } -fn ty_bounds(bounds: Vec) -> Vec { +fn ty_bounds(bounds: Vec) -> Vec { bounds } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index e858f10860b41..53ebb3a12f527 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -77,7 +77,7 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> { /// Table node id of lifetime parameter definition -> substituted lifetime pub lt_substs: RefCell>, /// Table DefId of `impl Trait` in argument position -> bounds - pub impl_trait_bounds: RefCell>>, + pub impl_trait_bounds: RefCell>>, pub send_trait: Option, pub fake_def_ids: RefCell>, pub all_fake_def_ids: RefCell>, diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index f85a70a6d401f..16d14bc56d695 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -201,7 +201,7 @@ pub struct Trait { pub name: Name, pub items: hir::HirVec, pub generics: hir::Generics, - pub bounds: hir::HirVec, + pub bounds: hir::HirVec, pub attrs: hir::HirVec, pub id: ast::NodeId, pub whence: Span, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 40dcd6e891fe8..3d360f2f344b6 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -46,7 +46,7 @@ pub struct MutableSpace(pub clean::Mutability); #[derive(Copy, Clone)] pub struct RawMutableSpace(pub clean::Mutability); /// Wrapper struct for emitting type parameter bounds. -pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]); +pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]); /// Wrapper struct for emitting a comma-separated list of items pub struct CommaSep<'a, T: 'a>(pub &'a [T]); pub struct AbiSpace(pub Abi); @@ -104,9 +104,9 @@ impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> { } } -impl<'a> fmt::Display for TyParamBounds<'a> { +impl<'a> fmt::Display for GenericBounds<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let &TyParamBounds(bounds) = self; + let &GenericBounds(bounds) = self; for (i, bound) in bounds.iter().enumerate() { if i > 0 { f.write_str(" + ")?; @@ -119,20 +119,20 @@ impl<'a> fmt::Display for TyParamBounds<'a> { impl fmt::Display for clean::GenericParamDef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - clean::GenericParamDef::Lifetime(ref lp) => write!(f, "{}", lp), - clean::GenericParamDef::Type(ref tp) => { - f.write_str(&tp.name)?; + match self.kind { + clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name), + clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => { + f.write_str(&self.name)?; - if !tp.bounds.is_empty() { + if !bounds.is_empty() { if f.alternate() { - write!(f, ": {:#}", TyParamBounds(&tp.bounds))?; + write!(f, ": {:#}", GenericBounds(bounds))?; } else { - write!(f, ": {}", TyParamBounds(&tp.bounds))?; + write!(f, ": {}", GenericBounds(bounds))?; } } - if let Some(ref ty) = tp.default { + if let Some(ref ty) = default { if f.alternate() { write!(f, " = {:#}", ty)?; } else { @@ -190,9 +190,9 @@ impl<'a> fmt::Display for WhereClause<'a> { &clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => { let bounds = bounds; if f.alternate() { - clause.push_str(&format!("{:#}: {:#}", ty, TyParamBounds(bounds))); + clause.push_str(&format!("{:#}: {:#}", ty, GenericBounds(bounds))); } else { - clause.push_str(&format!("{}: {}", ty, TyParamBounds(bounds))); + clause.push_str(&format!("{}: {}", ty, GenericBounds(bounds))); } } &clean::WherePredicate::RegionPredicate { ref lifetime, @@ -267,13 +267,13 @@ impl fmt::Display for clean::PolyTrait { } } -impl fmt::Display for clean::TyParamBound { +impl fmt::Display for clean::GenericBound { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - clean::RegionBound(ref lt) => { + clean::GenericBound::Outlives(ref lt) => { write!(f, "{}", *lt) } - clean::TraitBound(ref ty, modifier) => { + clean::GenericBound::TraitBound(ref ty, modifier) => { let modifier_str = match modifier { hir::TraitBoundModifier::None => "", hir::TraitBoundModifier::Maybe => "?", @@ -288,10 +288,10 @@ impl fmt::Display for clean::TyParamBound { } } -impl fmt::Display for clean::PathParameters { +impl fmt::Display for clean::GenericArgs { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - clean::PathParameters::AngleBracketed { + clean::GenericArgs::AngleBracketed { ref lifetimes, ref types, ref bindings } => { if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() { @@ -337,7 +337,7 @@ impl fmt::Display for clean::PathParameters { } } } - clean::PathParameters::Parenthesized { ref inputs, ref output } => { + clean::GenericArgs::Parenthesized { ref inputs, ref output } => { f.write_str("(")?; let mut comma = false; for ty in inputs { @@ -369,9 +369,9 @@ impl fmt::Display for clean::PathSegment { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&self.name)?; if f.alternate() { - write!(f, "{:#}", self.params) + write!(f, "{:#}", self.args) } else { - write!(f, "{}", self.params) + write!(f, "{}", self.args) } } } @@ -447,7 +447,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path, } } if w.alternate() { - write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.params)?; + write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.args)?; } else { let path = if use_absolute { match href(did) { @@ -461,7 +461,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path, } else { format!("{}", HRef::new(did, &last.name)) }; - write!(w, "{}{}", path, last.params)?; + write!(w, "{}{}", path, last.args)?; } Ok(()) } @@ -512,7 +512,7 @@ fn primitive_link(f: &mut fmt::Formatter, /// Helper to render type parameters fn tybounds(w: &mut fmt::Formatter, - typarams: &Option>) -> fmt::Result { + typarams: &Option>) -> fmt::Result { match *typarams { Some(ref params) => { for param in params { @@ -667,7 +667,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: } } clean::ImplTrait(ref bounds) => { - write!(f, "impl {}", TyParamBounds(bounds)) + write!(f, "impl {}", GenericBounds(bounds)) } clean::QPath { ref name, ref self_type, ref trait_ } => { let should_show_cast = match *trait_ { @@ -757,7 +757,7 @@ fn fmt_impl(i: &clean::Impl, clean::ResolvedPath { typarams: None, ref path, is_generic: false, .. } => { let last = path.segments.last().unwrap(); fmt::Display::fmt(&last.name, f)?; - fmt::Display::fmt(&last.params, f)?; + fmt::Display::fmt(&last.args, f)?; } _ => unreachable!(), } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 5c2ec2058ee9d..180591b353260 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -69,7 +69,7 @@ use doctree; use fold::DocFolder; use html::escape::Escape; use html::format::{ConstnessSpace}; -use html::format::{TyParamBounds, WhereClause, href, AbiSpace}; +use html::format::{GenericBounds, WhereClause, href, AbiSpace}; use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace}; use html::format::fmt_impl_for_trait_page; use html::item_type::ItemType; @@ -1453,11 +1453,11 @@ impl DocFolder for Cache { impl<'a> Cache { fn generics(&mut self, generics: &clean::Generics) { for param in &generics.params { - match *param { - clean::GenericParamDef::Type(ref typ) => { - self.typarams.insert(typ.did, typ.name.clone()); + match param.kind { + clean::GenericParamDefKind::Lifetime => {} + clean::GenericParamDefKind::Type { did, .. } => { + self.typarams.insert(did, param.name.clone()); } - clean::GenericParamDef::Lifetime(_) => {} } } } @@ -2960,14 +2960,14 @@ fn assoc_const(w: &mut fmt::Formatter, } fn assoc_type(w: &mut W, it: &clean::Item, - bounds: &Vec, + bounds: &Vec, default: Option<&clean::Type>, link: AssocItemLink) -> fmt::Result { write!(w, "type {}", naive_assoc_href(it, link), it.name.as_ref().unwrap())?; if !bounds.is_empty() { - write!(w, ": {}", TyParamBounds(bounds))? + write!(w, ": {}", GenericBounds(bounds))? } if let Some(default) = default { write!(w, " = {}", default)?; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 97c84d8348f7c..8e691049d3395 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -18,6 +18,7 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(fs_read_write)] +#![feature(iterator_find_map)] #![feature(set_stdio)] #![feature(slice_sort_by_cached_key)] #![feature(test)] diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 76fa463a63134..c6de2c4da39cf 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -10,9 +10,8 @@ // The Rust abstract syntax tree. -pub use self::TyParamBound::*; pub use self::UnsafeSource::*; -pub use self::PathParameters::*; +pub use self::GenericArgs::*; pub use symbol::{Ident, Symbol as Name}; pub use util::ThinVec; pub use util::parser::ExprPrecedence; @@ -58,14 +57,6 @@ impl fmt::Debug for Lifetime { } } -/// A lifetime definition, e.g. `'a: 'b+'c+'d` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct LifetimeDef { - pub attrs: ThinVec, - pub lifetime: Lifetime, - pub bounds: Vec -} - /// A "Path" is essentially Rust's notion of a name. /// /// It's represented as a sequence of identifiers, @@ -135,30 +126,30 @@ pub struct PathSegment { /// `Some` means that parameter list is supplied (`Path`) /// but it can be empty (`Path<>`). /// `P` is used as a size optimization for the common case with no parameters. - pub parameters: Option>, + pub args: Option>, } impl PathSegment { pub fn from_ident(ident: Ident) -> Self { - PathSegment { ident, parameters: None } + PathSegment { ident, args: None } } pub fn crate_root(span: Span) -> Self { PathSegment::from_ident(Ident::new(keywords::CrateRoot.name(), span)) } } -/// Parameters of a path segment. +/// Arguments of a path segment. /// /// E.g. `` as in `Foo` or `(A, B)` as in `Foo(A, B)` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum PathParameters { +pub enum GenericArgs { /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>` - AngleBracketed(AngleBracketedParameterData), + AngleBracketed(AngleBracketedArgs), /// The `(A,B)` and `C` in `Foo(A,B) -> C` - Parenthesized(ParenthesizedParameterData), + Parenthesized(ParenthesisedArgs), } -impl PathParameters { +impl GenericArgs { pub fn span(&self) -> Span { match *self { AngleBracketed(ref data) => data.span, @@ -167,36 +158,40 @@ impl PathParameters { } } +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum GenericArg { + Lifetime(Lifetime), + Type(P), +} + /// A path like `Foo<'a, T>` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)] -pub struct AngleBracketedParameterData { +pub struct AngleBracketedArgs { /// Overall span pub span: Span, - /// The lifetime parameters for this path segment. - pub lifetimes: Vec, - /// The type parameters for this path segment, if present. - pub types: Vec>, + /// The arguments for this path segment. + pub args: Vec, /// Bindings (equality constraints) on associated types, if present. /// /// E.g., `Foo`. pub bindings: Vec, } -impl Into>> for AngleBracketedParameterData { - fn into(self) -> Option> { - Some(P(PathParameters::AngleBracketed(self))) +impl Into>> for AngleBracketedArgs { + fn into(self) -> Option> { + Some(P(GenericArgs::AngleBracketed(self))) } } -impl Into>> for ParenthesizedParameterData { - fn into(self) -> Option> { - Some(P(PathParameters::Parenthesized(self))) +impl Into>> for ParenthesisedArgs { + fn into(self) -> Option> { + Some(P(GenericArgs::Parenthesized(self))) } } /// A path like `Foo(A,B) -> C` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct ParenthesizedParameterData { +pub struct ParenthesisedArgs { /// Overall span pub span: Span, @@ -273,64 +268,52 @@ pub const CRATE_NODE_ID: NodeId = NodeId(0); /// small, positive ids. pub const DUMMY_NODE_ID: NodeId = NodeId(!0); +/// A modifier on a bound, currently this is only used for `?Sized`, where the +/// modifier is `Maybe`. Negative bounds should also be handled here. +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum TraitBoundModifier { + None, + Maybe, +} + /// The AST represents all type param bounds as types. /// typeck::collect::compute_bounds matches these against /// the "special" built-in traits (see middle::lang_items) and /// detects Copy, Send and Sync. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TyParamBound { - TraitTyParamBound(PolyTraitRef, TraitBoundModifier), - RegionTyParamBound(Lifetime) +pub enum GenericBound { + Trait(PolyTraitRef, TraitBoundModifier), + Outlives(Lifetime) } -impl TyParamBound { +impl GenericBound { pub fn span(&self) -> Span { match self { - &TraitTyParamBound(ref t, ..) => t.span, - &RegionTyParamBound(ref l) => l.ident.span, + &GenericBound::Trait(ref t, ..) => t.span, + &GenericBound::Outlives(ref l) => l.ident.span, } } } -/// A modifier on a bound, currently this is only used for `?Sized`, where the -/// modifier is `Maybe`. Negative bounds should also be handled here. -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TraitBoundModifier { - None, - Maybe, -} - -pub type TyParamBounds = Vec; +pub type GenericBounds = Vec; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct TyParam { - pub attrs: ThinVec, - pub ident: Ident, - pub id: NodeId, - pub bounds: TyParamBounds, - pub default: Option>, +pub enum GenericParamKind { + /// A lifetime definition, e.g. `'a: 'b+'c+'d`. + Lifetime, + Type { + default: Option>, + } } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum GenericParam { - Lifetime(LifetimeDef), - Type(TyParam), -} - -impl GenericParam { - pub fn is_lifetime_param(&self) -> bool { - match *self { - GenericParam::Lifetime(_) => true, - _ => false, - } - } +pub struct GenericParam { + pub id: NodeId, + pub ident: Ident, + pub attrs: ThinVec, + pub bounds: GenericBounds, - pub fn is_type_param(&self) -> bool { - match *self { - GenericParam::Type(_) => true, - _ => false, - } - } + pub kind: GenericParamKind, } /// Represents lifetime, type and const parameters attached to a declaration of @@ -342,31 +325,6 @@ pub struct Generics { pub span: Span, } -impl Generics { - pub fn is_lt_parameterized(&self) -> bool { - self.params.iter().any(|param| param.is_lifetime_param()) - } - - pub fn is_type_parameterized(&self) -> bool { - self.params.iter().any(|param| param.is_type_param()) - } - - pub fn is_parameterized(&self) -> bool { - !self.params.is_empty() - } - - pub fn span_for_name(&self, name: &str) -> Option { - for param in &self.params { - if let GenericParam::Type(ref t) = *param { - if t.ident.name == name { - return Some(t.ident.span); - } - } - } - None - } -} - impl Default for Generics { /// Creates an instance of `Generics`. fn default() -> Generics { @@ -422,7 +380,7 @@ pub struct WhereBoundPredicate { /// The type being bounded pub bounded_ty: P, /// Trait and lifetime bounds (`Clone+Send+'static`) - pub bounds: TyParamBounds, + pub bounds: GenericBounds, } /// A lifetime predicate. @@ -432,7 +390,7 @@ pub struct WhereBoundPredicate { pub struct WhereRegionPredicate { pub span: Span, pub lifetime: Lifetime, - pub bounds: Vec, + pub bounds: GenericBounds, } /// An equality predicate (unsupported). @@ -968,11 +926,11 @@ impl Expr { } } - fn to_bound(&self) -> Option { + fn to_bound(&self) -> Option { match &self.node { ExprKind::Path(None, path) => - Some(TraitTyParamBound(PolyTraitRef::new(Vec::new(), path.clone(), self.span), - TraitBoundModifier::None)), + Some(GenericBound::Trait(PolyTraitRef::new(Vec::new(), path.clone(), self.span), + TraitBoundModifier::None)), _ => None, } } @@ -1393,7 +1351,7 @@ pub struct TraitItem { pub enum TraitItemKind { Const(P, Option>), Method(MethodSig, Option>), - Type(TyParamBounds, Option>), + Type(GenericBounds, Option>), Macro(Mac), } @@ -1578,10 +1536,10 @@ pub enum TyKind { Path(Option, Path), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. - TraitObject(TyParamBounds, TraitObjectSyntax), + TraitObject(GenericBounds, TraitObjectSyntax), /// An `impl Bound1 + Bound2 + Bound3` type /// where `Bound` is a trait or a lifetime. - ImplTrait(TyParamBounds), + ImplTrait(GenericBounds), /// No-op; kept solely so that we can pretty-print faithfully Paren(P), /// Unused for now @@ -2102,11 +2060,11 @@ pub enum ItemKind { /// A Trait declaration (`trait` or `pub trait`). /// /// E.g. `trait Foo { .. }`, `trait Foo { .. }` or `auto trait Foo {}` - Trait(IsAuto, Unsafety, Generics, TyParamBounds, Vec), + Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec), /// Trait alias /// /// E.g. `trait Foo = Bar + Quux;` - TraitAlias(Generics, TyParamBounds), + TraitAlias(Generics, GenericBounds), /// An implementation. /// /// E.g. `impl Foo { .. }` or `impl Trait for Foo { .. }` diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 2389ed799cfcc..ded493fe3958c 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -1446,17 +1446,12 @@ impl HasAttrs for Stmt { impl HasAttrs for GenericParam { fn attrs(&self) -> &[ast::Attribute] { - match self { - GenericParam::Lifetime(lifetime) => lifetime.attrs(), - GenericParam::Type(ty) => ty.attrs(), - } + &self.attrs } - fn map_attrs) -> Vec>(self, f: F) -> Self { - match self { - GenericParam::Lifetime(lifetime) => GenericParam::Lifetime(lifetime.map_attrs(f)), - GenericParam::Type(ty) => GenericParam::Type(ty.map_attrs(f)), - } + fn map_attrs) -> Vec>(mut self, f: F) -> Self { + self.attrs = self.attrs.map_attrs(f); + self } } @@ -1479,5 +1474,5 @@ macro_rules! derive_has_attrs { derive_has_attrs! { Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm, - ast::Field, ast::FieldPat, ast::Variant_, ast::LifetimeDef, ast::TyParam + ast::Field, ast::FieldPat, ast::Variant_ } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 4a6f06dcc17ba..9044cab05d667 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -30,10 +30,9 @@ pub trait AstBuilder { fn path_global(&self, span: Span, strs: Vec ) -> ast::Path; fn path_all(&self, sp: Span, global: bool, - idents: Vec , - lifetimes: Vec, - types: Vec>, - bindings: Vec ) + idents: Vec, + args: Vec, + bindings: Vec) -> ast::Path; fn qpath(&self, self_type: P, @@ -43,8 +42,7 @@ pub trait AstBuilder { fn qpath_all(&self, self_type: P, trait_path: ast::Path, ident: ast::Ident, - lifetimes: Vec, - types: Vec>, + args: Vec, bindings: Vec) -> (ast::QSelf, ast::Path); @@ -70,19 +68,19 @@ pub trait AstBuilder { span: Span, id: ast::Ident, attrs: Vec, - bounds: ast::TyParamBounds, - default: Option>) -> ast::TyParam; + bounds: ast::GenericBounds, + default: Option>) -> ast::GenericParam; fn trait_ref(&self, path: ast::Path) -> ast::TraitRef; fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef; - fn typarambound(&self, path: ast::Path) -> ast::TyParamBound; + fn trait_bound(&self, path: ast::Path) -> ast::GenericBound; fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime; fn lifetime_def(&self, span: Span, ident: ast::Ident, attrs: Vec, - bounds: Vec) - -> ast::LifetimeDef; + bounds: ast::GenericBounds) + -> ast::GenericParam; // statements fn stmt_expr(&self, expr: P) -> ast::Stmt; @@ -304,34 +302,33 @@ pub trait AstBuilder { impl<'a> AstBuilder for ExtCtxt<'a> { fn path(&self, span: Span, strs: Vec ) -> ast::Path { - self.path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new()) + self.path_all(span, false, strs, vec![], vec![]) } fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path { self.path(span, vec![id]) } fn path_global(&self, span: Span, strs: Vec ) -> ast::Path { - self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new()) + self.path_all(span, true, strs, vec![], vec![]) } fn path_all(&self, span: Span, global: bool, mut idents: Vec , - lifetimes: Vec, - types: Vec>, + args: Vec, bindings: Vec ) -> ast::Path { let last_ident = idents.pop().unwrap(); - let mut segments: Vec = Vec::new(); + let mut segments: Vec = vec![]; segments.extend(idents.into_iter().map(|ident| { ast::PathSegment::from_ident(ident.with_span_pos(span)) })); - let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() { - ast::AngleBracketedParameterData { lifetimes, types, bindings, span }.into() + let args = if !args.is_empty() || !bindings.is_empty() { + ast::AngleBracketedArgs { args, bindings, span }.into() } else { None }; - segments.push(ast::PathSegment { ident: last_ident.with_span_pos(span), parameters }); + segments.push(ast::PathSegment { ident: last_ident.with_span_pos(span), args }); let mut path = ast::Path { span, segments }; if global { if let Some(seg) = path.make_root() { @@ -349,7 +346,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { trait_path: ast::Path, ident: ast::Ident) -> (ast::QSelf, ast::Path) { - self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![]) + self.qpath_all(self_type, trait_path, ident, vec![], vec![]) } /// Constructs a qualified path. @@ -359,17 +356,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self_type: P, trait_path: ast::Path, ident: ast::Ident, - lifetimes: Vec, - types: Vec>, + args: Vec, bindings: Vec) -> (ast::QSelf, ast::Path) { let mut path = trait_path; - let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() { - ast::AngleBracketedParameterData { lifetimes, types, bindings, span: ident.span }.into() + let args = if !args.is_empty() || !bindings.is_empty() { + ast::AngleBracketedArgs { args, bindings, span: ident.span }.into() } else { None }; - path.segments.push(ast::PathSegment { ident, parameters }); + path.segments.push(ast::PathSegment { ident, args }); (ast::QSelf { ty: self_type, @@ -428,8 +424,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.path_all(DUMMY_SP, true, self.std_path(&["option", "Option"]), - Vec::new(), - vec![ ty ], + vec![ast::GenericArg::Type(ty)], Vec::new())) } @@ -441,14 +436,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> { span: Span, ident: ast::Ident, attrs: Vec, - bounds: ast::TyParamBounds, - default: Option>) -> ast::TyParam { - ast::TyParam { + bounds: ast::GenericBounds, + default: Option>) -> ast::GenericParam { + ast::GenericParam { ident: ident.with_span_pos(span), id: ast::DUMMY_NODE_ID, attrs: attrs.into(), bounds, - default, + kind: ast::GenericParamKind::Type { + default, + } } } @@ -467,8 +464,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } } - fn typarambound(&self, path: ast::Path) -> ast::TyParamBound { - ast::TraitTyParamBound(self.poly_trait_ref(path.span, path), ast::TraitBoundModifier::None) + fn trait_bound(&self, path: ast::Path) -> ast::GenericBound { + ast::GenericBound::Trait(self.poly_trait_ref(path.span, path), + ast::TraitBoundModifier::None) } fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime { @@ -479,12 +477,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> { span: Span, ident: ast::Ident, attrs: Vec, - bounds: Vec) - -> ast::LifetimeDef { - ast::LifetimeDef { + bounds: ast::GenericBounds) + -> ast::GenericParam { + let lifetime = self.lifetime(span, ident); + ast::GenericParam { + ident: lifetime.ident, + id: lifetime.id, attrs: attrs.into(), - lifetime: self.lifetime(span, ident), bounds, + kind: ast::GenericParamKind::Lifetime, } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index a2ea6a214841e..be4cf197be4eb 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1797,7 +1797,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, associated_type_defaults, ti.span, "associated type defaults are unstable"); } - if ti.generics.is_parameterized() { + if !ti.generics.params.is_empty() { gate_feature_post!(&self, generic_associated_types, ti.span, "generic associated types are unstable"); } @@ -1824,7 +1824,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable"); } } - ast::ImplItemKind::Type(_) if ii.generics.is_parameterized() => { + ast::ImplItemKind::Type(_) if !ii.generics.params.is_empty() => { gate_feature_post!(&self, generic_associated_types, ii.span, "generic associated types are unstable"); } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 8544ef330dc33..93248fe3bfab0 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -132,10 +132,21 @@ pub trait Folder : Sized { noop_fold_exprs(es, self) } + fn fold_generic_arg(&mut self, arg: GenericArg) -> GenericArg { + match arg { + GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.fold_lifetime(lt)), + GenericArg::Type(ty) => GenericArg::Type(self.fold_ty(ty)), + } + } + fn fold_ty(&mut self, t: P) -> P { noop_fold_ty(t, self) } + fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime { + noop_fold_lifetime(l, self) + } + fn fold_ty_binding(&mut self, t: TypeBinding) -> TypeBinding { noop_fold_ty_binding(t, self) } @@ -172,18 +183,18 @@ pub trait Folder : Sized { noop_fold_qpath(qs, p, self) } - fn fold_path_parameters(&mut self, p: PathParameters) -> PathParameters { - noop_fold_path_parameters(p, self) + fn fold_generic_args(&mut self, p: GenericArgs) -> GenericArgs { + noop_fold_generic_args(p, self) } - fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedParameterData) - -> AngleBracketedParameterData + fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedArgs) + -> AngleBracketedArgs { noop_fold_angle_bracketed_parameter_data(p, self) } - fn fold_parenthesized_parameter_data(&mut self, p: ParenthesizedParameterData) - -> ParenthesizedParameterData + fn fold_parenthesized_parameter_data(&mut self, p: ParenthesisedArgs) + -> ParenthesisedArgs { noop_fold_parenthesized_parameter_data(p, self) } @@ -233,10 +244,6 @@ pub trait Folder : Sized { noop_fold_variant_data(vdata, self) } - fn fold_ty_param(&mut self, tp: TyParam) -> TyParam { - noop_fold_ty_param(tp, self) - } - fn fold_generic_param(&mut self, param: GenericParam) -> GenericParam { noop_fold_generic_param(param, self) } @@ -261,18 +268,16 @@ pub trait Folder : Sized { noop_fold_interpolated(nt, self) } - fn fold_opt_bounds(&mut self, b: Option) - -> Option { + fn fold_opt_bounds(&mut self, b: Option) -> Option { noop_fold_opt_bounds(b, self) } - fn fold_bounds(&mut self, b: TyParamBounds) - -> TyParamBounds { + fn fold_bounds(&mut self, b: GenericBounds) -> GenericBounds { noop_fold_bounds(b, self) } - fn fold_ty_param_bound(&mut self, tpb: TyParamBound) -> TyParamBound { - noop_fold_ty_param_bound(tpb, self) + fn fold_param_bound(&mut self, tpb: GenericBound) -> GenericBound { + noop_fold_param_bound(tpb, self) } fn fold_mt(&mut self, mt: MutTy) -> MutTy { @@ -385,10 +390,10 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { TyKind::Typeof(fld.fold_anon_const(expr)) } TyKind::TraitObject(bounds, syntax) => { - TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b)), syntax) + TyKind::TraitObject(bounds.move_map(|b| fld.fold_param_bound(b)), syntax) } TyKind::ImplTrait(bounds) => { - TyKind::ImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b))) + TyKind::ImplTrait(bounds.move_map(|b| fld.fold_param_bound(b))) } TyKind::Mac(mac) => { TyKind::Mac(fld.fold_mac(mac)) @@ -433,9 +438,9 @@ pub fn noop_fold_usize(i: usize, _: &mut T) -> usize { pub fn noop_fold_path(Path { segments, span }: Path, fld: &mut T) -> Path { Path { - segments: segments.move_map(|PathSegment {ident, parameters}| PathSegment { + segments: segments.move_map(|PathSegment { ident, args }| PathSegment { ident: fld.fold_ident(ident), - parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))), + args: args.map(|args| args.map(|args| fld.fold_generic_args(args))), }), span: fld.new_span(span) } @@ -454,36 +459,40 @@ pub fn noop_fold_qpath(qself: Option, (qself, fld.fold_path(path)) } -pub fn noop_fold_path_parameters(path_parameters: PathParameters, fld: &mut T) - -> PathParameters +pub fn noop_fold_generic_args(generic_args: GenericArgs, fld: &mut T) -> GenericArgs { - match path_parameters { - PathParameters::AngleBracketed(data) => - PathParameters::AngleBracketed(fld.fold_angle_bracketed_parameter_data(data)), - PathParameters::Parenthesized(data) => - PathParameters::Parenthesized(fld.fold_parenthesized_parameter_data(data)), + match generic_args { + GenericArgs::AngleBracketed(data) => { + GenericArgs::AngleBracketed(fld.fold_angle_bracketed_parameter_data(data)) + } + GenericArgs::Parenthesized(data) => { + GenericArgs::Parenthesized(fld.fold_parenthesized_parameter_data(data)) + } } } -pub fn noop_fold_angle_bracketed_parameter_data(data: AngleBracketedParameterData, +pub fn noop_fold_angle_bracketed_parameter_data(data: AngleBracketedArgs, fld: &mut T) - -> AngleBracketedParameterData + -> AngleBracketedArgs { - let AngleBracketedParameterData { lifetimes, types, bindings, span } = data; - AngleBracketedParameterData { lifetimes: lifetimes.move_map(|l| noop_fold_lifetime(l, fld)), - types: types.move_map(|ty| fld.fold_ty(ty)), - bindings: bindings.move_map(|b| fld.fold_ty_binding(b)), - span: fld.new_span(span) } + let AngleBracketedArgs { args, bindings, span } = data; + AngleBracketedArgs { + args: args.move_map(|arg| fld.fold_generic_arg(arg)), + bindings: bindings.move_map(|b| fld.fold_ty_binding(b)), + span: fld.new_span(span) + } } -pub fn noop_fold_parenthesized_parameter_data(data: ParenthesizedParameterData, +pub fn noop_fold_parenthesized_parameter_data(data: ParenthesisedArgs, fld: &mut T) - -> ParenthesizedParameterData + -> ParenthesisedArgs { - let ParenthesizedParameterData { inputs, output, span } = data; - ParenthesizedParameterData { inputs: inputs.move_map(|ty| fld.fold_ty(ty)), - output: output.map(|ty| fld.fold_ty(ty)), - span: fld.new_span(span) } + let ParenthesisedArgs { inputs, output, span } = data; + ParenthesisedArgs { + inputs: inputs.move_map(|ty| fld.fold_ty(ty)), + output: output.map(|ty| fld.fold_ty(ty)), + span: fld.new_span(span) + } } pub fn noop_fold_local(l: P, fld: &mut T) -> P { @@ -667,47 +676,33 @@ pub fn noop_fold_fn_decl(decl: P, fld: &mut T) -> P { }) } -pub fn noop_fold_ty_param_bound(tpb: TyParamBound, fld: &mut T) - -> TyParamBound - where T: Folder { - match tpb { - TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier), - RegionTyParamBound(lifetime) => RegionTyParamBound(noop_fold_lifetime(lifetime, fld)), - } -} - -pub fn noop_fold_ty_param(tp: TyParam, fld: &mut T) -> TyParam { - let TyParam {attrs, id, ident, bounds, default} = tp; - let attrs: Vec<_> = attrs.into(); - TyParam { - attrs: attrs.into_iter() - .flat_map(|x| fld.fold_attribute(x).into_iter()) - .collect::>() - .into(), - id: fld.new_id(id), - ident: fld.fold_ident(ident), - bounds: fld.fold_bounds(bounds), - default: default.map(|x| fld.fold_ty(x)), +pub fn noop_fold_param_bound(pb: GenericBound, fld: &mut T) -> GenericBound where T: Folder { + match pb { + GenericBound::Trait(ty, modifier) => { + GenericBound::Trait(fld.fold_poly_trait_ref(ty), modifier) + } + GenericBound::Outlives(lifetime) => { + GenericBound::Outlives(noop_fold_lifetime(lifetime, fld)) + } } } pub fn noop_fold_generic_param(param: GenericParam, fld: &mut T) -> GenericParam { - match param { - GenericParam::Lifetime(l) => { - let attrs: Vec<_> = l.attrs.into(); - GenericParam::Lifetime(LifetimeDef { - attrs: attrs.into_iter() + let attrs: Vec<_> = param.attrs.into(); + GenericParam { + ident: fld.fold_ident(param.ident), + id: fld.new_id(param.id), + attrs: attrs.into_iter() .flat_map(|x| fld.fold_attribute(x).into_iter()) .collect::>() .into(), - lifetime: Lifetime { - id: fld.new_id(l.lifetime.id), - ident: fld.fold_ident(l.lifetime.ident), - }, - bounds: l.bounds.move_map(|l| noop_fold_lifetime(l, fld)), - }) + bounds: param.bounds.move_map(|l| noop_fold_param_bound(l, fld)), + kind: match param.kind { + GenericParamKind::Lifetime => GenericParamKind::Lifetime, + GenericParamKind::Type { default } => GenericParamKind::Type { + default: default.map(|ty| fld.fold_ty(ty)) + } } - GenericParam::Type(t) => GenericParam::Type(fld.fold_ty_param(t)), } } @@ -765,7 +760,7 @@ pub fn noop_fold_where_predicate( ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { bound_generic_params: fld.fold_generic_params(bound_generic_params), bounded_ty: fld.fold_ty(bounded_ty), - bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)), + bounds: bounds.move_map(|x| fld.fold_param_bound(x)), span: fld.new_span(span) }) } @@ -775,7 +770,7 @@ pub fn noop_fold_where_predicate( ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { span: fld.new_span(span), lifetime: noop_fold_lifetime(lifetime, fld), - bounds: bounds.move_map(|bound| noop_fold_lifetime(bound, fld)) + bounds: bounds.move_map(|bound| noop_fold_param_bound(bound, fld)) }) } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, @@ -854,14 +849,14 @@ pub fn noop_fold_mt(MutTy {ty, mutbl}: MutTy, folder: &mut T) -> MutT } } -pub fn noop_fold_opt_bounds(b: Option, folder: &mut T) - -> Option { +pub fn noop_fold_opt_bounds(b: Option, folder: &mut T) + -> Option { b.map(|bounds| folder.fold_bounds(bounds)) } -fn noop_fold_bounds(bounds: TyParamBounds, folder: &mut T) - -> TyParamBounds { - bounds.move_map(|bound| folder.fold_ty_param_bound(bound)) +fn noop_fold_bounds(bounds: GenericBounds, folder: &mut T) + -> GenericBounds { + bounds.move_map(|bound| folder.fold_param_bound(bound)) } pub fn noop_fold_block(b: P, folder: &mut T) -> P { @@ -1184,8 +1179,8 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::MethodCall( PathSegment { ident: folder.fold_ident(seg.ident), - parameters: seg.parameters.map(|ps| { - ps.map(|ps| folder.fold_path_parameters(ps)) + args: seg.args.map(|args| { + args.map(|args| folder.fold_generic_args(args)) }), }, folder.fold_exprs(args)) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1735951da2f34..6f78ae9ebca5d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -9,8 +9,8 @@ // except according to those terms. use rustc_target::spec::abi::{self, Abi}; -use ast::{AngleBracketedParameterData, ParenthesizedParameterData, AttrStyle, BareFnTy}; -use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; +use ast::{AngleBracketedArgs, ParenthesisedArgs, AttrStyle, BareFnTy}; +use ast::{GenericBound, TraitBoundModifier}; use ast::Unsafety; use ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind}; use ast::Block; @@ -21,9 +21,10 @@ use ast::EnumDef; use ast::{Expr, ExprKind, RangeLimits}; use ast::{Field, FnDecl}; use ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; -use ast::GenericParam; +use ast::{GenericParam, GenericParamKind}; +use ast::GenericArg; use ast::{Ident, ImplItem, IsAuto, Item, ItemKind}; -use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind}; +use ast::{Label, Lifetime, Lit, LitKind}; use ast::Local; use ast::MacStmtStyle; use ast::{Mac, Mac_, MacDelimiter}; @@ -35,7 +36,7 @@ use ast::{VariantData, StructField}; use ast::StrStyle; use ast::SelfKind; use ast::{TraitItem, TraitRef, TraitObjectSyntax}; -use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; +use ast::{Ty, TyKind, TypeBinding, GenericBounds}; use ast::{Visibility, VisibilityKind, WhereClause, CrateSugar}; use ast::{UseTree, UseTreeKind}; use ast::{BinOpKind, UnOp}; @@ -1245,8 +1246,7 @@ impl<'a> Parser<'a> { } /// parse a TyKind::BareFn type: - fn parse_ty_bare_fn(&mut self, generic_params: Vec) - -> PResult<'a, TyKind> { + fn parse_ty_bare_fn(&mut self, generic_params: Vec) -> PResult<'a, TyKind> { /* [unsafe] [extern "ABI"] fn (S) -> T @@ -1311,9 +1311,7 @@ impl<'a> Parser<'a> { let lo = self.span; let (name, node, generics) = if self.eat_keyword(keywords::Type) { - let (generics, TyParam {ident, bounds, default, ..}) = - self.parse_trait_item_assoc_ty(vec![])?; - (ident, TraitItemKind::Type(bounds, default), generics) + self.parse_trait_item_assoc_ty()? } else if self.is_const_item() { self.expect_keyword(keywords::Const)?; let ident = self.parse_ident()?; @@ -1446,7 +1444,7 @@ impl<'a> Parser<'a> { TyKind::TraitObject(ref bounds, TraitObjectSyntax::None) if maybe_bounds && bounds.len() == 1 && !trailing_plus => { let path = match bounds[0] { - TraitTyParamBound(ref pt, ..) => pt.trait_ref.path.clone(), + GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(), _ => self.bug("unexpected lifetime bound"), }; self.parse_remaining_bounds(Vec::new(), path, lo, true)? @@ -1511,7 +1509,7 @@ impl<'a> Parser<'a> { } } else if self.eat_keyword(keywords::Impl) { // Always parse bounds greedily for better error recovery. - let bounds = self.parse_ty_param_bounds()?; + let bounds = self.parse_generic_bounds()?; impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; TyKind::ImplTrait(bounds) } else if self.check_keyword(keywords::Dyn) && @@ -1519,13 +1517,13 @@ impl<'a> Parser<'a> { !can_continue_type_after_non_fn_ident(t)) { self.bump(); // `dyn` // Always parse bounds greedily for better error recovery. - let bounds = self.parse_ty_param_bounds()?; + let bounds = self.parse_generic_bounds()?; impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn) } else if self.check(&token::Question) || self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus()) { // Bound list (trait object type) - TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?, + TyKind::TraitObject(self.parse_generic_bounds_common(allow_plus)?, TraitObjectSyntax::None) } else if self.eat_lt() { // Qualified path @@ -1568,10 +1566,10 @@ impl<'a> Parser<'a> { fn parse_remaining_bounds(&mut self, generic_params: Vec, path: ast::Path, lo: Span, parse_plus: bool) -> PResult<'a, TyKind> { let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span)); - let mut bounds = vec![TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)]; + let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)]; if parse_plus { self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded - bounds.append(&mut self.parse_ty_param_bounds()?); + bounds.append(&mut self.parse_generic_bounds()?); } Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) } @@ -1596,7 +1594,7 @@ impl<'a> Parser<'a> { } self.bump(); // `+` - let bounds = self.parse_ty_param_bounds()?; + let bounds = self.parse_generic_bounds()?; let sum_span = ty.span.to(self.prev_span); let mut err = struct_span_err!(self.sess.span_diagnostic, sum_span, E0178, @@ -1612,7 +1610,7 @@ impl<'a> Parser<'a> { s.print_mutability(mut_ty.mutbl)?; s.popen()?; s.print_type(&mut_ty.ty)?; - s.print_bounds(" +", &bounds)?; + s.print_type_bounds(" +", &bounds)?; s.pclose() }); err.span_suggestion_with_applicability( @@ -1894,7 +1892,7 @@ impl<'a> Parser<'a> { -> PResult<'a, ast::Path> { maybe_whole!(self, NtPath, |path| { if style == PathStyle::Mod && - path.segments.iter().any(|segment| segment.parameters.is_some()) { + path.segments.iter().any(|segment| segment.args.is_some()) { self.diagnostic().span_err(path.span, "unexpected generic arguments in path"); } path @@ -1969,12 +1967,12 @@ impl<'a> Parser<'a> { .span_label(self.prev_span, "try removing `::`").emit(); } - let parameters = if self.eat_lt() { + let args = if self.eat_lt() { // `<'a, T, A = U>` - let (lifetimes, types, bindings) = self.parse_generic_args()?; + let (args, bindings) = self.parse_generic_args()?; self.expect_gt()?; let span = lo.to(self.prev_span); - AngleBracketedParameterData { lifetimes, types, bindings, span }.into() + AngleBracketedArgs { args, bindings, span }.into() } else { // `(T, U) -> R` self.bump(); // `(` @@ -1990,10 +1988,10 @@ impl<'a> Parser<'a> { None }; let span = lo.to(self.prev_span); - ParenthesizedParameterData { inputs, output, span }.into() + ParenthesisedArgs { inputs, output, span }.into() }; - PathSegment { ident, parameters } + PathSegment { ident, args } } else { // Generic arguments are not found. PathSegment::from_ident(ident) @@ -2543,8 +2541,8 @@ impl<'a> Parser<'a> { } _ => { // Field access `expr.f` - if let Some(parameters) = segment.parameters { - self.span_err(parameters.span(), + if let Some(args) = segment.args { + self.span_err(args.span(), "field expressions may not have generic arguments"); } @@ -4737,7 +4735,7 @@ impl<'a> Parser<'a> { // LT_BOUND = LIFETIME (e.g. `'a`) // TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) // TY_BOUND_NOPAREN = [?] [for] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`) - fn parse_ty_param_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, TyParamBounds> { + fn parse_generic_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, GenericBounds> { let mut bounds = Vec::new(); loop { // This needs to be syncronized with `Token::can_begin_bound`. @@ -4754,7 +4752,7 @@ impl<'a> Parser<'a> { self.span_err(question_span, "`?` may only modify trait bounds, not lifetime bounds"); } - bounds.push(RegionTyParamBound(self.expect_lifetime())); + bounds.push(GenericBound::Outlives(self.expect_lifetime())); if has_parens { self.expect(&token::CloseDelim(token::Paren))?; self.span_err(self.prev_span, @@ -4772,7 +4770,7 @@ impl<'a> Parser<'a> { } else { TraitBoundModifier::None }; - bounds.push(TraitTyParamBound(poly_trait, modifier)); + bounds.push(GenericBound::Trait(poly_trait, modifier)); } } else { break @@ -4786,16 +4784,16 @@ impl<'a> Parser<'a> { return Ok(bounds); } - fn parse_ty_param_bounds(&mut self) -> PResult<'a, TyParamBounds> { - self.parse_ty_param_bounds_common(true) + fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> { + self.parse_generic_bounds_common(true) } // Parse bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. // BOUND = LT_BOUND (e.g. `'a`) - fn parse_lt_param_bounds(&mut self) -> Vec { + fn parse_lt_param_bounds(&mut self) -> GenericBounds { let mut lifetimes = Vec::new(); while self.check_lifetime() { - lifetimes.push(self.expect_lifetime()); + lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime())); if !self.eat_plus() { break @@ -4805,12 +4803,14 @@ impl<'a> Parser<'a> { } /// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )? - fn parse_ty_param(&mut self, preceding_attrs: Vec) -> PResult<'a, TyParam> { + fn parse_ty_param(&mut self, + preceding_attrs: Vec) + -> PResult<'a, GenericParam> { let ident = self.parse_ident()?; // Parse optional colon and param bounds. let bounds = if self.eat(&token::Colon) { - self.parse_ty_param_bounds()? + self.parse_generic_bounds()? } else { Vec::new() }; @@ -4821,25 +4821,27 @@ impl<'a> Parser<'a> { None }; - Ok(TyParam { - attrs: preceding_attrs.into(), + Ok(GenericParam { ident, id: ast::DUMMY_NODE_ID, + attrs: preceding_attrs.into(), bounds, - default, + kind: GenericParamKind::Type { + default, + } }) } /// Parses the following grammar: - /// TraitItemAssocTy = Ident ["<"...">"] [":" [TyParamBounds]] ["where" ...] ["=" Ty] - fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec) - -> PResult<'a, (ast::Generics, TyParam)> { + /// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] + fn parse_trait_item_assoc_ty(&mut self) + -> PResult<'a, (Ident, TraitItemKind, ast::Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; // Parse optional colon and param bounds. let bounds = if self.eat(&token::Colon) { - self.parse_ty_param_bounds()? + self.parse_generic_bounds()? } else { Vec::new() }; @@ -4852,13 +4854,7 @@ impl<'a> Parser<'a> { }; self.expect(&token::Semi)?; - Ok((generics, TyParam { - attrs: preceding_attrs.into(), - ident, - id: ast::DUMMY_NODE_ID, - bounds, - default, - })) + Ok((ident, TraitItemKind::Type(bounds, default), generics)) } /// Parses (possibly empty) list of lifetime and type parameters, possibly including @@ -4876,18 +4872,20 @@ impl<'a> Parser<'a> { } else { Vec::new() }; - params.push(ast::GenericParam::Lifetime(LifetimeDef { + params.push(ast::GenericParam { + ident: lifetime.ident, + id: lifetime.id, attrs: attrs.into(), - lifetime, bounds, - })); + kind: ast::GenericParamKind::Lifetime, + }); if seen_ty_param { self.span_err(self.prev_span, "lifetime parameters must be declared prior to type parameters"); } } else if self.check_ident() { // Parse type parameter. - params.push(ast::GenericParam::Type(self.parse_ty_param(attrs)?)); + params.push(self.parse_ty_param(attrs)?); seen_ty_param = true; } else { // Check for trailing attributes and stop parsing. @@ -4936,16 +4934,16 @@ impl<'a> Parser<'a> { /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings, /// possibly including trailing comma. - fn parse_generic_args(&mut self) -> PResult<'a, (Vec, Vec>, Vec)> { - let mut lifetimes = Vec::new(); - let mut types = Vec::new(); + fn parse_generic_args(&mut self) + -> PResult<'a, (Vec, Vec)> { + let mut args = Vec::new(); let mut bindings = Vec::new(); let mut seen_type = false; let mut seen_binding = false; loop { if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { // Parse lifetime argument. - lifetimes.push(self.expect_lifetime()); + args.push(GenericArg::Lifetime(self.expect_lifetime())); if seen_type || seen_binding { self.span_err(self.prev_span, "lifetime parameters must be declared prior to type parameters"); @@ -4965,11 +4963,12 @@ impl<'a> Parser<'a> { seen_binding = true; } else if self.check_type() { // Parse type argument. - types.push(self.parse_ty()?); + let ty_param = self.parse_ty()?; if seen_binding { - self.span_err(types[types.len() - 1].span, + self.span_err(ty_param.span, "type parameters must be declared prior to associated type bindings"); } + args.push(GenericArg::Type(ty_param)); seen_type = true; } else { break @@ -4979,7 +4978,7 @@ impl<'a> Parser<'a> { break } } - Ok((lifetimes, types, bindings)) + Ok((args, bindings)) } /// Parses an optional `where` clause and places it in `generics`. @@ -5037,7 +5036,7 @@ impl<'a> Parser<'a> { // or with mandatory equality sign and the second type. let ty = self.parse_ty()?; if self.eat(&token::Colon) { - let bounds = self.parse_ty_param_bounds()?; + let bounds = self.parse_generic_bounds()?; where_clause.predicates.push(ast::WherePredicate::BoundPredicate( ast::WhereBoundPredicate { span: lo.to(self.prev_span), @@ -5537,14 +5536,14 @@ impl<'a> Parser<'a> { // Parse optional colon and supertrait bounds. let bounds = if self.eat(&token::Colon) { - self.parse_ty_param_bounds()? + self.parse_generic_bounds()? } else { Vec::new() }; if self.eat(&token::Eq) { // it's a trait alias - let bounds = self.parse_ty_param_bounds()?; + let bounds = self.parse_generic_bounds()?; tps.where_clause = self.parse_where_clause()?; self.expect(&token::Semi)?; if unsafety != Unsafety::Normal { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 87edfd69e2bd6..7a55919f422b8 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -12,8 +12,8 @@ pub use self::AnnNode::*; use rustc_target::spec::abi::{self, Abi}; use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}; -use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; -use ast::{Attribute, MacDelimiter}; +use ast::{SelfKind, GenericBound, TraitBoundModifier}; +use ast::{Attribute, MacDelimiter, GenericArg}; use util::parser::{self, AssocOp, Fixity}; use attr; use codemap::{self, CodeMap}; @@ -292,8 +292,8 @@ pub fn ty_to_string(ty: &ast::Ty) -> String { to_string(|s| s.print_type(ty)) } -pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String { - to_string(|s| s.print_bounds("", bounds)) +pub fn bounds_to_string(bounds: &[ast::GenericBound]) -> String { + to_string(|s| s.print_type_bounds("", bounds)) } pub fn pat_to_string(pat: &ast::Pat) -> String { @@ -308,8 +308,8 @@ pub fn expr_to_string(e: &ast::Expr) -> String { to_string(|s| s.print_expr(e)) } -pub fn lifetime_to_string(e: &ast::Lifetime) -> String { - to_string(|s| s.print_lifetime(e)) +pub fn lifetime_to_string(lt: &ast::Lifetime) -> String { + to_string(|s| s.print_lifetime(*lt)) } pub fn tt_to_string(tt: tokenstream::TokenTree) -> String { @@ -1008,15 +1008,21 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_opt_lifetime(&mut self, - lifetime: &Option) -> io::Result<()> { - if let Some(l) = *lifetime { - self.print_lifetime(&l)?; + pub fn print_opt_lifetime(&mut self, lifetime: &Option) -> io::Result<()> { + if let Some(lt) = *lifetime { + self.print_lifetime(lt)?; self.nbsp()?; } Ok(()) } + pub fn print_generic_arg(&mut self, generic_arg: &GenericArg) -> io::Result<()> { + match generic_arg { + GenericArg::Lifetime(lt) => self.print_lifetime(*lt), + GenericArg::Type(ty) => self.print_type(ty), + } + } + pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> { self.maybe_print_comment(ty.span.lo())?; self.ibox(0)?; @@ -1071,10 +1077,10 @@ impl<'a> State<'a> { } ast::TyKind::TraitObject(ref bounds, syntax) => { let prefix = if syntax == ast::TraitObjectSyntax::Dyn { "dyn" } else { "" }; - self.print_bounds(prefix, &bounds[..])?; + self.print_type_bounds(prefix, &bounds[..])?; } ast::TyKind::ImplTrait(ref bounds) => { - self.print_bounds("impl", &bounds[..])?; + self.print_type_bounds("impl", &bounds[..])?; } ast::TyKind::Array(ref ty, ref length) => { self.s.word("[")?; @@ -1171,13 +1177,13 @@ impl<'a> State<'a> { fn print_associated_type(&mut self, ident: ast::Ident, - bounds: Option<&ast::TyParamBounds>, + bounds: Option<&ast::GenericBounds>, ty: Option<&ast::Ty>) -> io::Result<()> { self.word_space("type")?; self.print_ident(ident)?; if let Some(bounds) = bounds { - self.print_bounds(":", bounds)?; + self.print_type_bounds(":", bounds)?; } if let Some(ty) = ty { self.s.space()?; @@ -1322,7 +1328,7 @@ impl<'a> State<'a> { self.print_unsafety(unsafety)?; self.word_nbsp("impl")?; - if generics.is_parameterized() { + if !generics.params.is_empty() { self.print_generic_params(&generics.params)?; self.s.space()?; } @@ -1358,7 +1364,7 @@ impl<'a> State<'a> { self.print_generic_params(&generics.params)?; let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { - if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b { + if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b { self.s.space()?; self.word_space("for ?")?; self.print_trait_ref(&ptr.trait_ref)?; @@ -1366,7 +1372,7 @@ impl<'a> State<'a> { real_bounds.push(b.clone()); } } - self.print_bounds(":", &real_bounds[..])?; + self.print_type_bounds(":", &real_bounds[..])?; self.print_where_clause(&generics.where_clause)?; self.s.word(" ")?; self.bopen()?; @@ -1384,7 +1390,7 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(bounds.len()); // FIXME(durka) this seems to be some quite outdated syntax for b in bounds.iter() { - if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b { + if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b { self.s.space()?; self.word_space("for ?")?; self.print_trait_ref(&ptr.trait_ref)?; @@ -1393,7 +1399,7 @@ impl<'a> State<'a> { } } self.nbsp()?; - self.print_bounds("=", &real_bounds[..])?; + self.print_type_bounds("=", &real_bounds[..])?; self.print_where_clause(&generics.where_clause)?; self.s.word(";")?; } @@ -1984,8 +1990,8 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?; self.s.word(".")?; self.print_ident(segment.ident)?; - if let Some(ref parameters) = segment.parameters { - self.print_path_parameters(parameters, true)?; + if let Some(ref args) = segment.args { + self.print_generic_args(args, true)?; } self.print_call_post(base_args) } @@ -2428,8 +2434,8 @@ impl<'a> State<'a> { if segment.ident.name != keywords::CrateRoot.name() && segment.ident.name != keywords::DollarCrate.name() { self.print_ident(segment.ident)?; - if let Some(ref parameters) = segment.parameters { - self.print_path_parameters(parameters, colons_before_params)?; + if let Some(ref args) = segment.args { + self.print_generic_args(args, colons_before_params)?; } } else if segment.ident.name == keywords::DollarCrate.name() { self.print_dollar_crate(segment.ident.span.ctxt())?; @@ -2455,44 +2461,30 @@ impl<'a> State<'a> { self.s.word("::")?; let item_segment = path.segments.last().unwrap(); self.print_ident(item_segment.ident)?; - match item_segment.parameters { - Some(ref parameters) => self.print_path_parameters(parameters, colons_before_params), + match item_segment.args { + Some(ref args) => self.print_generic_args(args, colons_before_params), None => Ok(()), } } - fn print_path_parameters(&mut self, - parameters: &ast::PathParameters, - colons_before_params: bool) - -> io::Result<()> + fn print_generic_args(&mut self, + args: &ast::GenericArgs, + colons_before_params: bool) + -> io::Result<()> { if colons_before_params { self.s.word("::")? } - match *parameters { - ast::PathParameters::AngleBracketed(ref data) => { + match *args { + ast::GenericArgs::AngleBracketed(ref data) => { self.s.word("<")?; - let mut comma = false; - for lifetime in &data.lifetimes { - if comma { - self.word_space(",")? - } - self.print_lifetime(lifetime)?; - comma = true; - } + self.commasep(Inconsistent, &data.args, |s, generic_arg| { + s.print_generic_arg(generic_arg) + })?; - if !data.types.is_empty() { - if comma { - self.word_space(",")? - } - self.commasep( - Inconsistent, - &data.types, - |s, ty| s.print_type(ty))?; - comma = true; - } + let mut comma = data.args.len() != 0; for binding in data.bindings.iter() { if comma { @@ -2508,7 +2500,7 @@ impl<'a> State<'a> { self.s.word(">")? } - ast::PathParameters::Parenthesized(ref data) => { + ast::GenericArgs::Parenthesized(ref data) => { self.s.word("(")?; self.commasep( Inconsistent, @@ -2816,9 +2808,9 @@ impl<'a> State<'a> { } } - pub fn print_bounds(&mut self, + pub fn print_type_bounds(&mut self, prefix: &str, - bounds: &[ast::TyParamBound]) + bounds: &[ast::GenericBound]) -> io::Result<()> { if !bounds.is_empty() { self.s.word(prefix)?; @@ -2834,32 +2826,25 @@ impl<'a> State<'a> { } match bound { - TraitTyParamBound(tref, modifier) => { + GenericBound::Trait(tref, modifier) => { if modifier == &TraitBoundModifier::Maybe { self.s.word("?")?; } self.print_poly_trait_ref(tref)?; } - RegionTyParamBound(lt) => { - self.print_lifetime(lt)?; - } + GenericBound::Outlives(lt) => self.print_lifetime(*lt)?, } } } Ok(()) } - pub fn print_lifetime(&mut self, - lifetime: &ast::Lifetime) - -> io::Result<()> - { + pub fn print_lifetime(&mut self, lifetime: ast::Lifetime) -> io::Result<()> { self.print_name(lifetime.ident.name) } - pub fn print_lifetime_bounds(&mut self, - lifetime: &ast::Lifetime, - bounds: &[ast::Lifetime]) - -> io::Result<()> + pub fn print_lifetime_bounds(&mut self, lifetime: ast::Lifetime, bounds: &ast::GenericBounds) + -> io::Result<()> { self.print_lifetime(lifetime)?; if !bounds.is_empty() { @@ -2868,7 +2853,10 @@ impl<'a> State<'a> { if i != 0 { self.s.word(" + ")?; } - self.print_lifetime(bound)?; + match bound { + ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt)?, + _ => panic!(), + } } } Ok(()) @@ -2885,12 +2873,25 @@ impl<'a> State<'a> { self.s.word("<")?; self.commasep(Inconsistent, &generic_params, |s, param| { - match *param { - ast::GenericParam::Lifetime(ref lifetime_def) => { - s.print_outer_attributes_inline(&lifetime_def.attrs)?; - s.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds) + match param.kind { + ast::GenericParamKind::Lifetime => { + s.print_outer_attributes_inline(¶m.attrs)?; + let lt = ast::Lifetime { id: param.id, ident: param.ident }; + s.print_lifetime_bounds(lt, ¶m.bounds) }, - ast::GenericParam::Type(ref ty_param) => s.print_ty_param(ty_param), + ast::GenericParamKind::Type { ref default } => { + s.print_outer_attributes_inline(¶m.attrs)?; + s.print_ident(param.ident)?; + s.print_type_bounds(":", ¶m.bounds)?; + match default { + Some(ref default) => { + s.s.space()?; + s.word_space("=")?; + s.print_type(default) + } + _ => Ok(()) + } + } } })?; @@ -2898,20 +2899,6 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> { - self.print_outer_attributes_inline(¶m.attrs)?; - self.print_ident(param.ident)?; - self.print_bounds(":", ¶m.bounds)?; - match param.default { - Some(ref default) => { - self.s.space()?; - self.word_space("=")?; - self.print_type(default) - } - _ => Ok(()) - } - } - pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause) -> io::Result<()> { if where_clause.predicates.is_empty() { @@ -2935,12 +2922,12 @@ impl<'a> State<'a> { }) => { self.print_formal_generic_params(bound_generic_params)?; self.print_type(bounded_ty)?; - self.print_bounds(":", bounds)?; + self.print_type_bounds(":", bounds)?; } ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, ref bounds, ..}) => { - self.print_lifetime_bounds(lifetime, bounds)?; + self.print_lifetime_bounds(*lifetime, bounds)?; } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref lhs_ty, ref rhs_ty, diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index da7deb3c4cfe7..f896fa351b0af 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -353,7 +353,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { match (has_output, has_should_panic_attr) { (true, true) => No(BadTestSignature::ShouldPanicOnlyWithNoArgs), - (true, false) => if generics.is_parameterized() { + (true, false) => if !generics.params.is_empty() { No(BadTestSignature::WrongTypeSignature) } else { Yes diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index d4c6b4b158b25..ebb3081c1fde5 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -95,9 +95,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_trait_ref(self, t) } - fn visit_ty_param_bound(&mut self, bounds: &TyParamBound) { + fn visit_param_bound(&mut self, bounds: &GenericBound) { self.count += 1; - walk_ty_param_bound(self, bounds) + walk_param_bound(self, bounds) } fn visit_poly_trait_ref(&mut self, t: &PolyTraitRef, m: &TraitBoundModifier) { self.count += 1; @@ -137,9 +137,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_use_tree(self, use_tree, id) } - fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &PathParameters) { + fn visit_generic_args(&mut self, path_span: Span, generic_args: &GenericArgs) { self.count += 1; - walk_path_parameters(self, path_span, path_parameters) + walk_generic_args(self, path_span, generic_args) } fn visit_assoc_type_binding(&mut self, type_binding: &TypeBinding) { self.count += 1; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index adda39c62ed0e..613f1a4f113bd 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -73,7 +73,9 @@ pub trait Visitor<'ast>: Sized { fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) } fn visit_expr_post(&mut self, _ex: &'ast Expr) { } fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) } - fn visit_generic_param(&mut self, param: &'ast GenericParam) { walk_generic_param(self, param) } + fn visit_generic_param(&mut self, param: &'ast GenericParam) { + walk_generic_param(self, param) + } fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) } fn visit_where_predicate(&mut self, p: &'ast WherePredicate) { walk_where_predicate(self, p) @@ -84,8 +86,8 @@ pub trait Visitor<'ast>: Sized { fn visit_trait_item(&mut self, ti: &'ast TraitItem) { walk_trait_item(self, ti) } fn visit_impl_item(&mut self, ii: &'ast ImplItem) { walk_impl_item(self, ii) } fn visit_trait_ref(&mut self, t: &'ast TraitRef) { walk_trait_ref(self, t) } - fn visit_ty_param_bound(&mut self, bounds: &'ast TyParamBound) { - walk_ty_param_bound(self, bounds) + fn visit_param_bound(&mut self, bounds: &'ast GenericBound) { + walk_param_bound(self, bounds) } fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { walk_poly_trait_ref(self, t, m) @@ -128,8 +130,14 @@ pub trait Visitor<'ast>: Sized { fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) { walk_path_segment(self, path_span, path_segment) } - fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'ast PathParameters) { - walk_path_parameters(self, path_span, path_parameters) + fn visit_generic_args(&mut self, path_span: Span, generic_args: &'ast GenericArgs) { + walk_generic_args(self, path_span, generic_args) + } + fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) { + match generic_arg { + GenericArg::Lifetime(lt) => self.visit_lifetime(lt), + GenericArg::Type(ty) => self.visit_ty(ty), + } } fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) { walk_assoc_type_binding(self, type_binding) @@ -268,12 +276,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { } ItemKind::Trait(.., ref generics, ref bounds, ref methods) => { visitor.visit_generics(generics); - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_trait_item, methods); } ItemKind::TraitAlias(ref generics, ref bounds) => { visitor.visit_generics(generics); - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); } ItemKind::Mac(ref mac) => visitor.visit_mac(mac), ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id), @@ -333,7 +341,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { } TyKind::TraitObject(ref bounds, ..) | TyKind::ImplTrait(ref bounds) => { - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); } TyKind::Typeof(ref expression) => { visitor.visit_anon_const(expression) @@ -375,23 +383,22 @@ pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V, path_span: Span, segment: &'a PathSegment) { visitor.visit_ident(segment.ident); - if let Some(ref parameters) = segment.parameters { - visitor.visit_path_parameters(path_span, parameters); + if let Some(ref args) = segment.args { + visitor.visit_generic_args(path_span, args); } } -pub fn walk_path_parameters<'a, V>(visitor: &mut V, - _path_span: Span, - path_parameters: &'a PathParameters) +pub fn walk_generic_args<'a, V>(visitor: &mut V, + _path_span: Span, + generic_args: &'a GenericArgs) where V: Visitor<'a>, { - match *path_parameters { - PathParameters::AngleBracketed(ref data) => { - walk_list!(visitor, visit_ty, &data.types); - walk_list!(visitor, visit_lifetime, &data.lifetimes); + match *generic_args { + GenericArgs::AngleBracketed(ref data) => { + walk_list!(visitor, visit_generic_arg, &data.args); walk_list!(visitor, visit_assoc_type_binding, &data.bindings); } - PathParameters::Parenthesized(ref data) => { + GenericArgs::Parenthesized(ref data) => { walk_list!(visitor, visit_ty, &data.inputs); walk_list!(visitor, visit_ty, &data.output); } @@ -472,30 +479,20 @@ pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) { // Empty! } -pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyParamBound) { +pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) { match *bound { - TraitTyParamBound(ref typ, ref modifier) => { - visitor.visit_poly_trait_ref(typ, modifier); - } - RegionTyParamBound(ref lifetime) => { - visitor.visit_lifetime(lifetime); - } + GenericBound::Trait(ref typ, ref modifier) => visitor.visit_poly_trait_ref(typ, modifier), + GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), } } pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) { - match *param { - GenericParam::Lifetime(ref l) => { - visitor.visit_ident(l.lifetime.ident); - walk_list!(visitor, visit_lifetime, &l.bounds); - walk_list!(visitor, visit_attribute, &*l.attrs); - } - GenericParam::Type(ref t) => { - visitor.visit_ident(t.ident); - walk_list!(visitor, visit_ty_param_bound, &t.bounds); - walk_list!(visitor, visit_ty, &t.default); - walk_list!(visitor, visit_attribute, &*t.attrs); - } + visitor.visit_ident(param.ident); + walk_list!(visitor, visit_attribute, param.attrs.iter()); + walk_list!(visitor, visit_param_bound, ¶m.bounds); + match param.kind { + GenericParamKind::Lifetime => {} + GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default), } } @@ -511,14 +508,14 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a ref bound_generic_params, ..}) => { visitor.visit_ty(bounded_ty); - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_generic_param, bound_generic_params); } WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime, ref bounds, ..}) => { visitor.visit_lifetime(lifetime); - walk_list!(visitor, visit_lifetime, bounds); + walk_list!(visitor, visit_param_bound, bounds); } WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty, ref rhs_ty, @@ -579,7 +576,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai &sig.decl, trait_item.span, trait_item.id); } TraitItemKind::Type(ref bounds, ref default) => { - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, default); } TraitItemKind::Macro(ref mac) => { diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index dec24d13c9b49..9aeac5b1ddb2a 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -13,6 +13,7 @@ use deriving::generic::*; use deriving::generic::ty::*; use syntax::ast::{self, Expr, Generics, ItemKind, MetaItem, VariantData}; +use syntax::ast::GenericArg; use syntax::attr; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; @@ -48,7 +49,10 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, ItemKind::Struct(_, Generics { ref params, .. }) | ItemKind::Enum(_, Generics { ref params, .. }) => { if attr::contains_name(&annitem.attrs, "rustc_copy_clone_marker") && - !params.iter().any(|param| param.is_type_param()) + !params.iter().any(|param| match param.kind { + ast::GenericParamKind::Type { .. } => true, + _ => false, + }) { bounds = vec![]; is_shallow = true; @@ -123,7 +127,7 @@ fn cs_clone_shallow(name: &str, let span = span.with_ctxt(cx.backtrace()); let assert_path = cx.path_all(span, true, cx.std_path(&["clone", helper_name]), - vec![], vec![ty], vec![]); + vec![GenericArg::Type(ty)], vec![]); stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path))); } fn process_variant(cx: &mut ExtCtxt, stmts: &mut Vec, variant: &VariantData) { diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs index 237c8654edf6e..00ab39032acbd 100644 --- a/src/libsyntax_ext/deriving/cmp/eq.rs +++ b/src/libsyntax_ext/deriving/cmp/eq.rs @@ -12,7 +12,7 @@ use deriving::path_std; use deriving::generic::*; use deriving::generic::ty::*; -use syntax::ast::{self, Expr, MetaItem}; +use syntax::ast::{self, Expr, MetaItem, GenericArg}; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; use syntax::ptr::P; @@ -62,7 +62,7 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) let span = span.with_ctxt(cx.backtrace()); let assert_path = cx.path_all(span, true, cx.std_path(&["cmp", helper_name]), - vec![], vec![ty], vec![]); + vec![GenericArg::Type(ty)], vec![]); stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path))); } fn process_variant(cx: &mut ExtCtxt, stmts: &mut Vec, variant: &ast::VariantData) { diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 80f65957c39a2..672726d147579 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -192,10 +192,8 @@ use std::collections::HashSet; use std::vec; use rustc_target::spec::abi::Abi; -use syntax::ast::{ - self, BinOpKind, EnumDef, Expr, GenericParam, Generics, Ident, PatKind, VariantData -}; - +use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; +use syntax::ast::{VariantData, GenericParamKind, GenericArg}; use syntax::attr; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; @@ -424,7 +422,10 @@ impl<'a> TraitDef<'a> { ast::ItemKind::Struct(_, ref generics) | ast::ItemKind::Enum(_, ref generics) | ast::ItemKind::Union(_, ref generics) => { - !generics.params.iter().any(|p| p.is_type_param()) + !generics.params.iter().any(|param| match param.kind { + ast::GenericParamKind::Type { .. } => true, + _ => false, + }) } _ => { // Non-ADT derive is an error, but it should have been @@ -548,30 +549,27 @@ impl<'a> TraitDef<'a> { .to_generics(cx, self.span, type_ident, generics); // Create the generic parameters - params.extend(generics.params.iter().map(|param| { - match *param { - ref l @ GenericParam::Lifetime(_) => l.clone(), - GenericParam::Type(ref ty_param) => { - // I don't think this can be moved out of the loop, since - // a TyParamBound requires an ast id - let mut bounds: Vec<_> = - // extra restrictions on the generics parameters to the - // type being derived upon - self.additional_bounds.iter().map(|p| { - cx.typarambound(p.to_path(cx, self.span, - type_ident, generics)) - }).collect(); - - // require the current trait - bounds.push(cx.typarambound(trait_path.clone())); - - // also add in any bounds from the declaration - for declared_bound in ty_param.bounds.iter() { - bounds.push((*declared_bound).clone()); - } - - GenericParam::Type(cx.typaram(self.span, ty_param.ident, vec![], bounds, None)) + params.extend(generics.params.iter().map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => param.clone(), + GenericParamKind::Type { .. } => { + // I don't think this can be moved out of the loop, since + // a GenericBound requires an ast id + let mut bounds: Vec<_> = + // extra restrictions on the generics parameters to the + // type being derived upon + self.additional_bounds.iter().map(|p| { + cx.trait_bound(p.to_path(cx, self.span, type_ident, generics)) + }).collect(); + + // require the current trait + bounds.push(cx.trait_bound(trait_path.clone())); + + // also add in any bounds from the declaration + for declared_bound in ¶m.bounds { + bounds.push((*declared_bound).clone()); } + + cx.typaram(self.span, param.ident, vec![], bounds, None) } })); @@ -608,8 +606,8 @@ impl<'a> TraitDef<'a> { // Extra scope required here so ty_params goes out of scope before params is moved let mut ty_params = params.iter() - .filter_map(|param| match *param { - ast::GenericParam::Type(ref t) => Some(t), + .filter_map(|param| match param.kind { + ast::GenericParamKind::Type { .. } => Some(param), _ => None, }) .peekable(); @@ -636,12 +634,12 @@ impl<'a> TraitDef<'a> { let mut bounds: Vec<_> = self.additional_bounds .iter() .map(|p| { - cx.typarambound(p.to_path(cx, self.span, type_ident, generics)) + cx.trait_bound(p.to_path(cx, self.span, type_ident, generics)) }) .collect(); // require the current trait - bounds.push(cx.typarambound(trait_path.clone())); + bounds.push(cx.trait_bound(trait_path.clone())); let predicate = ast::WhereBoundPredicate { span: self.span, @@ -666,31 +664,18 @@ impl<'a> TraitDef<'a> { // Create the reference to the trait. let trait_ref = cx.trait_ref(trait_path); - // Create the type parameters on the `self` path. - let self_ty_params = generics.params - .iter() - .filter_map(|param| match *param { - GenericParam::Type(ref ty_param) - => Some(cx.ty_ident(self.span, ty_param.ident)), - _ => None, - }) - .collect(); - - let self_lifetimes: Vec = generics.params - .iter() - .filter_map(|param| match *param { - GenericParam::Lifetime(ref ld) => Some(ld.lifetime), - _ => None, - }) - .collect(); + let self_params: Vec<_> = generics.params.iter().map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + GenericArg::Lifetime(cx.lifetime(self.span, param.ident)) + } + GenericParamKind::Type { .. } => { + GenericArg::Type(cx.ty_ident(self.span, param.ident)) + } + }).collect(); // Create the type of `self`. - let self_type = cx.ty_path(cx.path_all(self.span, - false, - vec![type_ident], - self_lifetimes, - self_ty_params, - Vec::new())); + let path = cx.path_all(self.span, false, vec![type_ident], self_params, vec![]); + let self_type = cx.ty_path(path); let attr = cx.attribute(self.span, cx.meta_word(self.span, diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index 25a2969448835..0b809ab585cdc 100644 --- a/src/libsyntax_ext/deriving/generic/ty.rs +++ b/src/libsyntax_ext/deriving/generic/ty.rs @@ -15,7 +15,7 @@ pub use self::PtrTy::*; pub use self::Ty::*; use syntax::ast; -use syntax::ast::{Expr, GenericParam, Generics, Ident, SelfKind}; +use syntax::ast::{Expr, GenericParamKind, Generics, Ident, SelfKind, GenericArg}; use syntax::ext::base::ExtCtxt; use syntax::ext::build::AstBuilder; use syntax::codemap::{respan, DUMMY_SP}; @@ -86,15 +86,20 @@ impl<'a> Path<'a> { -> ast::Path { let mut idents = self.path.iter().map(|s| cx.ident_of(*s)).collect(); let lt = mk_lifetimes(cx, span, &self.lifetime); - let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); + let tys: Vec> = + self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); + let params = lt.into_iter() + .map(|lt| GenericArg::Lifetime(lt)) + .chain(tys.into_iter().map(|ty| GenericArg::Type(ty))) + .collect(); match self.kind { - PathKind::Global => cx.path_all(span, true, idents, lt, tys, Vec::new()), - PathKind::Local => cx.path_all(span, false, idents, lt, tys, Vec::new()), + PathKind::Global => cx.path_all(span, true, idents, params, Vec::new()), + PathKind::Local => cx.path_all(span, false, idents, params, Vec::new()), PathKind::Std => { let def_site = DUMMY_SP.apply_mark(cx.current_expansion.mark); idents.insert(0, Ident::new(keywords::DollarCrate.name(), def_site)); - cx.path_all(span, false, idents, lt, tys, Vec::new()) + cx.path_all(span, false, idents, params, Vec::new()) } } @@ -180,34 +185,22 @@ impl<'a> Ty<'a> { cx: &ExtCtxt, span: Span, self_ty: Ident, - self_generics: &Generics) + generics: &Generics) -> ast::Path { match *self { Self_ => { - let self_params = self_generics.params - .iter() - .filter_map(|param| match *param { - GenericParam::Type(ref ty_param) => Some(cx.ty_ident(span, ty_param.ident)), - _ => None, - }) - .collect(); - - let lifetimes: Vec = self_generics.params - .iter() - .filter_map(|param| match *param { - GenericParam::Lifetime(ref ld) => Some(ld.lifetime), - _ => None, - }) - .collect(); + let params: Vec<_> = generics.params.iter().map(|param| match param.kind { + GenericParamKind::Lifetime { .. } => { + GenericArg::Lifetime(ast::Lifetime { id: param.id, ident: param.ident }) + } + GenericParamKind::Type { .. } => { + GenericArg::Type(cx.ty_ident(span, param.ident)) + } + }).collect(); - cx.path_all(span, - false, - vec![self_ty], - lifetimes, - self_params, - Vec::new()) + cx.path_all(span, false, vec![self_ty], params, vec![]) } - Literal(ref p) => p.to_path(cx, span, self_ty, self_generics), + Literal(ref p) => p.to_path(cx, span, self_ty, generics), Ptr(..) => cx.span_bug(span, "pointer in a path in generic `derive`"), Tuple(..) => cx.span_bug(span, "tuple in a path in generic `derive`"), } @@ -222,17 +215,17 @@ fn mk_ty_param(cx: &ExtCtxt, bounds: &[Path], self_ident: Ident, self_generics: &Generics) - -> ast::TyParam { + -> ast::GenericParam { let bounds = bounds.iter() .map(|b| { let path = b.to_path(cx, span, self_ident, self_generics); - cx.typarambound(path) + cx.trait_bound(path) }) .collect(); cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None) } -fn mk_generics(params: Vec, span: Span) -> Generics { +fn mk_generics(params: Vec, span: Span) -> Generics { Generics { params, where_clause: ast::WhereClause { @@ -268,17 +261,14 @@ impl<'a> LifetimeBounds<'a> { .iter() .map(|&(lt, ref bounds)| { let bounds = bounds.iter() - .map(|b| cx.lifetime(span, Ident::from_str(b))) - .collect(); - GenericParam::Lifetime(cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds)) + .map(|b| ast::GenericBound::Outlives(cx.lifetime(span, Ident::from_str(b)))); + cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds.collect()) }) .chain(self.bounds .iter() .map(|t| { let (name, ref bounds) = *t; - GenericParam::Type(mk_ty_param( - cx, span, name, &[], &bounds, self_ty, self_generics - )) + mk_ty_param(cx, span, name, &[], &bounds, self_ty, self_generics) }) ) .collect(); diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index a5b348a661a78..6ff385b18e8bf 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -134,9 +134,12 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String { match item.node { ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) | ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => { - for param in params.iter() { - if let ast::GenericParam::Type(ref ty) = *param{ - typaram.push_str(&ty.ident.as_str()); + for param in params { + match param.kind { + ast::GenericParamKind::Type { .. } => { + typaram.push_str(¶m.ident.as_str()); + } + _ => {} } } } diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index 4e1af108ab4fa..bbc5b03d6885e 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -13,7 +13,7 @@ // interface. // -use syntax::ast::{self, Ident}; +use syntax::ast::{self, Ident, GenericArg}; use syntax::ext::base::*; use syntax::ext::base; use syntax::ext::build::AstBuilder; @@ -39,12 +39,11 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, cx.expr_path(cx.path_all(sp, true, cx.std_path(&["option", "Option", "None"]), - Vec::new(), - vec![cx.ty_rptr(sp, + vec![GenericArg::Type(cx.ty_rptr(sp, cx.ty_ident(sp, Ident::from_str("str")), Some(lt), - ast::Mutability::Immutable)], - Vec::new())) + ast::Mutability::Immutable))], + vec![])) } Ok(s) => { cx.expr_call_global(sp, diff --git a/src/test/compile-fail/issue-1900.rs b/src/test/compile-fail/issue-1900.rs index c7564a9355bc5..ccdd9db25c40a 100644 --- a/src/test/compile-fail/issue-1900.rs +++ b/src/test/compile-fail/issue-1900.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern: `main` function is not allowed to have type parameters +// error-pattern: `main` function is not allowed to have generic parameters fn main() { } diff --git a/src/test/run-pass/issue-22777.rs b/src/test/run-pass/issue-22777.rs index 2dc4d775a9c45..4df46c0e2e1e7 100644 --- a/src/test/run-pass/issue-22777.rs +++ b/src/test/run-pass/issue-22777.rs @@ -32,8 +32,8 @@ struct S04_TyParamBound(S05_PolyTraitRef); struct S05_PolyTraitRef(S06_TraitRef); struct S06_TraitRef(S07_Path); struct S07_Path(Vec); -struct S08_PathSegment(S09_PathParameters); -struct S09_PathParameters(P); +struct S08_PathSegment(S09_GenericArgs); +struct S09_GenericArgs(P); struct S10_ParenthesizedParameterData(Option>); struct S11_Ty(P); struct S12_Expr(P); diff --git a/src/test/ui/error-codes/E0110.stderr b/src/test/ui/error-codes/E0110.stderr index 10e06ee6d025a..7f5b78684fbc1 100644 --- a/src/test/ui/error-codes/E0110.stderr +++ b/src/test/ui/error-codes/E0110.stderr @@ -2,7 +2,7 @@ error[E0110]: lifetime parameters are not allowed on this type --> $DIR/E0110.rs:11:14 | LL | type X = u32<'static>; //~ ERROR E0110 - | ^^^^^^^ lifetime parameter not allowed on this type + | ^^^^^^^ lifetime parameter not allowed error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0131.stderr b/src/test/ui/error-codes/E0131.stderr index ba9355763f67a..46bc872746cc3 100644 --- a/src/test/ui/error-codes/E0131.stderr +++ b/src/test/ui/error-codes/E0131.stderr @@ -1,8 +1,8 @@ -error[E0131]: `main` function is not allowed to have type parameters +error[E0131]: `main` function is not allowed to have generic parameters --> $DIR/E0131.rs:11:8 | LL | fn main() { - | ^^^ `main` cannot have type parameters + | ^^^ `main` cannot have generic parameters error: aborting due to previous error diff --git a/src/test/ui/issue-51022.rs b/src/test/ui/issue-51022.rs index f9486fa57b136..831c3e5fda084 100644 --- a/src/test/ui/issue-51022.rs +++ b/src/test/ui/issue-51022.rs @@ -9,4 +9,4 @@ // except according to those terms. fn main<'a>() { } - //~^ ERROR `main` function is not allowed to have lifetime parameters [E0131] + //~^ ERROR `main` function is not allowed to have generic parameters [E0131] diff --git a/src/test/ui/issue-51022.stderr b/src/test/ui/issue-51022.stderr index 3b691bbb0330f..1daa8dfbba689 100644 --- a/src/test/ui/issue-51022.stderr +++ b/src/test/ui/issue-51022.stderr @@ -1,8 +1,8 @@ -error[E0131]: `main` function is not allowed to have lifetime parameters +error[E0131]: `main` function is not allowed to have generic parameters --> $DIR/issue-51022.rs:11:8 | LL | fn main<'a>() { } - | ^^^^ `main` cannot have lifetime parameters + | ^^^^ `main` cannot have generic parameters error: aborting due to previous error diff --git a/src/test/ui/rfc1598-generic-associated-types/collections.stderr b/src/test/ui/rfc1598-generic-associated-types/collections.stderr index ed96570583f4f..8c31ab2ca88e4 100644 --- a/src/test/ui/rfc1598-generic-associated-types/collections.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/collections.stderr @@ -20,13 +20,13 @@ error[E0110]: lifetime parameters are not allowed on this type --> $DIR/collections.rs:33:50 | LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>; - | ^^^^^ lifetime parameter not allowed on this type + | ^^^^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/collections.rs:59:50 | LL | fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> { - | ^^^^^ lifetime parameter not allowed on this type + | ^^^^^ lifetime parameter not allowed error: aborting due to 5 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr index 764a0db2478a8..1746122eb49f4 100644 --- a/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr @@ -2,19 +2,19 @@ error[E0110]: lifetime parameters are not allowed on this type --> $DIR/construct_with_other_type.rs:26:46 | LL | type Baa<'a>: Deref as Foo>::Bar<'a, 'static>>; - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/construct_with_other_type.rs:26:63 | LL | type Baa<'a>: Deref as Foo>::Bar<'a, 'static>>; - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/construct_with_other_type.rs:34:40 | LL | type Baa<'a> = &'a ::Bar<'a, 'static>; - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr index 64e82c0d1097f..d48c21477b310 100644 --- a/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr @@ -14,19 +14,19 @@ error[E0110]: lifetime parameters are not allowed on this type --> $DIR/generic_associated_type_undeclared_lifetimes.rs:20:47 | LL | type Iter<'a>: Iterator> - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/generic_associated_type_undeclared_lifetimes.rs:22:37 | LL | + Deref>; - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/generic_associated_type_undeclared_lifetimes.rs:26:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; - | ^^^^^^^^^^^ lifetime parameter not allowed on this type + | ^^^^^^^^^^^ lifetime parameter not allowed error: aborting due to 5 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/iterable.stderr b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr index 0e251300e451f..737a29ec2c8be 100644 --- a/src/test/ui/rfc1598-generic-associated-types/iterable.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/iterable.stderr @@ -2,37 +2,37 @@ error[E0110]: lifetime parameters are not allowed on this type --> $DIR/iterable.rs:20:47 | LL | type Iter<'a>: Iterator>; - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/iterable.rs:49:53 | LL | fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> { - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/iterable.rs:54:60 | LL | fn get_first<'a, I: Iterable>(it: &'a I) -> Option> { - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/iterable.rs:23:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'a>; - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/iterable.rs:32:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/iterable.rs:43:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'a> { - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error: aborting due to 6 previous errors diff --git a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr index df83fdaad5bfa..c8d37a51fa96b 100644 --- a/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr @@ -1,3 +1,9 @@ +error[E0110]: lifetime parameters are not allowed on this type + --> $DIR/parameter_number_and_kind.rs:26:27 + | +LL | type FOk = Self::E<'static, T>; + | ^^^^^^^ lifetime parameter not allowed + error[E0109]: type parameters are not allowed on this type --> $DIR/parameter_number_and_kind.rs:26:36 | @@ -5,16 +11,16 @@ LL | type FOk = Self::E<'static, T>; | ^ type parameter not allowed error[E0110]: lifetime parameters are not allowed on this type - --> $DIR/parameter_number_and_kind.rs:26:27 + --> $DIR/parameter_number_and_kind.rs:29:26 | -LL | type FOk = Self::E<'static, T>; - | ^^^^^^^ lifetime parameter not allowed on this type +LL | type FErr1 = Self::E<'static, 'static>; // Error + | ^^^^^^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type - --> $DIR/parameter_number_and_kind.rs:29:26 + --> $DIR/parameter_number_and_kind.rs:31:29 | -LL | type FErr1 = Self::E<'static, 'static>; // Error - | ^^^^^^^ lifetime parameter not allowed on this type +LL | type FErr2 = Self::E<'static, T, u32>; // Error + | ^^^^^^^ lifetime parameter not allowed error[E0109]: type parameters are not allowed on this type --> $DIR/parameter_number_and_kind.rs:31:38 @@ -22,12 +28,6 @@ error[E0109]: type parameters are not allowed on this type LL | type FErr2 = Self::E<'static, T, u32>; // Error | ^ type parameter not allowed -error[E0110]: lifetime parameters are not allowed on this type - --> $DIR/parameter_number_and_kind.rs:31:29 - | -LL | type FErr2 = Self::E<'static, T, u32>; // Error - | ^^^^^^^ lifetime parameter not allowed on this type - error: aborting due to 5 previous errors Some errors occurred: E0109, E0110. diff --git a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr index 607a4b8d57996..12e206cbd476a 100644 --- a/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr +++ b/src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr @@ -2,31 +2,31 @@ error[E0110]: lifetime parameters are not allowed on this type --> $DIR/streaming_iterator.rs:27:41 | LL | bar: ::Item<'static>, - | ^^^^^^^ lifetime parameter not allowed on this type + | ^^^^^^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/streaming_iterator.rs:35:64 | LL | fn foo(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ } - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/streaming_iterator.rs:21:48 | LL | fn next<'a>(&'a self) -> Option>; - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/streaming_iterator.rs:47:37 | LL | type Item<'a> = (usize, I::Item<'a>); - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error[E0110]: lifetime parameters are not allowed on this type --> $DIR/streaming_iterator.rs:49:48 | LL | fn next<'a>(&'a self) -> Option> { - | ^^ lifetime parameter not allowed on this type + | ^^ lifetime parameter not allowed error: aborting due to 5 previous errors