From 78493ed21aaeb20a8d5f7bd08f26c0c9fd496ed4 Mon Sep 17 00:00:00 2001 From: Jonas Platte Date: Mon, 16 Oct 2017 21:07:26 +0200 Subject: [PATCH] Add GenericParam, refactor Generics in ast, hir, rustdoc The Generics now contain one Vec of an enum for the generic parameters, rather than two separate Vec's for lifetime and type parameters. Additionally, places that previously used Vec now use Vec instead. --- src/librustc/hir/intravisit.rs | 42 ++-- src/librustc/hir/lowering.rs | 229 +++++++++++------- src/librustc/hir/map/collector.rs | 2 +- src/librustc/hir/map/def_collector.rs | 29 ++- src/librustc/hir/mod.rs | 107 ++++++-- src/librustc/hir/print.rs | 105 +++----- src/librustc/ich/impls_hir.rs | 14 +- src/librustc/lint/context.rs | 19 +- src/librustc/lint/mod.rs | 4 +- src/librustc/middle/reachable.rs | 2 +- src/librustc/middle/resolve_lifetime.rs | 146 +++++------ src/librustc_lint/bad_style.rs | 22 +- src/librustc_lint/builtin.rs | 6 +- src/librustc_lint/types.rs | 2 +- src/librustc_metadata/encoder.rs | 6 +- src/librustc_mir/monomorphize/collector.rs | 2 +- src/librustc_passes/ast_validation.rs | 48 ++-- src/librustc_passes/hir_stats.rs | 9 - src/librustc_privacy/lib.rs | 2 +- src/librustc_resolve/lib.rs | 69 +++--- src/librustc_save_analysis/dump_visitor.rs | 85 ++++--- src/librustc_save_analysis/lib.rs | 18 +- src/librustc_save_analysis/sig.rs | 86 ++++--- src/librustc_typeck/check/compare_method.rs | 6 +- src/librustc_typeck/check/mod.rs | 12 +- src/librustc_typeck/check/wfcheck.rs | 10 +- src/librustc_typeck/collect.rs | 16 +- src/librustc_typeck/impl_wf_check.rs | 4 +- src/librustc_typeck/lib.rs | 4 +- src/librustdoc/clean/mod.rs | 87 ++++--- src/librustdoc/html/format.rs | 63 ++--- src/librustdoc/html/render.rs | 6 +- src/libsyntax/ast.rs | 61 +++-- src/libsyntax/ext/build.rs | 2 +- src/libsyntax/feature_gate.rs | 25 +- src/libsyntax/fold.rs | 37 ++- src/libsyntax/parse/mod.rs | 5 +- src/libsyntax/parse/parser.rs | 49 ++-- src/libsyntax/print/pprust.rs | 111 ++++----- src/libsyntax/test.rs | 5 +- src/libsyntax/util/node_count.rs | 8 +- src/libsyntax/visit.rs | 42 ++-- src/libsyntax_ext/deriving/clone.rs | 26 +- src/libsyntax_ext/deriving/generic/mod.rs | 152 +++++++----- src/libsyntax_ext/deriving/generic/ty.rs | 49 ++-- src/libsyntax_ext/deriving/mod.rs | 10 +- .../projection-one-region-closure.stderr | 4 +- ...tion-one-region-trait-bound-closure.stderr | 2 +- ...tion-two-region-trait-bound-closure.stderr | 4 +- ...ram-closure-approximate-lower-bound.stderr | 2 +- ...-closure-outlives-from-where-clause.stderr | 4 +- 51 files changed, 1024 insertions(+), 836 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 3a1b0b8c58ebb..74714edfc8646 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -279,6 +279,9 @@ pub trait Visitor<'v> : Sized { fn visit_ty(&mut self, t: &'v Ty) { walk_ty(self, t) } + fn visit_generic_param(&mut self, p: &'v GenericParam) { + walk_generic_param(self, p) + } fn visit_generics(&mut self, g: &'v Generics) { walk_generics(self, g) } @@ -336,9 +339,6 @@ pub trait Visitor<'v> : Sized { fn visit_lifetime(&mut self, lifetime: &'v Lifetime) { walk_lifetime(self, lifetime) } - fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) { - walk_lifetime_def(self, lifetime) - } fn visit_qpath(&mut self, qpath: &'v QPath, id: NodeId, span: Span) { walk_qpath(self, qpath, id, span) } @@ -430,17 +430,12 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime } } -pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) { - visitor.visit_lifetime(&lifetime_def.lifetime); - walk_list!(visitor, visit_lifetime, &lifetime_def.bounds); -} - pub fn walk_poly_trait_ref<'v, V>(visitor: &mut V, trait_ref: &'v PolyTraitRef, _modifier: TraitBoundModifier) where V: Visitor<'v> { - walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes); + walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params); visitor.visit_trait_ref(&trait_ref.trait_ref); } @@ -581,7 +576,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { } TyBareFn(ref function_declaration) => { visitor.visit_fn_decl(&function_declaration.decl); - walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes); + walk_list!(visitor, visit_generic_param, &function_declaration.generic_params); } TyPath(ref qpath) => { visitor.visit_qpath(qpath, typ.id, typ.span); @@ -729,14 +724,23 @@ pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyPar } } -pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) { - for param in &generics.ty_params { - visitor.visit_id(param.id); - visitor.visit_name(param.span, param.name); - walk_list!(visitor, visit_ty_param_bound, ¶m.bounds); - walk_list!(visitor, visit_ty, ¶m.default); +pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam) { + match *param { + GenericParam::Lifetime(ref ld) => { + visitor.visit_lifetime(&ld.lifetime); + 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_lifetime_def, &generics.lifetimes); +} + +pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) { + walk_list!(visitor, visit_generic_param, &generics.params); visitor.visit_id(generics.where_clause.id); walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates); } @@ -748,11 +752,11 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( match predicate { &WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty, ref bounds, - ref bound_lifetimes, + ref bound_generic_params, ..}) => { visitor.visit_ty(bounded_ty); walk_list!(visitor, visit_ty_param_bound, bounds); - walk_list!(visitor, visit_lifetime_def, bound_lifetimes); + walk_list!(visitor, visit_generic_param, bound_generic_params); } &WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime, ref bounds, diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 847cf64ce6a03..22e661a876ec2 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -253,7 +253,9 @@ impl<'a> LoweringContext<'a> { ItemKind::Ty(_, ref generics) | ItemKind::Trait(_, _, ref generics, ..) => { let def_id = self.lctx.resolver.definitions().local_def_id(item.id); - let count = generics.lifetimes.len(); + let count = generics.params.iter() + .filter(|param| param.is_lifetime_param()) + .count(); self.lctx.type_def_lifetime_params.insert(def_id, count); } _ => {} @@ -306,8 +308,8 @@ impl<'a> LoweringContext<'a> { let item_lifetimes = match self.lctx.items.get(&item.id).unwrap().node { hir::Item_::ItemImpl(_,_,_,ref generics,..) | hir::Item_::ItemTrait(_,_,ref generics,..) => - generics.lifetimes.clone(), - _ => Vec::new().into(), + generics.lifetimes().cloned().collect::>(), + _ => Vec::new(), }; self.lctx.with_parent_impl_lifetime_defs(&item_lifetimes, |this| { @@ -532,14 +534,14 @@ impl<'a> LoweringContext<'a> { span.with_ctxt(SyntaxContext::empty().apply_mark(mark)) } - // Creates a new hir::LifetimeDef for every new lifetime encountered - // while evaluating `f`. Definitions are created with the parent provided. - // If no `parent_id` is provided, no definitions will be returned. + // Creates a new hir::GenericParam for every new lifetime and type parameter + // encountered while evaluating `f`. Definitions are created with the parent + // provided. If no `parent_id` is provided, no definitions will be returned. fn collect_in_band_defs( &mut self, parent_id: Option, f: F - ) -> (Vec, Vec, T) where F: FnOnce(&mut LoweringContext) -> T + ) -> (Vec, T) where F: FnOnce(&mut LoweringContext) -> T { assert!(!self.is_collecting_in_band_lifetimes); assert!(self.lifetimes_to_define.is_empty()); @@ -554,7 +556,7 @@ impl<'a> LoweringContext<'a> { let in_band_ty_params = self.in_band_ty_params.split_off(0); let lifetimes_to_define = self.lifetimes_to_define.split_off(0); - let lifetime_defs = match parent_id { + let mut params = match parent_id { Some(parent_id) => lifetimes_to_define.into_iter().map(|(span, name)| { let def_node_id = self.next_id().node_id; @@ -567,7 +569,7 @@ impl<'a> LoweringContext<'a> { Mark::root() ); - hir::LifetimeDef { + hir::GenericParam::Lifetime(hir::LifetimeDef { lifetime: hir::Lifetime { id: def_node_id, span, @@ -576,12 +578,14 @@ impl<'a> LoweringContext<'a> { bounds: Vec::new().into(), pure_wrt_drop: false, in_band: true, - } + }) }).collect(), None => Vec::new(), }; - (in_band_ty_params, lifetime_defs, res) + params.extend(in_band_ty_params.into_iter().map(|tp| hir::GenericParam::Type(tp))); + + (params, res) } // Evaluates `f` with the lifetimes in `lt_defs` in-scope. @@ -635,24 +639,24 @@ impl<'a> LoweringContext<'a> { ) -> (hir::Generics, T) where F: FnOnce(&mut LoweringContext) -> T { - let (in_band_ty_defs, in_band_lifetime_defs, (mut lowered_generics, res)) = - self.with_in_scope_lifetime_defs(&generics.lifetimes, |this| { - this.collect_in_band_defs(parent_id, |this| { - (this.lower_generics(generics), f(this)) - }) - }); - - lowered_generics.ty_params = - lowered_generics.ty_params - .iter().cloned() - .chain(in_band_ty_defs.into_iter()) - .collect(); + let (in_band_defs, (mut lowered_generics, res)) = + self.with_in_scope_lifetime_defs( + &generics.params + .iter() + .filter_map(|p| match *p { + GenericParam::Lifetime(ref ld) => Some(ld.clone()), + _ => None, + }) + .collect::>(), + |this| { + this.collect_in_band_defs(parent_id, |this| { + (this.lower_generics(generics), f(this)) + }) + } + ); - lowered_generics.lifetimes = - lowered_generics.lifetimes - .iter().cloned() - .chain(in_band_lifetime_defs.into_iter()) - .collect(); + lowered_generics.params = + lowered_generics.params.iter().cloned().chain(in_band_defs).collect(); (lowered_generics, res) } @@ -877,9 +881,16 @@ impl<'a> LoweringContext<'a> { hir::TyRptr(lifetime, self.lower_mt(mt, itctx)) } TyKind::BareFn(ref f) => { - self.with_in_scope_lifetime_defs(&f.lifetimes, |this| - hir::TyBareFn(P(hir::BareFnTy { - lifetimes: this.lower_lifetime_defs(&f.lifetimes), + self.with_in_scope_lifetime_defs( + &f.generic_params + .iter() + .filter_map(|p| match *p { + GenericParam::Lifetime(ref ld) => Some(ld.clone()), + _ => None, + }) + .collect::>(), + |this| hir::TyBareFn(P(hir::BareFnTy { + generic_params: this.lower_generic_params(&f.generic_params, &NodeMap()), unsafety: this.lower_unsafety(f.unsafety), abi: f.abi, decl: this.lower_fn_decl(&f.decl, None, false), @@ -954,9 +965,7 @@ impl<'a> LoweringContext<'a> { hir::TyImplTraitExistential(hir::ExistTy { generics: hir::Generics { - lifetimes: lifetime_defs, - // Type parameters are taken from environment: - ty_params: Vec::new().into(), + params: lifetime_defs, where_clause: hir::WhereClause { id: self.next_id().node_id, predicates: Vec::new().into(), @@ -1027,7 +1036,7 @@ impl<'a> LoweringContext<'a> { &mut self, parent_index: DefIndex, bounds: &hir::TyParamBounds - ) -> (HirVec, HirVec) { + ) -> (HirVec, HirVec) { // This visitor walks over impl trait bounds and creates defs for all lifetimes which // appear in the bounds, excluding lifetimes that are created within the bounds. @@ -1039,7 +1048,7 @@ impl<'a> LoweringContext<'a> { currently_bound_lifetimes: Vec, already_defined_lifetimes: HashSet, output_lifetimes: Vec, - output_lifetime_defs: Vec, + output_lifetime_params: Vec, } impl<'r, 'a: 'r, 'v> hir::intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a> { @@ -1078,14 +1087,16 @@ impl<'a> LoweringContext<'a> { let old_len = self.currently_bound_lifetimes.len(); // Record the introduction of 'a in `for<'a> ...` - for lt_def in &polytr.bound_lifetimes { - // 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); - - // Visit the lifetime bounds - for lt_bound in <_def.bounds { - self.visit_lifetime(<_bound); + for param in &polytr.bound_generic_params { + if let hir::GenericParam::Lifetime(ref lt_def) = *param { + // 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); + + // Visit the lifetime bounds + for lt_bound in <_def.bounds { + self.visit_lifetime(<_bound); + } } } @@ -1133,12 +1144,12 @@ impl<'a> LoweringContext<'a> { span: lifetime.span, name: name, }; - self.output_lifetime_defs.push(hir::LifetimeDef { + self.output_lifetime_params.push(hir::GenericParam::Lifetime(hir::LifetimeDef { lifetime: def_lifetime, bounds: Vec::new().into(), pure_wrt_drop: false, in_band: false, - }); + })); } } } @@ -1150,7 +1161,7 @@ impl<'a> LoweringContext<'a> { currently_bound_lifetimes: Vec::new(), already_defined_lifetimes: HashSet::new(), output_lifetimes: Vec::new(), - output_lifetime_defs: Vec::new(), + output_lifetime_params: Vec::new(), }; for bound in bounds { @@ -1159,7 +1170,7 @@ impl<'a> LoweringContext<'a> { ( lifetime_collector.output_lifetimes.into(), - lifetime_collector.output_lifetime_defs.into() + lifetime_collector.output_lifetime_params.into() ) } @@ -1568,13 +1579,6 @@ impl<'a> LoweringContext<'a> { } } - fn lower_ty_params(&mut self, tps: &Vec, add_bounds: &NodeMap>) - -> hir::HirVec { - tps.iter().map(|tp| { - self.lower_ty_param(tp, add_bounds.get(&tp.id).map_or(&[][..], |x| &x)) - }).collect() - } - fn lower_lifetime(&mut self, l: &Lifetime) -> hir::Lifetime { let name = match self.lower_ident(l.ident) { x if x == "'_" => hir::LifetimeName::Underscore, @@ -1620,12 +1624,31 @@ impl<'a> LoweringContext<'a> { lts.iter().map(|l| self.lower_lifetime(l)).collect() } - fn lower_lifetime_defs(&mut self, lts: &Vec) -> hir::HirVec { - lts.iter().map(|l| self.lower_lifetime_def(l)).collect() + fn lower_generic_params( + &mut self, + params: &Vec, + add_bounds: &NodeMap>, + ) -> hir::HirVec { + params.iter() + .map(|param| match *param { + GenericParam::Lifetime(ref lifetime_def) => { + hir::GenericParam::Lifetime(self.lower_lifetime_def(lifetime_def)) + } + GenericParam::Type(ref ty_param) => { + hir::GenericParam::Type(self.lower_ty_param( + ty_param, + add_bounds.get(&ty_param.id).map_or(&[][..], |x| &x) + )) + } + }) + .collect() } fn lower_generics(&mut self, g: &Generics) -> 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 { if let WherePredicate::BoundPredicate(ref bound_pred) = *pred { @@ -1640,17 +1663,20 @@ impl<'a> LoweringContext<'a> { match bound_pred.bounded_ty.node { TyKind::Path(None, ref path) if path.segments.len() == 1 && - bound_pred.bound_lifetimes.is_empty() => { + bound_pred.bound_generic_params.is_empty() => { if let Some(Def::TyParam(def_id)) = self.resolver.get_resolution(bound_pred.bounded_ty.id) .map(|d| d.base_def()) { if let Some(node_id) = self.resolver.definitions().as_local_node_id(def_id) { - for ty_param in &g.ty_params { - 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 &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; + } } } } @@ -1665,8 +1691,7 @@ impl<'a> LoweringContext<'a> { } hir::Generics { - ty_params: self.lower_ty_params(&g.ty_params, &add_bounds), - lifetimes: self.lower_lifetime_defs(&g.lifetimes), + params: self.lower_generic_params(&g.params, &add_bounds), where_clause: self.lower_where_clause(&g.where_clause), span: g.span, } @@ -1684,24 +1709,33 @@ impl<'a> LoweringContext<'a> { fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicate { match *pred { - WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_lifetimes, + WherePredicate::BoundPredicate(WhereBoundPredicate{ ref bound_generic_params, ref bounded_ty, ref bounds, span}) => { - self.with_in_scope_lifetime_defs(bound_lifetimes, |this| { - hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { - bound_lifetimes: this.lower_lifetime_defs(bound_lifetimes), - bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::Disallowed), - bounds: bounds.iter().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( - bound, ImplTraitContext::Disallowed)) - }).collect(), - span, - }) - }) + self.with_in_scope_lifetime_defs( + &bound_generic_params.iter() + .filter_map(|p| match *p { + GenericParam::Lifetime(ref ld) => Some(ld.clone()), + _ => None, + }) + .collect::>(), + |this| { + hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + bound_generic_params: + this.lower_generic_params(bound_generic_params, &NodeMap()), + bounded_ty: this.lower_ty(bounded_ty, ImplTraitContext::Disallowed), + bounds: bounds.iter().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( + bound, ImplTraitContext::Disallowed)) + }).collect(), + span, + }) + } + ) } WherePredicate::RegionPredicate(WhereRegionPredicate{ ref lifetime, ref bounds, @@ -1761,12 +1795,19 @@ impl<'a> LoweringContext<'a> { p: &PolyTraitRef, itctx: ImplTraitContext) -> hir::PolyTraitRef { - let bound_lifetimes = self.lower_lifetime_defs(&p.bound_lifetimes); - let trait_ref = self.with_parent_impl_lifetime_defs(&bound_lifetimes, - |this| this.lower_trait_ref(&p.trait_ref, itctx)); + let bound_generic_params = self.lower_generic_params(&p.bound_generic_params, &NodeMap()); + 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::>(), + |this| this.lower_trait_ref(&p.trait_ref, itctx), + ); hir::PolyTraitRef { - bound_lifetimes, + bound_generic_params, trait_ref, span: p.span, } @@ -1945,11 +1986,19 @@ impl<'a> LoweringContext<'a> { }); let new_impl_items = self.with_in_scope_lifetime_defs( - &ast_generics.lifetimes, |this| { - impl_items.iter() - .map(|item| this.lower_impl_item_ref(item)) - .collect() - }); + &ast_generics.params + .iter() + .filter_map(|p| match *p { + GenericParam::Lifetime(ref ld) => Some(ld.clone()), + _ => None, + }) + .collect::>(), + |this| { + impl_items.iter() + .map(|item| this.lower_impl_item_ref(item)) + .collect() + } + ); hir::ItemImpl(self.lower_unsafety(unsafety), @@ -3621,7 +3670,7 @@ impl<'a> LoweringContext<'a> { // Turn trait object paths into `TyTraitObject` instead. if let Def::Trait(_) = path.def { let principal = hir::PolyTraitRef { - bound_lifetimes: hir_vec![], + bound_generic_params: hir::HirVec::new(), trait_ref: hir::TraitRef { path: path.and_then(|path| path), ref_id: id.node_id, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 02a1e33eeb918..e3ca6f1591e72 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -326,7 +326,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_generics(&mut self, generics: &'hir Generics) { - for ty_param in generics.ty_params.iter() { + for ty_param in generics.ty_params() { self.insert(ty_param.id, NodeTyParam(ty_param)); } diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 2978f1eb409d8..002849c0399c3 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -183,14 +183,25 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { }); } - fn visit_generics(&mut self, generics: &'a Generics) { - for ty_param in generics.ty_params.iter() { - self.create_def(ty_param.id, - DefPathData::TypeParam(ty_param.ident.name.as_str()), - REGULAR_SPACE); + 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_str()), + REGULAR_SPACE + ); + } + GenericParam::Type(ref ty_param) => { + self.create_def( + ty_param.id, + DefPathData::TypeParam(ty_param.ident.name.as_str()), + REGULAR_SPACE + ); + } } - visit::walk_generics(self, generics); + visit::walk_generic_param(self, param); } fn visit_trait_item(&mut self, ti: &'a TraitItem) { @@ -268,12 +279,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { visit::walk_ty(self, ty); } - fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) { - self.create_def(def.lifetime.id, - DefPathData::LifetimeDef(def.lifetime.ident.name.as_str()), - REGULAR_SPACE); - } - fn visit_stmt(&mut self, stmt: &'a Stmt) { match stmt.node { StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id, false), diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 5e132865ca87d..ca2f3475fdb39 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -48,6 +48,8 @@ use rustc_data_structures::indexed_vec; 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 @@ -398,12 +400,67 @@ pub struct TyParam { pub synthetic: 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 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, + }) + } +} + /// Represents lifetimes and type parameters attached to a declaration /// of a function, enum, trait, etc. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Generics { - pub lifetimes: HirVec, - pub ty_params: HirVec, + pub params: HirVec, pub where_clause: WhereClause, pub span: Span, } @@ -411,8 +468,7 @@ pub struct Generics { impl Generics { pub fn empty() -> Generics { Generics { - lifetimes: HirVec::new(), - ty_params: HirVec::new(), + params: HirVec::new(), where_clause: WhereClause { id: DUMMY_NODE_ID, predicates: HirVec::new(), @@ -422,15 +478,19 @@ impl Generics { } pub fn is_lt_parameterized(&self) -> bool { - !self.lifetimes.is_empty() + self.params.iter().any(|param| param.is_lifetime_param()) } pub fn is_type_parameterized(&self) -> bool { - !self.ty_params.is_empty() + self.params.iter().any(|param| param.is_type_param()) + } + + pub fn lifetimes<'a>(&'a self) -> impl Iterator { + self.params.lifetimes() } - pub fn is_parameterized(&self) -> bool { - self.is_lt_parameterized() || self.is_type_parameterized() + pub fn ty_params<'a>(&'a self) -> impl Iterator { + self.params.ty_params() } } @@ -450,17 +510,22 @@ impl UnsafeGeneric { impl Generics { pub fn carries_unsafe_attr(&self) -> Option { - for r in &self.lifetimes { - if r.pure_wrt_drop { - return Some(UnsafeGeneric::Region(r.clone(), "may_dangle")); - } - } - for t in &self.ty_params { - if t.pure_wrt_drop { - return Some(UnsafeGeneric::Type(t.clone(), "may_dangle")); + 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")); + } + } } } - return None; + + None } } @@ -493,8 +558,8 @@ pub enum WherePredicate { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct WhereBoundPredicate { pub span: Span, - /// Any lifetimes from a `for` binding - pub bound_lifetimes: HirVec, + /// Any generics from a `for` binding + pub bound_generic_params: HirVec, /// The type being bounded pub bounded_ty: P, /// Trait and lifetime bounds (`Clone+Send+'static`) @@ -1475,7 +1540,7 @@ pub enum PrimTy { pub struct BareFnTy { pub unsafety: Unsafety, pub abi: Abi, - pub lifetimes: HirVec, + pub generic_params: HirVec, pub decl: P, pub arg_names: HirVec>, } @@ -1733,7 +1798,7 @@ pub struct TraitRef { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct PolyTraitRef { /// The `'a` in `<'a> Foo<&'a T>` - pub bound_lifetimes: HirVec, + pub bound_generic_params: HirVec, /// The `Foo<&'a T>` in `<'a> Foo<&'a T>` pub trait_ref: TraitRef, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 77469cb450bfa..2f9fc70252f8d 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -390,16 +390,7 @@ impl<'a> State<'a> { self.pclose()?; } hir::TyBareFn(ref f) => { - let generics = hir::Generics { - lifetimes: f.lifetimes.clone(), - ty_params: hir::HirVec::new(), - where_clause: hir::WhereClause { - id: ast::DUMMY_NODE_ID, - predicates: hir::HirVec::new(), - }, - span: syntax_pos::DUMMY_SP, - }; - self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics, + self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &f.generic_params, &f.arg_names[..])?; } hir::TyPath(ref qpath) => { @@ -635,15 +626,15 @@ impl<'a> State<'a> { self.s.word(&ga.asm.as_str())?; self.end()? } - hir::ItemTy(ref ty, ref params) => { + hir::ItemTy(ref ty, ref generics) => { self.ibox(indent_unit)?; self.ibox(0)?; self.word_nbsp(&visibility_qualified(&item.vis, "type"))?; self.print_name(item.name)?; - self.print_generics(params)?; + self.print_generic_params(&generics.params)?; self.end()?; // end the inner ibox - self.print_where_clause(¶ms.where_clause)?; + self.print_where_clause(&generics.where_clause)?; self.s.space()?; self.word_space("=")?; self.print_type(&ty)?; @@ -686,8 +677,8 @@ impl<'a> State<'a> { self.print_unsafety(unsafety)?; self.word_nbsp("impl")?; - if generics.is_parameterized() { - self.print_generics(generics)?; + if !generics.params.is_empty() { + self.print_generic_params(&generics.params)?; self.s.space()?; } @@ -725,7 +716,7 @@ impl<'a> State<'a> { self.print_unsafety(unsafety)?; self.word_nbsp("trait")?; self.print_name(item.name)?; - self.print_generics(generics)?; + 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 { @@ -750,7 +741,7 @@ impl<'a> State<'a> { self.print_visibility(&item.vis)?; self.word_nbsp("trait")?; self.print_name(item.name)?; - self.print_generics(generics)?; + self.print_generic_params(&generics.params)?; let mut real_bounds = Vec::with_capacity(bounds.len()); // FIXME(durka) this seems to be some quite outdated syntax for b in bounds.iter() { @@ -775,25 +766,20 @@ impl<'a> State<'a> { self.print_path(&t.path, false) } - fn print_formal_lifetime_list(&mut self, lifetimes: &[hir::LifetimeDef]) -> io::Result<()> { - if !lifetimes.is_empty() { - self.s.word("for<")?; - let mut comma = false; - for lifetime_def in lifetimes { - if comma { - self.word_space(",")? - } - self.print_lifetime_def(lifetime_def)?; - comma = true; - } - self.s.word(">")?; + fn print_formal_generic_params( + &mut self, + generic_params: &[hir::GenericParam] + ) -> io::Result<()> { + if !generic_params.is_empty() { + self.s.word("for")?; + self.print_generic_params(generic_params)?; self.nbsp()?; } Ok(()) } fn print_poly_trait_ref(&mut self, t: &hir::PolyTraitRef) -> io::Result<()> { - self.print_formal_lifetime_list(&t.bound_lifetimes)?; + self.print_formal_generic_params(&t.bound_generic_params)?; self.print_trait_ref(&t.trait_ref) } @@ -806,7 +792,7 @@ impl<'a> State<'a> { -> io::Result<()> { self.head(&visibility_qualified(visibility, "enum"))?; self.print_name(name)?; - self.print_generics(generics)?; + self.print_generic_params(&generics.params)?; self.print_where_clause(&generics.where_clause)?; self.s.space()?; self.print_variants(&enum_definition.variants, span) @@ -859,7 +845,7 @@ impl<'a> State<'a> { print_finalizer: bool) -> io::Result<()> { self.print_name(name)?; - self.print_generics(generics)?; + self.print_generic_params(&generics.params)?; if !struct_def.is_struct() { if struct_def.is_tuple() { self.popen()?; @@ -1941,7 +1927,7 @@ impl<'a> State<'a> { self.nbsp()?; self.print_name(name)?; } - self.print_generics(generics)?; + self.print_generic_params(&generics.params)?; self.popen()?; let mut i = 0; @@ -2056,31 +2042,19 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_generics(&mut self, generics: &hir::Generics) -> io::Result<()> { - let total = generics.lifetimes.len() + generics.ty_params.len(); - if total == 0 { - return Ok(()); - } + pub fn print_generic_params(&mut self, generic_params: &[hir::GenericParam]) -> io::Result<()> { + if !generic_params.is_empty() { + self.s.word("<")?; - 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), + } + })?; - let mut ints = Vec::new(); - for i in 0..total { - ints.push(i); + self.s.word(">")?; } - - self.commasep(Inconsistent, &ints[..], |s, &idx| { - if idx < generics.lifetimes.len() { - let lifetime = &generics.lifetimes[idx]; - s.print_lifetime_def(lifetime) - } else { - let idx = idx - generics.lifetimes.len(); - let param = &generics.ty_params[idx]; - s.print_ty_param(param) - } - })?; - - self.s.word(">")?; Ok(()) } @@ -2111,11 +2085,13 @@ impl<'a> State<'a> { } match predicate { - &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate{ref bound_lifetimes, - ref bounded_ty, - ref bounds, - ..}) => { - self.print_formal_lifetime_list(bound_lifetimes)?; + &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { + ref bound_generic_params, + ref bounded_ty, + ref bounds, + .. + }) => { + self.print_formal_generic_params(bound_generic_params)?; self.print_type(&bounded_ty)?; self.print_bounds(":", bounds)?; } @@ -2184,17 +2160,16 @@ impl<'a> State<'a> { unsafety: hir::Unsafety, decl: &hir::FnDecl, name: Option, - generics: &hir::Generics, + generic_params: &[hir::GenericParam], arg_names: &[Spanned]) -> io::Result<()> { self.ibox(indent_unit)?; - if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { + if !generic_params.is_empty() { self.s.word("for")?; - self.print_generics(generics)?; + self.print_generic_params(generic_params)?; } let generics = hir::Generics { - lifetimes: hir::HirVec::new(), - ty_params: hir::HirVec::new(), + params: hir::HirVec::new(), where_clause: hir::WhereClause { id: ast::DUMMY_NODE_ID, predicates: hir::HirVec::new(), diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 02a394f9634c2..bddbdec2c34ac 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -200,9 +200,13 @@ impl_stable_hash_for!(struct hir::TyParam { synthetic }); +impl_stable_hash_for!(enum hir::GenericParam { + Lifetime(lifetime_def), + Type(ty_param) +}); + impl_stable_hash_for!(struct hir::Generics { - lifetimes, - ty_params, + params, where_clause, span }); @@ -224,7 +228,7 @@ impl_stable_hash_for!(enum hir::WherePredicate { impl_stable_hash_for!(struct hir::WhereBoundPredicate { span, - bound_lifetimes, + bound_generic_params, bounded_ty, bounds }); @@ -291,7 +295,7 @@ impl_stable_hash_for!(enum hir::PrimTy { impl_stable_hash_for!(struct hir::BareFnTy { unsafety, abi, - lifetimes, + generic_params, decl, arg_names }); @@ -345,7 +349,7 @@ impl<'gcx> HashStable> for hir::TraitRef { impl_stable_hash_for!(struct hir::PolyTraitRef { - bound_lifetimes, + bound_generic_params, trait_ref, span }); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 75cd230e1e5e2..32ab458cb91de 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -783,6 +783,11 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { hir_visit::walk_decl(self, d); } + fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam) { + run_lints!(self, check_generic_param, late_passes, p); + hir_visit::walk_generic_param(self, p); + } + fn visit_generics(&mut self, g: &'tcx hir::Generics) { run_lints!(self, check_generics, late_passes, g); hir_visit::walk_generics(self, g); @@ -819,11 +824,6 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { hir_visit::walk_lifetime(self, lt); } - fn visit_lifetime_def(&mut self, lt: &'tcx hir::LifetimeDef) { - run_lints!(self, check_lifetime_def, late_passes, lt); - hir_visit::walk_lifetime_def(self, lt); - } - fn visit_path(&mut self, p: &'tcx hir::Path, id: ast::NodeId) { run_lints!(self, check_path, late_passes, p, id); hir_visit::walk_path(self, p); @@ -945,6 +945,11 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { run_lints!(self, check_expr_post, early_passes, e); } + fn visit_generic_param(&mut self, param: &'a ast::GenericParam) { + run_lints!(self, check_generic_param, early_passes, param); + ast_visit::walk_generic_param(self, param); + } + fn visit_generics(&mut self, g: &'a ast::Generics) { run_lints!(self, check_generics, early_passes, g); ast_visit::walk_generics(self, g); @@ -971,10 +976,6 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> { self.check_id(lt.id); } - fn visit_lifetime_def(&mut self, lt: &'a ast::LifetimeDef) { - run_lints!(self, check_lifetime_def, early_passes, lt); - } - fn visit_path(&mut self, p: &'a ast::Path, id: ast::NodeId) { run_lints!(self, check_path, early_passes, p, id); self.check_id(id); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index f0761ce617865..f4abc54ad2e4e 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -155,6 +155,7 @@ pub trait LateLintPass<'a, 'tcx>: LintPass { fn check_expr(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Expr) { } fn check_expr_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Expr) { } fn check_ty(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Ty) { } + fn check_generic_param(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::GenericParam) { } fn check_generics(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Generics) { } fn check_fn(&mut self, _: &LateContext<'a, 'tcx>, @@ -196,7 +197,6 @@ pub trait LateLintPass<'a, 'tcx>: LintPass { _: &'tcx hir::Variant, _: &'tcx hir::Generics) { } fn check_lifetime(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Lifetime) { } - fn check_lifetime_def(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::LifetimeDef) { } fn check_path(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Path, _: ast::NodeId) { } fn check_attribute(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx ast::Attribute) { } @@ -227,6 +227,7 @@ pub trait EarlyLintPass: LintPass { fn check_expr(&mut self, _: &EarlyContext, _: &ast::Expr) { } fn check_expr_post(&mut self, _: &EarlyContext, _: &ast::Expr) { } fn check_ty(&mut self, _: &EarlyContext, _: &ast::Ty) { } + fn check_generic_param(&mut self, _: &EarlyContext, _: &ast::GenericParam) { } fn check_generics(&mut self, _: &EarlyContext, _: &ast::Generics) { } fn check_fn(&mut self, _: &EarlyContext, _: ast_visit::FnKind, _: &ast::FnDecl, _: Span, _: ast::NodeId) { } @@ -244,7 +245,6 @@ pub trait EarlyLintPass: LintPass { fn check_variant(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } fn check_variant_post(&mut self, _: &EarlyContext, _: &ast::Variant, _: &ast::Generics) { } fn check_lifetime(&mut self, _: &EarlyContext, _: &ast::Lifetime) { } - fn check_lifetime_def(&mut self, _: &EarlyContext, _: &ast::LifetimeDef) { } fn check_path(&mut self, _: &EarlyContext, _: &ast::Path, _: ast::NodeId) { } fn check_attribute(&mut self, _: &EarlyContext, _: &ast::Attribute) { } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 27f12c2c1587e..6f457c9d1e1b2 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -37,7 +37,7 @@ 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.ty_params.is_empty() + generics.params.iter().any(|param| param.is_type_param()) } // Returns true if the given item must be inlined because it may be diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index e976f08607a89..8b302dbe67a42 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -33,7 +33,7 @@ use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap, NodeSet}; use std::slice; use rustc::lint; -use hir; +use hir::{self, GenericParamsExt}; use hir::intravisit::{self, NestedVisitorMap, Visitor}; /// The origin of a named lifetime definition. @@ -491,19 +491,17 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } else { 0 }; - let lifetimes = generics - .lifetimes - .iter() + let lifetimes = generics.lifetimes() .map(|def| Region::early(&self.tcx.hir, &mut index, def)) .collect(); - let next_early_index = index + generics.ty_params.len() as u32; + let next_early_index = index + generics.ty_params().count() as u32; let scope = Scope::Binder { lifetimes, next_early_index, s: ROOT_SCOPE, }; self.with(scope, |old_scope, this| { - this.check_lifetime_defs(old_scope, &generics.lifetimes); + this.check_lifetime_params(old_scope, &generics.params); intravisit::walk_item(this, item); }); } @@ -537,8 +535,8 @@ 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.lifetimes - .iter() + lifetimes: c.generic_params + .lifetimes() .map(|def| Region::late(&self.tcx.hir, def)) .collect(), s: self.scope, @@ -547,7 +545,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { self.with(scope, |old_scope, this| { // a bare fn has no bounds, so everything // contained within is scoped within its binder. - this.check_lifetime_defs(old_scope, &c.lifetimes); + this.check_lifetime_params(old_scope, &c.generic_params); intravisit::walk_ty(this, ty); }); self.is_in_fn_syntax = was_in_fn_syntax; @@ -621,7 +619,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let mut elision = None; let mut lifetimes = FxHashMap(); - for lt_def in &generics.lifetimes { + 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 @@ -632,7 +630,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } } - let next_early_index = index + generics.ty_params.len() as u32; + let next_early_index = index + generics.ty_params().count() as u32; if let Some(elision_region) = elision { let scope = Scope::Elision { @@ -678,11 +676,11 @@ 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.iter() + 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.len() as u32; + let next_early_index = index + generics.ty_params().count() as u32; let scope = Scope::Binder { lifetimes, next_early_index, s: self.scope }; self.with(scope, |_old_scope, this| { this.visit_generics(generics); @@ -696,7 +694,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }, Const(_, _) => { // Only methods and types support generics. - assert!(!trait_item.generics.is_parameterized()); + assert!(trait_item.generics.params.is_empty()); intravisit::walk_trait_item(self, trait_item); }, } @@ -718,11 +716,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let generics = &impl_item.generics; let mut index = self.next_early_index(); debug!("visit_ty: index = {}", index); - let lifetimes = generics.lifetimes.iter() + 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.len() as u32; + let next_early_index = index + generics.ty_params().count() as u32; let scope = Scope::Binder { lifetimes, next_early_index, s: self.scope }; self.with(scope, |_old_scope, this| { this.visit_generics(generics); @@ -731,7 +729,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }, Const(_, _) => { // Only methods and types support generics. - assert!(!impl_item.generics.is_parameterized()); + assert!(impl_item.generics.params.is_empty()); intravisit::walk_impl_item(self, impl_item); }, } @@ -767,8 +765,11 @@ 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); - for ty_param in generics.ty_params.iter() { + 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); @@ -779,22 +780,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { &hir::WherePredicate::BoundPredicate(hir::WhereBoundPredicate { ref bounded_ty, ref bounds, - ref bound_lifetimes, + ref bound_generic_params, .. }) => { - if !bound_lifetimes.is_empty() { + if bound_generic_params.iter().any(|p| p.is_lifetime_param()) { self.trait_ref_hack = true; let next_early_index = self.next_early_index(); let scope = Scope::Binder { - lifetimes: bound_lifetimes - .iter() + lifetimes: bound_generic_params.lifetimes() .map(|def| Region::late(&self.tcx.hir, def)) .collect(), s: self.scope, next_early_index, }; let result = self.with(scope, |old_scope, this| { - this.check_lifetime_defs(old_scope, bound_lifetimes); + this.check_lifetime_params(old_scope, &bound_generic_params); this.visit_ty(&bounded_ty); walk_list!(this, visit_ty_param_bound, bounds); }); @@ -834,7 +834,9 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { ) { debug!("visit_poly_trait_ref trait_ref={:?}", trait_ref); - if !self.trait_ref_hack || !trait_ref.bound_lifetimes.is_empty() { + if !self.trait_ref_hack || + trait_ref.bound_generic_params.iter().any(|p| p.is_lifetime_param()) + { if self.trait_ref_hack { span_err!( self.tcx.sess, @@ -845,19 +847,16 @@ 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_lifetimes - .iter() + lifetimes: trait_ref.bound_generic_params + .lifetimes() .map(|def| Region::late(&self.tcx.hir, def)) .collect(), s: self.scope, next_early_index, }; self.with(scope, |old_scope, this| { - this.check_lifetime_defs(old_scope, &trait_ref.bound_lifetimes); - for lifetime in &trait_ref.bound_lifetimes { - this.visit_lifetime_def(lifetime); - } + this.check_lifetime_params(old_scope, &trait_ref.bound_generic_params); + walk_list!(this, visit_generic_param, &trait_ref.bound_generic_params); this.visit_trait_ref(&trait_ref.trait_ref) }) } else { @@ -1087,8 +1086,9 @@ 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 - [i as usize] + Set1::One(Region::EarlyBound(i, _, _)) => generics.lifetimes() + .nth(i as usize) + .unwrap() .lifetime .name .name() @@ -1124,9 +1124,7 @@ fn object_lifetime_defaults_for_item( } } - generics - .ty_params - .iter() + generics.ty_params() .map(|param| { let mut set = Set1::Empty; @@ -1142,7 +1140,7 @@ fn object_lifetime_defaults_for_item( // Ignore `for<'a> type: ...` as they can change what // lifetimes mean (although we could "just" handle it). - if !data.bound_lifetimes.is_empty() { + if !data.bound_generic_params.is_empty() { continue; } @@ -1163,8 +1161,7 @@ fn object_lifetime_defaults_for_item( Set1::One(Region::Static) } else { generics - .lifetimes - .iter() + .lifetimes() .enumerate() .find(|&(_, def)| def.lifetime.name == name) .map_or(Set1::Many, |(i, def)| { @@ -1283,15 +1280,14 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { match parent.node { hir::ItemTrait(_, _, ref generics, ..) | hir::ItemImpl(_, _, _, ref generics, ..) => { - index += (generics.lifetimes.len() + generics.ty_params.len()) as u32; + index += generics.params.len() as u32; } _ => {} } } let lifetimes = generics - .lifetimes - .iter() + .lifetimes() .map(|def| { if self.map.late_bound.contains(&def.lifetime.id) { Region::late(&self.tcx.hir, def) @@ -1301,7 +1297,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { }) .collect(); - let next_early_index = index + generics.ty_params.len() as u32; + let next_early_index = index + generics.ty_params().count() as u32; let scope = Scope::Binder { lifetimes, @@ -1309,7 +1305,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { s: self.scope, }; self.with(scope, move |old_scope, this| { - this.check_lifetime_defs(old_scope, &generics.lifetimes); + this.check_lifetime_params(old_scope, &generics.params); this.hack(walk); // FIXME(#37666) workaround in place of `walk(this)` }); } @@ -1769,6 +1765,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } + fn visit_generic_param(&mut self, param: &hir::GenericParam) { + if let hir::GenericParam::Lifetime(ref lifetime_def) = *param { + for l in &lifetime_def.bounds { + self.visit_lifetime(l); + } + } + + intravisit::walk_generic_param(self, param); + } + fn visit_poly_trait_ref( &mut self, trait_ref: &hir::PolyTraitRef, @@ -1779,12 +1785,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { self.binder_depth -= 1; } - fn visit_lifetime_def(&mut self, lifetime_def: &hir::LifetimeDef) { - for l in &lifetime_def.bounds { - self.visit_lifetime(l); - } - } - fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) { if let Some(&lifetime) = self.map.defs.get(&lifetime_ref.id) { match lifetime { @@ -1980,11 +1980,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth)); } - fn check_lifetime_defs(&mut self, old_scope: ScopeRef, lifetimes: &'tcx [hir::LifetimeDef]) { - for i in 0..lifetimes.len() { - let lifetime_i = &lifetimes[i]; - - for lifetime in lifetimes { + fn check_lifetime_params(&mut self, old_scope: ScopeRef, params: &'tcx [hir::GenericParam]) { + for (i, lifetime_i) in params.lifetimes().enumerate() { + for lifetime in params.lifetimes() { match lifetime.lifetime.name { hir::LifetimeName::Static | hir::LifetimeName::Underscore => { let lifetime = lifetime.lifetime; @@ -2007,9 +2005,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } // It is a hard error to shadow a lifetime within the same scope. - for j in i + 1..lifetimes.len() { - let lifetime_j = &lifetimes[j]; - + for lifetime_j in params.lifetimes().skip(i + 1) { if lifetime_i.lifetime.name == lifetime_j.lifetime.name { struct_span_err!( self.tcx.sess, @@ -2200,24 +2196,30 @@ fn insert_late_bound_lifetimes( let mut appears_in_where_clause = AllCollector { regions: FxHashSet(), }; - for ty_param in generics.ty_params.iter() { - walk_list!( - &mut appears_in_where_clause, - visit_ty_param_bound, - &ty_param.bounds - ); + + for param in &generics.params { + match *param { + hir::GenericParam::Lifetime(ref lifetime_def) => { + if !lifetime_def.bounds.is_empty() { + // `'a: 'b` means both `'a` and `'b` are referenced + appears_in_where_clause.visit_generic_param(param); + } + } + hir::GenericParam::Type(ref ty_param) => { + walk_list!( + &mut appears_in_where_clause, + visit_ty_param_bound, + &ty_param.bounds + ); + } + } } + walk_list!( &mut appears_in_where_clause, visit_where_predicate, &generics.where_clause.predicates ); - for lifetime_def in &generics.lifetimes { - if !lifetime_def.bounds.is_empty() { - // `'a: 'b` means both `'a` and `'b` are referenced - appears_in_where_clause.visit_lifetime_def(lifetime_def); - } - } debug!( "insert_late_bound_lifetimes: appears_in_where_clause={:?}", @@ -2228,7 +2230,7 @@ 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 { + for lifetime in generics.lifetimes() { let name = lifetime.lifetime.name; // appears in the where clauses? early-bound. diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs index d14a6943fc112..49f14e8484f3a 100644 --- a/src/librustc_lint/bad_style.rs +++ b/src/librustc_lint/bad_style.rs @@ -126,8 +126,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonCamelCaseTypes { self.check_case(cx, "variant", v.node.name, v.span); } - fn check_generics(&mut self, cx: &LateContext, it: &hir::Generics) { - for gen in it.ty_params.iter() { + fn check_generic_param(&mut self, cx: &LateContext, param: &hir::GenericParam) { + if let hir::GenericParam::Type(ref gen) = *param { self.check_case(cx, "type parameter", gen.name, gen.span); } } @@ -232,6 +232,17 @@ 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) + ); + } + } + fn check_fn(&mut self, cx: &LateContext, fk: FnKind, @@ -280,13 +291,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } } - fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) { - self.check_snake_case(cx, - "lifetime", - &t.lifetime.name.name().as_str(), - Some(t.lifetime.span)); - } - fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) { if let &PatKind::Binding(_, _, ref path1, _) = &p.node { self.check_snake_case(cx, "variable", &path1.node.as_str(), Some(p.span)); diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 5417634144bb3..81db44b055311 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -507,21 +507,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations { } let (def, ty) = match item.node { hir::ItemStruct(_, ref ast_generics) => { - if ast_generics.is_parameterized() { + if !ast_generics.params.is_empty() { return; } let def = cx.tcx.adt_def(cx.tcx.hir.local_def_id(item.id)); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } hir::ItemUnion(_, ref ast_generics) => { - if ast_generics.is_parameterized() { + if !ast_generics.params.is_empty() { return; } let def = cx.tcx.adt_def(cx.tcx.hir.local_def_id(item.id)); (def, cx.tcx.mk_adt(def, cx.tcx.intern_substs(&[]))) } hir::ItemEnum(_, ref ast_generics) => { - if ast_generics.is_parameterized() { + if !ast_generics.params.is_empty() { return; } let def = cx.tcx.adt_def(cx.tcx.hir.local_def_id(item.id)); diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 1356574f646aa..c109a47f79867 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -744,7 +744,7 @@ 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.ty_params.is_empty() { + 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); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 5e8bbabee4a9a..29369f9f8bb41 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1078,8 +1078,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } hir::ItemConst(..) => self.encode_optimized_mir(def_id), hir::ItemFn(_, _, constness, _, ref generics, _) => { - let tps_len = generics.ty_params.len(); - let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs); + let has_tps = generics.ty_params().next().is_some(); + let needs_inline = has_tps || attr::requests_inline(&item.attrs); let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; if needs_inline || constness == hir::Constness::Const || always_encode_mir { self.encode_optimized_mir(def_id) @@ -1480,7 +1480,7 @@ 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 { + 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)); diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 44dedde522941..0d9976afb9e3d 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -922,7 +922,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> { hir::ItemEnum(_, ref generics) | hir::ItemStruct(_, ref generics) | hir::ItemUnion(_, ref generics) => { - if !generics.is_parameterized() { + if generics.params.is_empty() { if self.mode == MonoItemCollectionMode::Eager { let def_id = self.tcx.hir.local_def_id(item.id); debug!("RootCollector: ADT drop-glue for {}", diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 96c9323e7dc73..d74a8af921bea 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -250,7 +250,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.ty_params.is_empty() { + if generics.is_parameterized() { self.err_handler().span_err(item.span, "auto traits cannot have generics"); } @@ -283,17 +283,25 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } - ItemKind::TraitAlias(Generics { ref ty_params, .. }, ..) => { - for &TyParam { ref bounds, ref default, span, .. } in ty_params { - if !bounds.is_empty() { - self.err_handler().span_err(span, - "type parameters on the left side of a \ - trait alias cannot be bounded"); - } - if !default.is_none() { - self.err_handler().span_err(span, - "type parameters on the left side of a \ - trait alias cannot have defaults"); + ItemKind::TraitAlias(Generics { ref params, .. }, ..) => { + for param in params { + if let GenericParam::Type(TyParam { + ref bounds, + ref default, + span, + .. + }) = *param + { + if !bounds.is_empty() { + self.err_handler().span_err(span, + "type parameters on the left side of a \ + trait alias cannot be bounded"); + } + if !default.is_none() { + self.err_handler().span_err(span, + "type parameters on the left side of a \ + trait alias cannot have defaults"); + } } } } @@ -352,9 +360,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_generics(&mut self, g: &'a Generics) { + let mut seen_non_lifetime_param = false; let mut seen_default = None; - for ty_param in &g.ty_params { - if ty_param.default.is_some() { + for param in &g.params { + match (param, seen_non_lifetime_param) { + (&GenericParam::Lifetime(ref ld), true) => { + self.err_handler() + .span_err(ld.lifetime.span, "lifetime parameters must be leading"); + }, + (&GenericParam::Lifetime(_), false) => {} + _ => { + seen_non_lifetime_param = true; + } + } + + if let GenericParam::Type(ref ty_param @ TyParam { default: Some(_), .. }) = *param { seen_default = Some(ty_param.span); } else if let Some(span) = seen_default { self.err_handler() diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index 6f93fa133b9e4..ba0be974b2771 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -224,10 +224,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { self.record("Lifetime", Id::Node(lifetime.id), lifetime); hir_visit::walk_lifetime(self, lifetime) } - fn visit_lifetime_def(&mut self, lifetime: &'v hir::LifetimeDef) { - self.record("LifetimeDef", Id::None, lifetime); - hir_visit::walk_lifetime_def(self, lifetime) - } fn visit_qpath(&mut self, qpath: &'v hir::QPath, id: NodeId, span: Span) { self.record("QPath", Id::None, qpath); hir_visit::walk_qpath(self, qpath, id, span) @@ -349,11 +345,6 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { ast_visit::walk_lifetime(self, lifetime) } - fn visit_lifetime_def(&mut self, lifetime: &'v ast::LifetimeDef) { - self.record("LifetimeDef", Id::None, lifetime); - ast_visit::walk_lifetime_def(self, lifetime) - } - fn visit_mac(&mut self, mac: &'v ast::Mac) { self.record("Mac", Id::None, mac); } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 5b277402f1e03..bb0a4be49c2a8 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1236,7 +1236,7 @@ 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.iter() { + for ty_param in generics.ty_params() { for bound in ty_param.bounds.iter() { self.check_ty_param_bound(bound) } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 864a61108b1d3..b57a8bc7e77f1 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -53,7 +53,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, Generics}; +use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParam, Generics}; use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; use syntax::ast::{Local, Mutability, Pat, PatKind, Path}; use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind}; @@ -790,25 +790,30 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { // to following type parameters, as the Substs can only // provide previous type parameters as they're built. let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind); - default_ban_rib.bindings.extend(generics.ty_params.iter() + 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))); - for param in &generics.ty_params { - for bound in ¶m.bounds { - self.visit_ty_param_bound(bound); - } + 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); + } - if let Some(ref ty) = param.default { - self.ribs[TypeNS].push(default_ban_rib); - self.visit_ty(ty); - default_ban_rib = self.ribs[TypeNS].pop().unwrap(); - } + if let Some(ref ty) = ty_param.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(param.ident.name)); + // Allow all following defaults to refer to this type parameter. + default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(ty_param.ident.name)); + } + } } - for lt in &generics.lifetimes { self.visit_lifetime_def(lt); } for p in &generics.where_clause.predicates { self.visit_where_predicate(p); } } } @@ -2022,23 +2027,27 @@ impl<'a> Resolver<'a> { HasTypeParameters(generics, rib_kind) => { let mut function_type_rib = Rib::new(rib_kind); let mut seen_bindings = FxHashMap(); - for type_parameter in &generics.ty_params { - let ident = type_parameter.ident.modern(); - debug!("with_type_parameter_rib: {}", type_parameter.id); - - if seen_bindings.contains_key(&ident) { - let span = seen_bindings.get(&ident).unwrap(); - let err = - ResolutionError::NameAlreadyUsedInTypeParameterList(ident.name, span); - resolve_error(self, type_parameter.span, err); - } - seen_bindings.entry(ident).or_insert(type_parameter.span); + 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); + + if seen_bindings.contains_key(&ident) { + let span = seen_bindings.get(&ident).unwrap(); + let err = ResolutionError::NameAlreadyUsedInTypeParameterList( + ident.name, + span, + ); + resolve_error(self, type_parameter.span, err); + } + seen_bindings.entry(ident).or_insert(type_parameter.span); - // plain insert (no renaming) - let def_id = self.definitions.local_def_id(type_parameter.id); - let def = Def::TyParam(def_id); - function_type_rib.bindings.insert(ident, def); - self.record_def(type_parameter.id, PathResolution::new(def)); + // plain insert (no renaming) + let def_id = self.definitions.local_def_id(type_parameter.id); + let def = Def::TyParam(def_id); + function_type_rib.bindings.insert(ident, def); + self.record_def(type_parameter.id, PathResolution::new(def)); + } } self.ribs[TypeNS].push(function_type_rib); } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 11e2135d2de36..ed3b8eadad74c 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -36,7 +36,12 @@ use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID}; use syntax::parse::token; use syntax::symbol::keywords; use syntax::visit::{self, Visitor}; -use syntax::print::pprust::{bounds_to_string, generics_to_string, path_to_string, ty_to_string}; +use syntax::print::pprust::{ + bounds_to_string, + generic_params_to_string, + path_to_string, + ty_to_string +}; use syntax::ptr::P; use syntax::codemap::{Spanned, DUMMY_SP}; use syntax_pos::*; @@ -438,35 +443,37 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { prefix: &str, id: NodeId, ) { - for param in &generics.ty_params { - let param_ss = param.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); + for param in &generics.params { + if let ast::GenericParam::Type(ref ty_param) = *param { + let param_ss = ty_param.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); - 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![], + }, + ); + } } } self.visit_generics(generics); @@ -787,8 +794,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let name = item.ident.to_string(); let qualname = format!("::{}", self.tcx.node_path_str(item.id)); let mut val = name.clone(); - if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { - val.push_str(&generics_to_string(generics)); + if !generics.params.is_empty() { + val.push_str(&generic_params_to_string(&generics.params)); } if !trait_refs.is_empty() { val.push_str(": "); @@ -1478,14 +1485,16 @@ 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.ty_params.iter() { - for bound in param.bounds.iter() { - if let ast::TraitTyParamBound(ref trait_ref, _) = *bound { - self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path) + 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 { + self.process_path(trait_ref.trait_ref.ref_id, &trait_ref.trait_ref.path) + } + } + if let Some(ref ty) = ty_param.default { + self.visit_ty(&ty); } - } - if let Some(ref ty) = param.default { - self.visit_ty(&ty); } } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 97f77b20f8114..93fb22a2dc0c9 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -886,21 +886,15 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String { let mut sig = "fn ".to_owned(); - if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { + if !generics.params.is_empty() { sig.push('<'); sig.push_str(&generics - .lifetimes + .params .iter() - .map(|l| l.lifetime.ident.name.to_string()) - .collect::>() - .join(", ")); - if !generics.lifetimes.is_empty() { - sig.push_str(", "); - } - sig.push_str(&generics - .ty_params - .iter() - .map(|l| l.ident.to_string()) + .map(|param| match *param { + ast::GenericParam::Lifetime(ref l) => l.lifetime.ident.name.to_string(), + ast::GenericParam::Type(ref t) => t.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 11d17e0227fdf..9211ddfab671e 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -218,12 +218,17 @@ impl Sig for ast::Ty { } ast::TyKind::BareFn(ref f) => { let mut text = String::new(); - if !f.lifetimes.is_empty() { + if !f.generic_params.is_empty() { // FIXME defs, bounds on lifetimes text.push_str("for<"); - text.push_str(&f.lifetimes + text.push_str(&f.generic_params .iter() - .map(|l| l.lifetime.ident.to_string()) + .filter_map(|p| match *p { + ast::GenericParam::Lifetime(ref l) => { + Some(l.lifetime.ident.to_string()) + } + _ => None, + }) .collect::>() .join(", ")); text.push('>'); @@ -615,50 +620,53 @@ impl Sig for ast::Path { // This does not cover the where clause, which must be processed separately. impl Sig for ast::Generics { fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext) -> Result { - let total = self.lifetimes.len() + self.ty_params.len(); - if total == 0 { + if self.params.is_empty() { return Ok(text_sig(String::new())); } let mut text = "<".to_owned(); let mut defs = vec![]; - for l in &self.lifetimes { - 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()) - .collect::>() - .join(" + "); - l_text.push_str(&bounds); - // FIXME add lifetime bounds refs. - } - text.push_str(&l_text); - text.push(','); - } - for t in &self.ty_params { - 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(), - }); + 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()) + .collect::>() + .join(" + "); + l_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)); - // FIXME descend properly into bounds. + if !t.bounds.is_empty() { + t_text.push_str(": "); + t_text.push_str(&pprust::bounds_to_string(&t.bounds)); + // FIXME descend properly into bounds. + } + text.push_str(&t_text); + text.push(','); + } } - text.push_str(&t_text); - text.push(','); } text.push('>'); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 70607bf4842a5..734287f5f7d29 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -562,10 +562,10 @@ fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if num_impl_m_type_params != num_trait_m_type_params { let impl_m_node_id = tcx.hir.as_local_node_id(impl_m.def_id).unwrap(); let impl_m_item = tcx.hir.expect_impl_item(impl_m_node_id); - let span = if impl_m_item.generics.is_parameterized() { - impl_m_item.generics.span - } else { + let span = if impl_m_item.generics.params.is_empty() { impl_m_span + } else { + impl_m_item.generics.span }; let mut err = struct_span_err!(tcx.sess, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 14296e78ddd1c..77272b18f13b4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4949,16 +4949,18 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, generics: &hir::Generics, ty: Ty<'tcx>) { debug!("check_bounds_are_used(n_tps={}, ty={:?})", - generics.ty_params.len(), ty); + generics.ty_params().count(), ty); // make a vector of booleans initially false, set to true when used - if generics.ty_params.is_empty() { return; } - let mut tps_used = vec![false; generics.ty_params.len()]; + if generics.ty_params().next().is_none() { return; } + let mut tps_used = vec![false; generics.ty_params().count()]; + + let lifetime_count = generics.lifetimes().count(); for leaf_ty in ty.walk() { if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty { debug!("Found use of ty param num {}", idx); - tps_used[idx as usize - generics.lifetimes.len()] = true; + tps_used[idx as usize - lifetime_count] = 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 assert!(tcx.sess.err_count() > 0); @@ -4966,7 +4968,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } } - for (&used, param) in tps_used.iter().zip(&generics.ty_params) { + for (&used, param) in tps_used.iter().zip(generics.ty_params()) { if !used { struct_span_err!(tcx.sess, param.span, E0091, "type parameter `{}` is unused", diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index e65ae6a1b4db3..385b9321db71a 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -592,13 +592,9 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { continue; } - let (span, name) = if index < ast_generics.lifetimes.len() { - (ast_generics.lifetimes[index].lifetime.span, - ast_generics.lifetimes[index].lifetime.name.name()) - } else { - let index = index - ast_generics.lifetimes.len(); - (ast_generics.ty_params[index].span, - ast_generics.ty_params[index].name) + 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), }; self.report_bivariance(span, name); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index f51bdf050c715..0a6d87e5a60b7 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -111,7 +111,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> { } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { - for param in &generics.ty_params { + 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); @@ -315,8 +315,7 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { -> Vec> { let from_ty_params = - ast_generics.ty_params - .iter() + ast_generics.ty_params() .filter(|p| p.id == param_id) .flat_map(|p| p.bounds.iter()) .flat_map(|b| predicates_from_bound(self, ty, b)); @@ -365,7 +364,7 @@ fn ensure_no_ty_param_bounds(tcx: TyCtxt, thing: &'static str) { let mut warn = false; - for ty_param in generics.ty_params.iter() { + for ty_param in generics.ty_params() { for bound in ty_param.bounds.iter() { match *bound { hir::TraitTyParamBound(..) => { @@ -804,7 +803,7 @@ fn has_late_bound_regions<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut visitor = LateBoundRegionsDetector { tcx, binder_depth: 1, has_late_bound_regions: None }; - for lifetime in &generics.lifetimes { + 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); @@ -964,7 +963,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Now create the real type parameters. let type_start = own_start + regions.len() as u32; - let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| { + let types = 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"); } @@ -1359,8 +1358,7 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>( -> impl Iterator { ast_generics - .lifetimes - .iter() + .lifetimes() .filter(move |l| { let hir_id = tcx.hir.node_to_hir_id(l.lifetime.id); !tcx.is_late_bound(hir_id) @@ -1492,7 +1490,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). - for param in &ast_generics.ty_params { + for param in ast_generics.ty_params() { let param_ty = ty::ParamTy::new(index, param.name).to_ty(tcx); index += 1; diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 15708ab766ae8..1eed1bf4b71fb 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -105,7 +105,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx, &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters); // Disallow ANY unconstrained type parameters. - for (ty_param, param) in impl_generics.types.iter().zip(&impl_hir_generics.ty_params) { + for (ty_param, param) in impl_generics.types.iter().zip(impl_hir_generics.ty_params()) { let param_ty = ty::ParamTy::for_def(ty_param); if !input_parameters.contains(&ctp::Parameter::from(param_ty)) { report_unused_parameter(tcx, param.span, "type", ¶m_ty.to_string()); @@ -123,7 +123,7 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ctp::parameters_for(&tcx.type_of(def_id), true) }).collect(); for (ty_lifetime, lifetime) in impl_generics.regions.iter() - .zip(&impl_hir_generics.lifetimes) + .zip(impl_hir_generics.lifetimes()) { let param = ctp::Parameter::from(ty_lifetime.to_early_bound_region_data()); diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 05f366dfd18f4..129511ee64c62 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -186,7 +186,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Some(hir_map::NodeItem(it)) => { match it.node { hir::ItemFn(.., ref generics, _) => { - if generics.is_parameterized() { + if !generics.params.is_empty() { struct_span_err!(tcx.sess, generics.span, E0131, "main function is not allowed to have type parameters") .span_label(generics.span, @@ -235,7 +235,7 @@ fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Some(hir_map::NodeItem(it)) => { match it.node { hir::ItemFn(..,ref ps,_) - if ps.is_parameterized() => { + if !ps.params.is_empty() => { struct_span_err!(tcx.sess, ps.span, E0132, "start function is not allowed to have type parameters") .span_label(ps.span, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 56c39357f16a3..dc157f682fcea 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -43,6 +43,7 @@ use rustc_typeck::hir_ty_to_ty; use rustc::hir; use rustc_const_math::ConstInt; +use std::default::Default; use std::{mem, slice, vec}; use std::iter::FromIterator; use std::rc::Rc; @@ -856,7 +857,7 @@ impl TyParamBound { did, is_generic: false, }, - lifetimes: vec![] + generic_params: Vec::new(), }, hir::TraitBoundModifier::Maybe) } @@ -951,7 +952,7 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { if let &ty::RegionKind::ReLateBound(..) = *reg { debug!(" hit an ReLateBound {:?}", reg); if let Some(lt) = reg.clean(cx) { - late_bounds.push(lt); + late_bounds.push(GenericParam::Lifetime(lt)); } } } @@ -967,7 +968,7 @@ impl<'tcx> Clean for ty::TraitRef<'tcx> { did: self.def_id, is_generic: false, }, - lifetimes: late_bounds, + generic_params: late_bounds, }, hir::TraitBoundModifier::None ) @@ -981,7 +982,7 @@ impl<'tcx> Clean>> for Substs<'tcx> { .map(RegionBound)); v.extend(self.types().map(|t| TraitBound(PolyTrait { trait_: t.clean(cx), - lifetimes: vec![] + generic_params: Vec::new(), }, hir::TraitBoundModifier::None))); if !v.is_empty() {Some(v)} else {None} } @@ -1186,19 +1187,31 @@ impl<'tcx> Clean for ty::ProjectionTy<'tcx> { } } -// maybe use a Generic enum and use Vec? #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] +pub enum GenericParam { + Lifetime(Lifetime), + Type(TyParam), +} + +impl Clean for hir::GenericParam { + fn clean(&self, cx: &DocContext) -> GenericParam { + match *self { + hir::GenericParam::Lifetime(ref l) => GenericParam::Lifetime(l.clean(cx)), + hir::GenericParam::Type(ref t) => GenericParam::Type(t.clean(cx)), + } + } +} + +#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug, Default)] pub struct Generics { - pub lifetimes: Vec, - pub type_params: Vec, + pub params: Vec, pub where_predicates: Vec, } impl Clean for hir::Generics { fn clean(&self, cx: &DocContext) -> Generics { let mut g = Generics { - lifetimes: self.lifetimes.clean(cx), - type_params: self.ty_params.clean(cx), + params: self.params.clean(cx), where_predicates: self.where_clause.predicates.clean(cx) }; @@ -1209,10 +1222,12 @@ impl Clean for hir::Generics { match *where_pred { WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => { if bounds.is_empty() { - for type_params in &mut g.type_params { - if &type_params.name == name { - mem::swap(bounds, &mut type_params.bounds); - break + for param in &mut g.params { + if let GenericParam::Type(ref mut type_param) = *param { + if &type_param.name == name { + mem::swap(bounds, &mut type_param.bounds); + break + } } } } @@ -1283,8 +1298,16 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, // and instead see `where T: Foo + Bar + Sized + 'a` Generics { - type_params: simplify::ty_params(stripped_typarams), - lifetimes: gens.regions.clean(cx), + params: gens.regions + .clean(cx) + .into_iter() + .map(|lp| GenericParam::Lifetime(lp)) + .chain( + simplify::ty_params(stripped_typarams) + .into_iter() + .map(|tp| GenericParam::Type(tp)) + ) + .collect(), where_predicates: simplify::where_clauses(cx, where_predicates), } } @@ -1538,7 +1561,7 @@ impl Clean for hir::PolyTraitRef { fn clean(&self, cx: &DocContext) -> PolyTrait { PolyTrait { trait_: self.trait_ref.clean(cx), - lifetimes: self.bound_lifetimes.clean(cx) + generic_params: self.bound_generic_params.clean(cx) } } } @@ -1590,11 +1613,7 @@ impl Clean for hir::ImplItem { } hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef { type_: ty.clean(cx), - generics: Generics { - lifetimes: Vec::new(), - type_params: Vec::new(), - where_predicates: Vec::new() - }, + generics: Generics::default(), }, true), }; Item { @@ -1726,8 +1745,7 @@ impl<'tcx> Clean for ty::AssociatedItem { TypedefItem(Typedef { type_: cx.tcx.type_of(self.def_id).clean(cx), generics: Generics { - lifetimes: Vec::new(), - type_params: Vec::new(), + params: Vec::new(), where_predicates: Vec::new(), }, }, true) @@ -1757,7 +1775,7 @@ impl<'tcx> Clean for ty::AssociatedItem { #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] pub struct PolyTrait { pub trait_: Type, - pub lifetimes: Vec + pub generic_params: Vec, } /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original @@ -2081,7 +2099,7 @@ impl Clean for hir::Ty { let mut ty_substs = FxHashMap(); let mut lt_substs = FxHashMap(); provided_params.with_parameters(|provided_params| { - for (i, ty_param) in generics.ty_params.iter().enumerate() { + for (i, ty_param) in generics.ty_params().enumerate() { let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id)); if let Some(ty) = provided_params.types.get(i).cloned() { ty_substs.insert(ty_param_def, ty.into_inner().clean(cx)); @@ -2089,7 +2107,8 @@ impl Clean for hir::Ty { ty_substs.insert(ty_param_def, default.into_inner().clean(cx)); } } - for (i, lt_param) in generics.lifetimes.iter().enumerate() { + + for (i, lt_param) in generics.lifetimes().enumerate() { if let Some(lt) = provided_params.lifetimes.get(i).cloned() { if !lt.is_elided() { let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id); @@ -2197,11 +2216,7 @@ impl<'tcx> Clean for Ty<'tcx> { let sig = ty.fn_sig(cx.tcx); BareFunction(box BareFunctionDecl { unsafety: sig.unsafety(), - generics: Generics { - lifetimes: Vec::new(), - type_params: Vec::new(), - where_predicates: Vec::new() - }, + generic_params: Vec::new(), decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), abi: sig.abi(), }) @@ -2253,7 +2268,7 @@ impl<'tcx> Clean for Ty<'tcx> { did, is_generic: false, }, - lifetimes: vec![] + generic_params: Vec::new(), }, hir::TraitBoundModifier::None); typarams.push(bound); } @@ -2713,7 +2728,7 @@ impl Clean for doctree::Typedef { #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] pub struct BareFunctionDecl { pub unsafety: hir::Unsafety, - pub generics: Generics, + pub generic_params: Vec, pub decl: FnDecl, pub abi: Abi, } @@ -2722,11 +2737,7 @@ impl Clean for hir::BareFnTy { fn clean(&self, cx: &DocContext) -> BareFunctionDecl { BareFunctionDecl { unsafety: self.unsafety, - generics: Generics { - lifetimes: self.lifetimes.clean(cx), - type_params: Vec::new(), - where_predicates: Vec::new() - }, + generic_params: self.generic_params.clean(cx), decl: (&*self.decl, &self.arg_names[..]).clean(cx), abi: self.abi, } diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 53c10d101d0c4..7300721c38406 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -118,30 +118,11 @@ impl<'a> fmt::Display for TyParamBounds<'a> { } } -impl fmt::Display for clean::Generics { +impl fmt::Display for clean::GenericParam { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.lifetimes.is_empty() && self.type_params.is_empty() { return Ok(()) } - if f.alternate() { - f.write_str("<")?; - } else { - f.write_str("<")?; - } - - for (i, life) in self.lifetimes.iter().enumerate() { - if i > 0 { - f.write_str(", ")?; - } - write!(f, "{}", *life)?; - } - - if !self.type_params.is_empty() { - if !self.lifetimes.is_empty() { - f.write_str(", ")?; - } - for (i, tp) in self.type_params.iter().enumerate() { - if i > 0 { - f.write_str(", ")? - } + match *self { + clean::GenericParam::Lifetime(ref lp) => write!(f, "{}", lp), + clean::GenericParam::Type(ref tp) => { f.write_str(&tp.name)?; if !tp.bounds.is_empty() { @@ -158,15 +139,22 @@ impl fmt::Display for clean::Generics { } else { write!(f, " = {}", ty)?; } - }; + } + + Ok(()) } } + } +} + +impl fmt::Display for clean::Generics { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.params.is_empty() { return Ok(()) } if f.alternate() { - f.write_str(">")?; + write!(f, "<{:#}>", CommaSep(&self.params)) } else { - f.write_str(">")?; + write!(f, "<{}>", CommaSep(&self.params)) } - Ok(()) } } @@ -259,22 +247,11 @@ impl fmt::Display for clean::Lifetime { impl fmt::Display for clean::PolyTrait { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if !self.lifetimes.is_empty() { - if f.alternate() { - f.write_str("for<")?; - } else { - f.write_str("for<")?; - } - for (i, lt) in self.lifetimes.iter().enumerate() { - if i > 0 { - f.write_str(", ")?; - } - write!(f, "{}", lt)?; - } + if !self.generic_params.is_empty() { if f.alternate() { - f.write_str("> ")?; + write!(f, "for<{:#}> ", CommaSep(&self.generic_params))?; } else { - f.write_str("> ")?; + write!(f, "for<{}> ", CommaSep(&self.generic_params))?; } } if f.alternate() { @@ -602,12 +579,12 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt: write!(f, "{}{:#}fn{:#}{:#}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi), - decl.generics, + CommaSep(&decl.generic_params), decl.decl) } else { write!(f, "{}{}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi))?; primitive_link(f, PrimitiveType::Fn, "fn")?; - write!(f, "{}{}", decl.generics, decl.decl) + write!(f, "{}{}", CommaSep(&decl.generic_params), decl.decl) } } clean::Tuple(ref typs) => { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 9f981e97a762b..515baa2c6698f 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1424,8 +1424,10 @@ impl DocFolder for Cache { impl<'a> Cache { fn generics(&mut self, generics: &clean::Generics) { - for typ in &generics.type_params { - self.typarams.insert(typ.did, typ.name.clone()); + for param in &generics.params { + if let clean::GenericParam::Type(ref typ) = *param { + self.typarams.insert(typ.did, typ.name.clone()); + } } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 461cb0480d20b..2c9ea44de5ec9 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -302,30 +302,56 @@ pub struct TyParam { pub span: Span, } -/// Represents lifetimes and type parameters attached to a declaration -/// of a function, enum, trait, etc. +#[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 fn is_type_param(&self) -> bool { + match *self { + GenericParam::Type(_) => true, + _ => false, + } + } +} + +/// Represents lifetime, type and const parameters attached to a declaration of +/// a function, enum, trait, etc. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Generics { - pub lifetimes: Vec, - pub ty_params: Vec, + pub params: Vec, pub where_clause: WhereClause, pub span: Span, } impl Generics { pub fn is_lt_parameterized(&self) -> bool { - !self.lifetimes.is_empty() + self.params.iter().any(|param| param.is_lifetime_param()) } + pub fn is_type_parameterized(&self) -> bool { - !self.ty_params.is_empty() + self.params.iter().any(|param| param.is_type_param()) } + pub fn is_parameterized(&self) -> bool { - self.is_lt_parameterized() || self.is_type_parameterized() + !self.params.is_empty() } + pub fn span_for_name(&self, name: &str) -> Option { - for t in &self.ty_params { - if t.ident.name == name { - return Some(t.span); + for param in &self.params { + if let GenericParam::Type(ref t) = *param { + if t.ident.name == name { + return Some(t.span); + } } } None @@ -336,8 +362,7 @@ impl Default for Generics { /// Creates an instance of `Generics`. fn default() -> Generics { Generics { - lifetimes: Vec::new(), - ty_params: Vec::new(), + params: Vec::new(), where_clause: WhereClause { id: DUMMY_NODE_ID, predicates: Vec::new(), @@ -373,8 +398,8 @@ pub enum WherePredicate { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct WhereBoundPredicate { pub span: Span, - /// Any lifetimes from a `for` binding - pub bound_lifetimes: Vec, + /// Any generics from a `for` binding + pub bound_generic_params: Vec, /// The type being bounded pub bounded_ty: P, /// Trait and lifetime bounds (`Clone+Send+'static`) @@ -1492,7 +1517,7 @@ impl fmt::Debug for Ty { pub struct BareFnTy { pub unsafety: Unsafety, pub abi: Abi, - pub lifetimes: Vec, + pub generic_params: Vec, pub decl: P } @@ -1851,7 +1876,7 @@ pub struct TraitRef { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct PolyTraitRef { /// The `'a` in `<'a> Foo<&'a T>` - pub bound_lifetimes: Vec, + pub bound_generic_params: Vec, /// The `Foo<&'a T>` in `<'a> Foo<&'a T>` pub trait_ref: TraitRef, @@ -1860,9 +1885,9 @@ pub struct PolyTraitRef { } impl PolyTraitRef { - pub fn new(lifetimes: Vec, path: Path, span: Span) -> Self { + pub fn new(generic_params: Vec, path: Path, span: Span) -> Self { PolyTraitRef { - bound_lifetimes: lifetimes, + bound_generic_params: generic_params, trait_ref: TraitRef { path: path, ref_id: DUMMY_NODE_ID }, span, } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 9a96432f11d4e..0b3272fc1db24 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -462,7 +462,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef { ast::PolyTraitRef { - bound_lifetimes: Vec::new(), + bound_generic_params: Vec::new(), trait_ref: self.trait_ref(path), span, } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 1f398ff155cc9..2d47382ac0fae 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1748,22 +1748,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_vis(self, vis); } - fn visit_generics(&mut self, g: &'a ast::Generics) { - for t in &g.ty_params { - if !t.attrs.is_empty() { - gate_feature_post!(&self, generic_param_attrs, t.attrs[0].span, - "attributes on type parameter bindings are experimental"); - } + fn visit_generic_param(&mut self, param: &'a ast::GenericParam) { + let (attrs, explain) = match *param { + ast::GenericParam::Lifetime(ref ld) => + (&ld.attrs, "attributes on lifetime bindings are experimental"), + ast::GenericParam::Type(ref t) => + (&t.attrs, "attributes on type parameter bindings are experimental"), + }; + + if !attrs.is_empty() { + gate_feature_post!(&self, generic_param_attrs, attrs[0].span, explain); } - visit::walk_generics(self, g) - } - fn visit_lifetime_def(&mut self, lifetime_def: &'a ast::LifetimeDef) { - if !lifetime_def.attrs.is_empty() { - gate_feature_post!(&self, generic_param_attrs, lifetime_def.attrs[0].span, - "attributes on lifetime bindings are experimental"); - } - visit::walk_lifetime_def(self, lifetime_def) + visit::walk_generic_param(self, param) } fn visit_lifetime(&mut self, lt: &'a ast::Lifetime) { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 6f973e2bcfaef..d1aef0c5042e8 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -237,8 +237,12 @@ pub trait Folder : Sized { noop_fold_ty_param(tp, self) } - fn fold_ty_params(&mut self, tps: Vec) -> Vec { - noop_fold_ty_params(tps, self) + fn fold_generic_param(&mut self, param: GenericParam) -> GenericParam { + noop_fold_generic_param(param, self) + } + + fn fold_generic_params(&mut self, params: Vec) -> Vec { + noop_fold_generic_params(params, self) } fn fold_tt(&mut self, tt: TokenTree) -> TokenTree { @@ -363,8 +367,8 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P { TyKind::Rptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt)) } TyKind::BareFn(f) => { - TyKind::BareFn(f.map(|BareFnTy {lifetimes, unsafety, abi, decl}| BareFnTy { - lifetimes: fld.fold_lifetime_defs(lifetimes), + TyKind::BareFn(f.map(|BareFnTy {generic_params, unsafety, abi, decl}| BareFnTy { + generic_params: fld.fold_generic_params(generic_params), unsafety, abi, decl: fld.fold_fn_decl(decl) @@ -677,8 +681,18 @@ pub fn noop_fold_ty_param(tp: TyParam, fld: &mut T) -> TyParam { } } -pub fn noop_fold_ty_params(tps: Vec, fld: &mut T) -> Vec { - tps.move_map(|tp| fld.fold_ty_param(tp)) +pub fn noop_fold_generic_param(param: GenericParam, fld: &mut T) -> GenericParam { + match param { + GenericParam::Lifetime(l) => GenericParam::Lifetime(fld.fold_lifetime_def(l)), + GenericParam::Type(t) => GenericParam::Type(fld.fold_ty_param(t)), + } +} + +pub fn noop_fold_generic_params( + params: Vec, + fld: &mut T +) -> Vec { + params.move_map(|p| fld.fold_generic_param(p)) } pub fn noop_fold_lifetime(l: Lifetime, fld: &mut T) -> Lifetime { @@ -716,11 +730,10 @@ pub fn noop_fold_opt_lifetime(o_lt: Option, fld: &mut T) o_lt.map(|lt| fld.fold_lifetime(lt)) } -pub fn noop_fold_generics(Generics {ty_params, lifetimes, where_clause, span}: Generics, +pub fn noop_fold_generics(Generics { params, where_clause, span }: Generics, fld: &mut T) -> Generics { Generics { - ty_params: fld.fold_ty_params(ty_params), - lifetimes: fld.fold_lifetime_defs(lifetimes), + params: fld.fold_generic_params(params), where_clause: fld.fold_where_clause(where_clause), span: fld.new_span(span), } @@ -744,12 +757,12 @@ pub fn noop_fold_where_predicate( fld: &mut T) -> WherePredicate { match pred { - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{bound_lifetimes, + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{bound_generic_params, bounded_ty, bounds, span}) => { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { - bound_lifetimes: fld.fold_lifetime_defs(bound_lifetimes), + 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)), span: fld.new_span(span) @@ -806,7 +819,7 @@ pub fn noop_fold_trait_ref(p: TraitRef, fld: &mut T) -> TraitRef { pub fn noop_fold_poly_trait_ref(p: PolyTraitRef, fld: &mut T) -> PolyTraitRef { ast::PolyTraitRef { - bound_lifetimes: fld.fold_lifetime_defs(p.bound_lifetimes), + bound_generic_params: fld.fold_generic_params(p.bound_generic_params), trait_ref: fld.fold_trait_ref(p.trait_ref), span: fld.new_span(p.span), } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 89a54989f9693..17bccfc2d0f35 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -905,9 +905,8 @@ mod tests { node: ast::Constness::NotConst, }, Abi::Rust, - ast::Generics{ // no idea on either of these: - lifetimes: Vec::new(), - ty_params: Vec::new(), + ast::Generics{ + params: Vec::new(), where_clause: ast::WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2aac7ef39f2da..565e2191c0073 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -21,6 +21,7 @@ use ast::EnumDef; use ast::{Expr, ExprKind, RangeLimits}; use ast::{Field, FnDecl}; use ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; +use ast::GenericParam; use ast::{Ident, ImplItem, IsAuto, Item, ItemKind}; use ast::{Lifetime, LifetimeDef, Lit, LitKind, UintTy}; use ast::Local; @@ -1261,7 +1262,7 @@ impl<'a> Parser<'a> { } /// parse a TyKind::BareFn type: - pub fn parse_ty_bare_fn(&mut self, lifetime_defs: Vec) + pub fn parse_ty_bare_fn(&mut self, generic_params: Vec) -> PResult<'a, TyKind> { /* @@ -1293,7 +1294,7 @@ impl<'a> Parser<'a> { Ok(TyKind::BareFn(P(BareFnTy { abi, unsafety, - lifetimes: lifetime_defs, + generic_params, decl, }))) } @@ -1582,9 +1583,9 @@ impl<'a> Parser<'a> { Ok(P(ty)) } - fn parse_remaining_bounds(&mut self, lifetime_defs: Vec, path: ast::Path, + 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(lifetime_defs, path, lo.to(self.prev_span)); + let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span)); let mut bounds = vec![TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)]; if parse_plus { self.bump(); // `+` @@ -4550,9 +4551,8 @@ impl<'a> Parser<'a> { /// Parses (possibly empty) list of lifetime and type parameters, possibly including /// trailing comma and erroneous trailing attributes. - pub fn parse_generic_params(&mut self) -> PResult<'a, (Vec, Vec)> { - let mut lifetime_defs = Vec::new(); - let mut ty_params = Vec::new(); + pub fn parse_generic_params(&mut self) -> PResult<'a, Vec> { + let mut params = Vec::new(); let mut seen_ty_param = false; loop { let attrs = self.parse_outer_attributes()?; @@ -4564,18 +4564,18 @@ impl<'a> Parser<'a> { } else { Vec::new() }; - lifetime_defs.push(LifetimeDef { + params.push(ast::GenericParam::Lifetime(LifetimeDef { attrs: attrs.into(), lifetime, bounds, - }); + })); 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. - ty_params.push(self.parse_ty_param(attrs)?); + params.push(ast::GenericParam::Type(self.parse_ty_param(attrs)?)); seen_ty_param = true; } else { // Check for trailing attributes and stop parsing. @@ -4591,7 +4591,7 @@ impl<'a> Parser<'a> { break } } - Ok((lifetime_defs, ty_params)) + Ok(params) } /// Parse a set of optional generic type parameter declarations. Where @@ -4606,11 +4606,10 @@ impl<'a> Parser<'a> { let span_lo = self.span; if self.eat_lt() { - let (lifetime_defs, ty_params) = self.parse_generic_params()?; + let params = self.parse_generic_params()?; self.expect_gt()?; Ok(ast::Generics { - lifetimes: lifetime_defs, - ty_params, + params, where_clause: WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), @@ -4738,7 +4737,7 @@ impl<'a> Parser<'a> { where_clause.predicates.push(ast::WherePredicate::BoundPredicate( ast::WhereBoundPredicate { span: lo.to(self.prev_span), - bound_lifetimes: lifetime_defs, + bound_generic_params: lifetime_defs, bounded_ty: ty, bounds, } @@ -5363,16 +5362,24 @@ impl<'a> Parser<'a> { } } - fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec> { + fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec> { if self.eat_keyword(keywords::For) { self.expect_lt()?; - let (lifetime_defs, ty_params) = self.parse_generic_params()?; + let params = self.parse_generic_params()?; self.expect_gt()?; - if !ty_params.is_empty() { - self.span_err(ty_params[0].span, - "only lifetime parameters can be used in this context"); + + let first_non_lifetime_param_span = params.iter() + .filter_map(|param| match *param { + ast::GenericParam::Lifetime(_) => None, + ast::GenericParam::Type(ref t) => Some(t.span), + }) + .next(); + + if let Some(span) = first_non_lifetime_param_span { + self.span_err(span, "only lifetime parameters can be used in this context"); } - Ok(lifetime_defs) + + Ok(params) } else { Ok(Vec::new()) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index da4d5f5f676a6..8f619e8af765a 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -275,7 +275,7 @@ pub fn token_to_string(tok: &Token) -> String { token::NtArm(ref e) => arm_to_string(e), token::NtImplItem(ref e) => impl_item_to_string(e), token::NtTraitItem(ref e) => trait_item_to_string(e), - token::NtGenerics(ref e) => generics_to_string(e), + token::NtGenerics(ref e) => generic_params_to_string(&e.params), token::NtWhereClause(ref e) => where_clause_to_string(e), token::NtArg(ref e) => arg_to_string(e), token::NtVis(ref e) => vis_to_string(e), @@ -339,8 +339,8 @@ pub fn trait_item_to_string(i: &ast::TraitItem) -> String { to_string(|s| s.print_trait_item(i)) } -pub fn generics_to_string(generics: &ast::Generics) -> String { - to_string(|s| s.print_generics(generics)) +pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String { + to_string(|s| s.print_generic_params(generic_params)) } pub fn where_clause_to_string(i: &ast::WhereClause) -> String { @@ -1043,21 +1043,11 @@ impl<'a> State<'a> { self.pclose()?; } ast::TyKind::BareFn(ref f) => { - let generics = ast::Generics { - lifetimes: f.lifetimes.clone(), - ty_params: Vec::new(), - where_clause: ast::WhereClause { - id: ast::DUMMY_NODE_ID, - predicates: Vec::new(), - span: syntax_pos::DUMMY_SP, - }, - span: syntax_pos::DUMMY_SP, - }; self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, - &generics)?; + &f.generic_params)?; } ast::TyKind::Path(None, ref path) => { self.print_path(path, false, 0, false)?; @@ -1271,15 +1261,15 @@ impl<'a> State<'a> { self.s.word(&ga.asm.as_str())?; self.end()?; } - ast::ItemKind::Ty(ref ty, ref params) => { + ast::ItemKind::Ty(ref ty, ref generics) => { self.ibox(INDENT_UNIT)?; self.ibox(0)?; self.word_nbsp(&visibility_qualified(&item.vis, "type"))?; self.print_ident(item.ident)?; - self.print_generics(params)?; + self.print_generic_params(&generics.params)?; self.end()?; // end the inner ibox - self.print_where_clause(¶ms.where_clause)?; + self.print_where_clause(&generics.where_clause)?; self.s.space()?; self.word_space("=")?; self.print_type(ty)?; @@ -1329,7 +1319,7 @@ impl<'a> State<'a> { self.word_nbsp("impl")?; if generics.is_parameterized() { - self.print_generics(generics)?; + self.print_generic_params(&generics.params)?; self.s.space()?; } @@ -1361,7 +1351,7 @@ impl<'a> State<'a> { self.print_is_auto(is_auto)?; self.word_nbsp("trait")?; self.print_ident(item.ident)?; - self.print_generics(generics)?; + 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 { @@ -1386,7 +1376,7 @@ impl<'a> State<'a> { self.print_visibility(&item.vis)?; self.word_nbsp("trait")?; self.print_ident(item.ident)?; - self.print_generics(generics)?; + self.print_generic_params(&generics.params)?; let mut real_bounds = Vec::with_capacity(bounds.len()); // FIXME(durka) this seems to be some quite outdated syntax for b in bounds.iter() { @@ -1432,26 +1422,20 @@ impl<'a> State<'a> { self.print_path(&t.path, false, 0, false) } - fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> io::Result<()> { - if !lifetimes.is_empty() { - self.s.word("for<")?; - let mut comma = false; - for lifetime_def in lifetimes { - if comma { - self.word_space(",")? - } - self.print_outer_attributes_inline(&lifetime_def.attrs)?; - self.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds)?; - comma = true; - } - self.s.word(">")?; + fn print_formal_generic_params( + &mut self, + generic_params: &[ast::GenericParam] + ) -> io::Result<()> { + if !generic_params.is_empty() { + self.s.word("for")?; + self.print_generic_params(generic_params)?; self.nbsp()?; } Ok(()) } fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> io::Result<()> { - self.print_formal_lifetime_list(&t.bound_lifetimes)?; + self.print_formal_generic_params(&t.bound_generic_params)?; self.print_trait_ref(&t.trait_ref) } @@ -1461,7 +1445,7 @@ impl<'a> State<'a> { visibility: &ast::Visibility) -> io::Result<()> { self.head(&visibility_qualified(visibility, "enum"))?; self.print_ident(ident)?; - self.print_generics(generics)?; + self.print_generic_params(&generics.params)?; self.print_where_clause(&generics.where_clause)?; self.s.space()?; self.print_variants(&enum_definition.variants, span) @@ -1517,7 +1501,7 @@ impl<'a> State<'a> { span: syntax_pos::Span, print_finalizer: bool) -> io::Result<()> { self.print_ident(ident)?; - self.print_generics(generics)?; + self.print_generic_params(&generics.params)?; if !struct_def.is_struct() { if struct_def.is_tuple() { self.popen()?; @@ -2764,7 +2748,7 @@ impl<'a> State<'a> { self.nbsp()?; self.print_ident(name)?; } - self.print_generics(generics)?; + self.print_generic_params(&generics.params)?; self.print_fn_args_and_ret(decl)?; self.print_where_clause(&generics.where_clause) } @@ -2870,31 +2854,23 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_generics(&mut self, - generics: &ast::Generics) - -> io::Result<()> - { - let total = generics.lifetimes.len() + generics.ty_params.len(); - if total == 0 { + pub fn print_generic_params( + &mut self, + generic_params: &[ast::GenericParam] + ) -> io::Result<()> { + if generic_params.is_empty() { return Ok(()); } self.s.word("<")?; - let mut ints = Vec::new(); - for i in 0..total { - ints.push(i); - } - - self.commasep(Inconsistent, &ints[..], |s, &idx| { - if idx < generics.lifetimes.len() { - let lifetime_def = &generics.lifetimes[idx]; - s.print_outer_attributes_inline(&lifetime_def.attrs)?; - s.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds) - } else { - let idx = idx - generics.lifetimes.len(); - let param = &generics.ty_params[idx]; - s.print_ty_param(param) + 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) + }, + ast::GenericParam::Type(ref ty_param) => s.print_ty_param(ty_param), } })?; @@ -2931,11 +2907,13 @@ impl<'a> State<'a> { } match *predicate { - ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes, - ref bounded_ty, - ref bounds, - ..}) => { - self.print_formal_lifetime_list(bound_lifetimes)?; + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + ref bound_generic_params, + ref bounded_ty, + ref bounds, + .. + }) => { + self.print_formal_generic_params(bound_generic_params)?; self.print_type(bounded_ty)?; self.print_bounds(":", bounds)?; } @@ -3057,16 +3035,15 @@ impl<'a> State<'a> { unsafety: ast::Unsafety, decl: &ast::FnDecl, name: Option, - generics: &ast::Generics) + generic_params: &Vec) -> io::Result<()> { self.ibox(INDENT_UNIT)?; - if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() { + if !generic_params.is_empty() { self.s.word("for")?; - self.print_generics(generics)?; + self.print_generic_params(generic_params)?; } let generics = ast::Generics { - lifetimes: Vec::new(), - ty_params: Vec::new(), + params: Vec::new(), where_clause: ast::WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 694a9c1f47252..1a0f4e9278da6 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -363,7 +363,10 @@ fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { ast::FunctionRetTy::Ty(ref t) if t.node == ast::TyKind::Tup(vec![]) => true, _ => false }; - let tparm_cnt = generics.ty_params.len(); + let tparm_cnt = generics.params.iter() + .filter(|param| param.is_type_param()) + .count(); + // NB: inadequate check, but we're running // well before resolve, can't get too deep. input_cnt == 1 diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index ac5642e53cf67..da238be85e0e2 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -71,6 +71,10 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_ty(self, t) } + fn visit_generic_param(&mut self, param: &GenericParam) { + self.count += 1; + walk_generic_param(self, param) + } fn visit_generics(&mut self, g: &Generics) { self.count += 1; walk_generics(self, g) @@ -121,10 +125,6 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_lifetime(self, lifetime) } - fn visit_lifetime_def(&mut self, lifetime: &LifetimeDef) { - self.count += 1; - walk_lifetime_def(self, lifetime) - } fn visit_mac(&mut self, _mac: &Mac) { self.count += 1; walk_mac(self, _mac) diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 9266cc280974d..bd68d7cf8f5d8 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -72,6 +72,7 @@ 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_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) } fn visit_where_predicate(&mut self, p: &'ast WherePredicate) { walk_where_predicate(self, p) @@ -103,9 +104,6 @@ pub trait Visitor<'ast>: Sized { fn visit_lifetime(&mut self, lifetime: &'ast Lifetime) { walk_lifetime(self, lifetime) } - fn visit_lifetime_def(&mut self, lifetime: &'ast LifetimeDef) { - walk_lifetime_def(self, lifetime) - } fn visit_mac(&mut self, _mac: &'ast Mac) { panic!("visit_mac disabled by default"); // NB: see note about macros above. @@ -210,18 +208,12 @@ pub fn walk_lifetime<'a, V: Visitor<'a>>(visitor: &mut V, lifetime: &'a Lifetime visitor.visit_ident(lifetime.span, lifetime.ident); } -pub fn walk_lifetime_def<'a, V: Visitor<'a>>(visitor: &mut V, lifetime_def: &'a LifetimeDef) { - visitor.visit_lifetime(&lifetime_def.lifetime); - walk_list!(visitor, visit_lifetime, &lifetime_def.bounds); - walk_list!(visitor, visit_attribute, &*lifetime_def.attrs); -} - pub fn walk_poly_trait_ref<'a, V>(visitor: &mut V, trait_ref: &'a PolyTraitRef, _: &TraitBoundModifier) where V: Visitor<'a>, { - walk_list!(visitor, visit_lifetime_def, &trait_ref.bound_lifetimes); + walk_list!(visitor, visit_generic_param, &trait_ref.bound_generic_params); visitor.visit_trait_ref(&trait_ref.trait_ref); } @@ -339,7 +331,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { } TyKind::BareFn(ref function_declaration) => { walk_fn_decl(visitor, &function_declaration.decl); - walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes); + walk_list!(visitor, visit_generic_param, &function_declaration.generic_params); } TyKind::Path(ref maybe_qself, ref path) => { if let Some(ref qself) = *maybe_qself { @@ -499,14 +491,24 @@ pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyPar } } -pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) { - for param in &generics.ty_params { - visitor.visit_ident(param.span, param.ident); - walk_list!(visitor, visit_ty_param_bound, ¶m.bounds); - walk_list!(visitor, visit_ty, ¶m.default); - walk_list!(visitor, visit_attribute, &*param.attrs); +pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) { + match *param { + GenericParam::Lifetime(ref l) => { + visitor.visit_lifetime(&l.lifetime); + walk_list!(visitor, visit_lifetime, &l.bounds); + walk_list!(visitor, visit_attribute, &*l.attrs); + } + GenericParam::Type(ref t) => { + visitor.visit_ident(t.span, 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); + } } - walk_list!(visitor, visit_lifetime_def, &generics.lifetimes); +} + +pub fn walk_generics<'a, V: Visitor<'a>>(visitor: &mut V, generics: &'a Generics) { + walk_list!(visitor, visit_generic_param, &generics.params); walk_list!(visitor, visit_where_predicate, &generics.where_clause.predicates); } @@ -514,11 +516,11 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a match *predicate { WherePredicate::BoundPredicate(WhereBoundPredicate{ref bounded_ty, ref bounds, - ref bound_lifetimes, + ref bound_generic_params, ..}) => { visitor.visit_ty(bounded_ty); walk_list!(visitor, visit_ty_param_bound, bounds); - walk_list!(visitor, visit_lifetime_def, bound_lifetimes); + walk_list!(visitor, visit_generic_param, bound_generic_params); } WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime, ref bounds, diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 35def632fc188..f23d22b0c365f 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -45,15 +45,23 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, match *item { Annotatable::Item(ref annitem) => { match annitem.node { - ItemKind::Struct(_, Generics { ref ty_params, .. }) | - ItemKind::Enum(_, Generics { ref ty_params, .. }) - if attr::contains_name(&annitem.attrs, "rustc_copy_clone_marker") && - ty_params.is_empty() => { - bounds = vec![]; - is_shallow = true; - substructure = combine_substructure(Box::new(|c, s, sub| { - cs_clone_shallow("Clone", c, s, sub, false) - })); + 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()) + { + bounds = vec![]; + is_shallow = true; + substructure = combine_substructure(Box::new(|c, s, sub| { + cs_clone_shallow("Clone", c, s, sub, false) + })); + } else { + bounds = vec![]; + is_shallow = false; + substructure = combine_substructure(Box::new(|c, s, sub| { + cs_clone("Clone", c, s, sub) + })); + } } ItemKind::Union(..) => { bounds = vec![Literal(path_std!(cx, marker::Copy))]; diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 2b565ca51e9ec..29f5196c9bd6f 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -192,7 +192,9 @@ use std::collections::HashSet; use std::vec; use syntax::abi::Abi; -use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind, VariantData}; +use syntax::ast::{ + self, BinOpKind, EnumDef, Expr, GenericParam, Generics, Ident, PatKind, VariantData +}; use syntax::attr; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; @@ -417,7 +419,7 @@ impl<'a> TraitDef<'a> { ast::ItemKind::Struct(_, ref generics) | ast::ItemKind::Enum(_, ref generics) | ast::ItemKind::Union(_, ref generics) => { - generics.ty_params.is_empty() + !generics.params.iter().any(|p| p.is_type_param()) } _ => { // Non-ADT derive is an error, but it should have been @@ -537,32 +539,35 @@ impl<'a> TraitDef<'a> { } }); - let Generics { mut lifetimes, mut ty_params, mut where_clause, span } = self.generics + let Generics { mut params, mut where_clause, span } = self.generics .to_generics(cx, self.span, type_ident, generics); - // Copy the lifetimes - lifetimes.extend(generics.lifetimes.iter().cloned()); - - // Create the type parameters. - ty_params.extend(generics.ty_params.iter().map(|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()); - } + // 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()); + } - cx.typaram(self.span, ty_param.ident, vec![], bounds, None) + GenericParam::Type(cx.typaram(self.span, ty_param.ident, vec![], bounds, None)) + } + } })); // and similarly for where clauses @@ -571,7 +576,7 @@ impl<'a> TraitDef<'a> { ast::WherePredicate::BoundPredicate(ref wb) => { ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { span: self.span, - bound_lifetimes: wb.bound_lifetimes.clone(), + bound_generic_params: wb.bound_generic_params.clone(), bounded_ty: wb.bounded_ty.clone(), bounds: wb.bounds.iter().cloned().collect(), }) @@ -594,49 +599,61 @@ impl<'a> TraitDef<'a> { } })); - if !ty_params.is_empty() { - let ty_param_names: Vec = ty_params.iter() - .map(|ty_param| ty_param.ident.name) - .collect(); + { + // Extra scope required here so ty_params goes out of scope before params is moved - let mut processed_field_types = HashSet::new(); - for field_ty in field_tys { - let tys = find_type_parameters(&field_ty, &ty_param_names, self.span, cx); - - for ty in tys { - // if we have already handled this type, skip it - if let ast::TyKind::Path(_, ref p) = ty.node { - if p.segments.len() == 1 && - ty_param_names.contains(&p.segments[0].identifier.name) || - processed_field_types.contains(&p.segments) { - continue; - }; - processed_field_types.insert(p.segments.clone()); - } - let mut bounds: Vec<_> = self.additional_bounds - .iter() - .map(|p| cx.typarambound(p.to_path(cx, self.span, type_ident, generics))) - .collect(); + let mut ty_params = params.iter() + .filter_map(|param| match *param { + ast::GenericParam::Type(ref t) => Some(t), + _ => None, + }) + .peekable(); - // require the current trait - bounds.push(cx.typarambound(trait_path.clone())); + if ty_params.peek().is_some() { + let ty_param_names: Vec = ty_params + .map(|ty_param| ty_param.ident.name) + .collect(); - let predicate = ast::WhereBoundPredicate { - span: self.span, - bound_lifetimes: vec![], - bounded_ty: ty, - bounds, - }; + let mut processed_field_types = HashSet::new(); + for field_ty in field_tys { + let tys = find_type_parameters(&field_ty, &ty_param_names, self.span, cx); + + for ty in tys { + // if we have already handled this type, skip it + if let ast::TyKind::Path(_, ref p) = ty.node { + if p.segments.len() == 1 && + ty_param_names.contains(&p.segments[0].identifier.name) || + processed_field_types.contains(&p.segments) { + continue; + }; + processed_field_types.insert(p.segments.clone()); + } + let mut bounds: Vec<_> = self.additional_bounds + .iter() + .map(|p| { + cx.typarambound(p.to_path(cx, self.span, type_ident, generics)) + }) + .collect(); - let predicate = ast::WherePredicate::BoundPredicate(predicate); - where_clause.predicates.push(predicate); + // require the current trait + bounds.push(cx.typarambound(trait_path.clone())); + + let predicate = ast::WhereBoundPredicate { + span: self.span, + bound_generic_params: Vec::new(), + bounded_ty: ty, + bounds, + }; + + let predicate = ast::WherePredicate::BoundPredicate(predicate); + where_clause.predicates.push(predicate); + } } } } let trait_generics = Generics { - lifetimes, - ty_params, + params, where_clause, span, }; @@ -645,14 +662,21 @@ impl<'a> TraitDef<'a> { let trait_ref = cx.trait_ref(trait_path); // Create the type parameters on the `self` path. - let self_ty_params = generics.ty_params + let self_ty_params = generics.params .iter() - .map(|ty_param| cx.ty_ident(self.span, ty_param.ident)) + .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.lifetimes + let self_lifetimes: Vec = generics.params .iter() - .map(|ld| ld.lifetime) + .filter_map(|param| match *param { + GenericParam::Lifetime(ref ld) => Some(ld.lifetime), + _ => None, + }) .collect(); // Create the type of `self`. diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index e4faf652389a0..cc3e8b6e6b7c0 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, Generics, Ident, SelfKind}; +use syntax::ast::{Expr, GenericParam, Generics, Ident, SelfKind}; use syntax::ext::base::ExtCtxt; use syntax::ext::build::AstBuilder; use syntax::codemap::respan; @@ -185,13 +185,20 @@ impl<'a> Ty<'a> { -> ast::Path { match *self { Self_ => { - let self_params = self_generics.ty_params + let self_params = self_generics.params .iter() - .map(|ty_param| cx.ty_ident(span, ty_param.ident)) + .filter_map(|param| match *param { + GenericParam::Type(ref ty_param) => Some(cx.ty_ident(span, ty_param.ident)), + _ => None, + }) .collect(); - let lifetimes = self_generics.lifetimes + + let lifetimes: Vec = self_generics.params .iter() - .map(|d| d.lifetime) + .filter_map(|param| match *param { + GenericParam::Lifetime(ref ld) => Some(ld.lifetime), + _ => None, + }) .collect(); cx.path_all(span, @@ -226,11 +233,9 @@ fn mk_ty_param(cx: &ExtCtxt, cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None) } -fn mk_generics(lifetimes: Vec, ty_params: Vec, span: Span) - -> Generics { +fn mk_generics(params: Vec, span: Span) -> Generics { Generics { - lifetimes, - ty_params, + params, where_clause: ast::WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), @@ -260,26 +265,26 @@ impl<'a> LifetimeBounds<'a> { self_ty: Ident, self_generics: &Generics) -> Generics { - let lifetimes = self.lifetimes + let generic_params = self.lifetimes .iter() .map(|&(lt, ref bounds)| { let bounds = bounds.iter() .map(|b| cx.lifetime(span, Ident::from_str(b))) .collect(); - cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds) + GenericParam::Lifetime(cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds)) }) + .chain(self.bounds + .iter() + .map(|t| { + let (name, ref bounds) = *t; + GenericParam::Type(mk_ty_param( + cx, span, name, &[], &bounds, self_ty, self_generics + )) + }) + ) .collect(); - let ty_params = self.bounds - .iter() - .map(|t| { - match *t { - (ref name, ref bounds) => { - mk_ty_param(cx, span, *name, &[], bounds, self_ty, self_generics) - } - } - }) - .collect(); - mk_generics(lifetimes, ty_params, span) + + mk_generics(generic_params, span) } } diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index a6696b533694e..d769732381ccf 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -121,10 +121,12 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String { let mut typaram = String::from(base); if let Annotatable::Item(ref item) = *item { match item.node { - ast::ItemKind::Struct(_, ast::Generics { ref ty_params, .. }) | - ast::ItemKind::Enum(_, ast::Generics { ref ty_params, .. }) => { - for ty in ty_params.iter() { - typaram.push_str(&ty.ident.name.as_str()); + 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.name.as_str()); + } } } diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index e57a39a9de963..bfe408342a868 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -89,9 +89,9 @@ error[E0309]: the parameter type `T` may not live long enough 56 | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:17), 'a))`... + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`... -error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:17), 'a))` +error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))` --> $DIR/projection-one-region-closure.rs:56:20 | 56 | with_signature(cell, t, |cell, t| require(cell, t)); diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr index 5053b8486959a..6cb54170d7a90 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -94,7 +94,7 @@ note: External requirements = note: number of external vids: 3 = note: where '_#1r: '_#2r -error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:17), 'a))` +error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))` --> $DIR/projection-one-region-trait-bound-closure.rs:48:20 | 48 | with_signature(cell, t, |cell, t| require(cell, t)); diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index 414ae38080f63..21487899d3ba6 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -158,7 +158,7 @@ error[E0309]: the associated type `>::AssocType` may 49 | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:19), 'a))`... + = help: consider adding an explicit lifetime bound `>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:18), 'a))`... note: No external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:45:1 @@ -270,7 +270,7 @@ note: No external requirements T ] -error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:13 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]), BrNamed(crate0:DefIndex(1:44), 'a))` +error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:13 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]), BrNamed(crate0:DefIndex(1:43), 'a))` --> $DIR/projection-two-region-trait-bound-closure.rs:109:20 | 109 | with_signature(cell, t, |cell, t| require(cell, t)); diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index ef564377e506e..023b58c927d86 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -66,7 +66,7 @@ error[E0309]: the parameter type `T` may not live long enough 43 | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^^^^^^^^^^^^^^ | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:16), 'a))`... + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:15), 'a))`... note: No external requirements --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:1 diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index d47f506cd2043..2dd13810ae48a 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -107,7 +107,7 @@ error[E0309]: the parameter type `T` may not live long enough 47 | | }) | |_____^ | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:15), 'a))`... + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:14), 'a))`... note: No external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:1 @@ -154,7 +154,7 @@ error[E0309]: the parameter type `T` may not live long enough 81 | | }) | |_____^ | - = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:21), 'a))`... + = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:20), 'a))`... note: No external requirements --> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1