diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 3a1b0b8c58eb..74714edfc864 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 847cf64ce6a0..22e661a876ec 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 02a1e33eeb91..e3ca6f1591e7 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 2978f1eb409d..002849c0399c 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 5e132865ca87..ca2f3475fdb3 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 77469cb450bf..2f9fc70252f8 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 02a394f9634c..bddbdec2c34a 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 75cd230e1e5e..32ab458cb91d 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 f0761ce61786..f4abc54ad2e4 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 27f12c2c1587..6f457c9d1e1b 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 e976f08607a8..8b302dbe67a4 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 d14a6943fc11..49f14e8484f3 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 5417634144bb..81db44b05531 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 1356574f646a..c109a47f7986 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 5e8bbabee4a9..29369f9f8bb4 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 44dedde52294..0d9976afb9e3 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 96c9323e7dc7..d74a8af921be 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 6f93fa133b9e..ba0be974b277 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 5b277402f1e0..bb0a4be49c2a 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 864a61108b1d..b57a8bc7e77f 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 11e2135d2de3..ed3b8eadad74 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 97f77b20f811..93fb22a2dc0c 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 11d17e0227fd..9211ddfab671 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 70607bf4842a..734287f5f7d2 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 14296e78ddd1..77272b18f13b 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 e65ae6a1b4db..385b9321db71 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 f51bdf050c71..0a6d87e5a60b 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 15708ab766ae..1eed1bf4b71f 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 05f366dfd18f..129511ee64c6 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 56c39357f16a..dc157f682fce 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 53c10d101d0c..7300721c3840 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 9f981e97a762..515baa2c6698 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 461cb0480d20..2c9ea44de5ec 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 9a96432f11d4..0b3272fc1db2 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 1f398ff155cc..2d47382ac0fa 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 6f973e2bcfae..d1aef0c5042e 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 89a54989f969..17bccfc2d0f3 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 2aac7ef39f2d..565e2191c007 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 da4d5f5f676a..8f619e8af765 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 694a9c1f4725..1a0f4e9278da 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 ac5642e53cf6..da238be85e0e 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 9266cc280974..bd68d7cf8f5d 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 35def632fc18..f23d22b0c365 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 2b565ca51e9e..29f5196c9bd6 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 e4faf652389a..cc3e8b6e6b7c 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 a6696b533694..d769732381cc 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 e57a39a9de96..bfe408342a86 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 5053b8486959..6cb54170d7a9 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 414ae38080f6..21487899d3ba 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 ef564377e506..023b58c927d8 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 d47f506cd204..2dd13810ae48 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