diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index ae7d8bd8403..68ceb39d575 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -759,20 +759,20 @@ impl<'a> LoweringContext<'a> { hir_name } - // Evaluates `f` with the lifetimes in `lt_defs` in-scope. + // Evaluates `f` with the lifetimes in `params` in-scope. // This is used to track which lifetimes have already been defined, and // which are new in-band lifetimes that need to have a definition created // for them. fn with_in_scope_lifetime_defs<'l, T, F>( &mut self, - lt_defs: impl Iterator, + params: impl Iterator, f: F, ) -> T where F: FnOnce(&mut LoweringContext) -> T, { let old_len = self.in_scope_lifetimes.len(); - let lt_def_names = lt_defs.map(|lt_def| lt_def.lifetime.ident.name); + let lt_def_names = params.map(|param| param.ident.name); self.in_scope_lifetimes.extend(lt_def_names); let res = f(self); @@ -781,8 +781,8 @@ impl<'a> LoweringContext<'a> { res } - // Same as the method above, but accepts `hir::LifetimeDef`s - // instead of `ast::LifetimeDef`s. + // Same as the method above, but accepts `hir::GenericParam`s + // instead of `ast::GenericParam`s. // This should only be used with generics that have already had their // in-band lifetimes added. In practice, this means that this function is // only used when lowering a child item of a trait or impl. @@ -817,8 +817,8 @@ impl<'a> LoweringContext<'a> { F: FnOnce(&mut LoweringContext) -> T, { let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs( - generics.params.iter().filter_map(|p| match p { - GenericParamAST::Lifetime(ld) => Some(ld), + generics.params.iter().filter_map(|param| match param.kind { + GenericParamKindAST::Lifetime { .. } => Some(param), _ => None, }), |this| { @@ -1076,8 +1076,8 @@ impl<'a> LoweringContext<'a> { hir::TyRptr(lifetime, self.lower_mt(mt, itctx)) } TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs( - f.generic_params.iter().filter_map(|p| match p { - GenericParamAST::Lifetime(ld) => Some(ld), + f.generic_params.iter().filter_map(|param| match param.kind { + GenericParamKindAST::Lifetime { .. } => Some(param), _ => None, }), |this| { @@ -1940,21 +1940,19 @@ impl<'a> LoweringContext<'a> { add_bounds: &NodeMap>, itctx: ImplTraitContext) -> hir::GenericParam { - match param { - GenericParamAST::Lifetime(ref lifetime_def) => { + match param.kind { + GenericParamKindAST::Lifetime { ref bounds, ref lifetime, .. } => { let was_collecting_in_band = self.is_collecting_in_band_lifetimes; self.is_collecting_in_band_lifetimes = false; - let lifetime = self.lower_lifetime(&lifetime_def.lifetime); + let lifetime = self.lower_lifetime(lifetime); let param = hir::GenericParam { id: lifetime.id, span: lifetime.span, - pure_wrt_drop: attr::contains_name(&lifetime_def.attrs, "may_dangle"), + pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"), kind: hir::GenericParamKind::Lifetime { name: lifetime.name, - bounds: lifetime_def.bounds - .iter() - .map(|lt| self.lower_lifetime(lt)).collect(), + bounds: bounds.iter().map(|lt| self.lower_lifetime(lt)).collect(), in_band: false, lifetime_deprecated: lifetime, } @@ -1964,8 +1962,8 @@ impl<'a> LoweringContext<'a> { param } - GenericParamAST::Type(ref ty_param) => { - let mut name = self.lower_ident(ty_param.ident); + GenericParamKindAST::Type { ref bounds, ref default } => { + let mut name = self.lower_ident(param.ident); // Don't expose `Self` (recovered "keyword used as ident" parse error). // `rustc::ty` expects `Self` to be only used for a trait's `Self`. @@ -1974,8 +1972,8 @@ impl<'a> LoweringContext<'a> { name = Symbol::gensym("Self"); } - let mut bounds = self.lower_bounds(&ty_param.bounds, itctx); - let add_bounds = add_bounds.get(&ty_param.id).map_or(&[][..], |x| &x); + let mut bounds = self.lower_bounds(bounds, itctx); + let add_bounds = add_bounds.get(¶m.id).map_or(&[][..], |x| &x); if !add_bounds.is_empty() { bounds = bounds .into_iter() @@ -1984,22 +1982,20 @@ impl<'a> LoweringContext<'a> { } hir::GenericParam { - id: self.lower_node_id(ty_param.id).node_id, - span: ty_param.ident.span, - pure_wrt_drop: attr::contains_name(&ty_param.attrs, "may_dangle"), + id: self.lower_node_id(param.id).node_id, + span: param.ident.span, + pure_wrt_drop: attr::contains_name(¶m.attrs, "may_dangle"), kind: hir::GenericParamKind::Type { name, bounds, - default: ty_param.default.as_ref() - .map(|x| { - self.lower_ty(x, ImplTraitContext::Disallowed) - }), - synthetic: ty_param.attrs - .iter() - .filter(|attr| attr.check_name("rustc_synthetic")) - .map(|_| hir::SyntheticTyParamKind::ImplTrait) - .nth(0), - attrs: self.lower_attrs(&ty_param.attrs), + default: default.as_ref().map(|x| { + self.lower_ty(x, ImplTraitContext::Disallowed) + }), + synthetic: param.attrs.iter() + .filter(|attr| attr.check_name("rustc_synthetic")) + .map(|_| hir::SyntheticTyParamKind::ImplTrait) + .nth(0), + attrs: self.lower_attrs(¶m.attrs), } } } @@ -2015,13 +2011,18 @@ impl<'a> LoweringContext<'a> { params.iter().map(|param| self.lower_generic_param(param, add_bounds, itctx)).collect() } - fn lower_generics(&mut self, g: &Generics, itctx: ImplTraitContext) -> hir::Generics { + fn lower_generics( + &mut self, + generics: &Generics, + itctx: ImplTraitContext) + -> hir::Generics + { // Collect `?Trait` bounds in where clause and move them to parameter definitions. // FIXME: This could probably be done with less rightward drift. Also looks like two control // paths where report_error is called are also the only paths that advance to after // the match statement, so the error reporting could probably just be moved there. let mut add_bounds = NodeMap(); - for pred in &g.where_clause.predicates { + for pred in &generics.where_clause.predicates { if let WherePredicate::BoundPredicate(ref bound_pred) = *pred { 'next_bound: for bound in &bound_pred.bounds { if let TraitTyParamBound(_, TraitBoundModifier::Maybe) = *bound { @@ -2045,15 +2046,17 @@ impl<'a> LoweringContext<'a> { if let Some(node_id) = self.resolver.definitions().as_local_node_id(def_id) { - for param in &g.params { - if let GenericParamAST::Type(ref ty_param) = *param { - if node_id == ty_param.id { - add_bounds - .entry(ty_param.id) - .or_insert(Vec::new()) - .push(bound.clone()); - continue 'next_bound; + for param in &generics.params { + match param.kind { + GenericParamKindAST::Type { .. } => { + if node_id == param.id { + add_bounds.entry(param.id) + .or_insert(Vec::new()) + .push(bound.clone()); + continue 'next_bound; + } } + _ => {} } } } @@ -2068,9 +2071,9 @@ impl<'a> LoweringContext<'a> { } hir::Generics { - params: self.lower_generic_params(&g.params, &add_bounds, itctx), - where_clause: self.lower_where_clause(&g.where_clause), - span: g.span, + params: self.lower_generic_params(&generics.params, &add_bounds, itctx), + where_clause: self.lower_where_clause(&generics.where_clause), + span: generics.span, } } @@ -2093,8 +2096,8 @@ impl<'a> LoweringContext<'a> { span, }) => { self.with_in_scope_lifetime_defs( - bound_generic_params.iter().filter_map(|p| match p { - GenericParamAST::Lifetime(ld) => Some(ld), + bound_generic_params.iter().filter_map(|param| match param.kind { + GenericParamKindAST::Lifetime { .. } => Some(param), _ => None, }), |this| { @@ -2412,8 +2415,8 @@ impl<'a> LoweringContext<'a> { ); let new_impl_items = self.with_in_scope_lifetime_defs( - ast_generics.params.iter().filter_map(|p| match p { - GenericParamAST::Lifetime(ld) => Some(ld), + ast_generics.params.iter().filter_map(|param| match param.kind { + GenericParamKindAST::Lifetime { .. } => Some(param), _ => None, }), |this| { diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 7ab6e17ac35..6015063aa82 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -171,24 +171,17 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } fn visit_generic_param(&mut self, param: &'a GenericParamAST) { - match *param { - GenericParamAST::Lifetime(ref lifetime_def) => { - self.create_def( - lifetime_def.lifetime.id, - DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_interned_str()), - REGULAR_SPACE, - lifetime_def.lifetime.ident.span - ); - } - GenericParamAST::Type(ref ty_param) => { - self.create_def( - ty_param.id, - DefPathData::TypeParam(ty_param.ident.name.as_interned_str()), - REGULAR_SPACE, - ty_param.ident.span - ); - } - } + let name = param.ident.name.as_interned_str(); + let def_path_data = match param.kind { + GenericParamKindAST::Lifetime { .. } => DefPathData::LifetimeDef(name), + GenericParamKindAST::Type { .. } => DefPathData::TypeParam(name), + }; + self.create_def( + param.id, + def_path_data, + REGULAR_SPACE, + param.ident.span + ); visit::walk_generic_param(self, param); } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index b50407c82d1..d7ebd40f49b 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -139,30 +139,24 @@ impl<'a> AstValidator<'a> { } fn check_late_bound_lifetime_defs(&self, params: &Vec) { - // Check: Only lifetime parameters - let non_lifetime_param_spans : Vec<_> = params.iter() - .filter_map(|param| match *param { - GenericParamAST::Lifetime(_) => None, - GenericParamAST::Type(ref t) => Some(t.ident.span), + // Check only lifetime parameters are present and that the lifetime + // parameters that are present have no bounds. + let non_lifetime_param_spans: Vec<_> = params.iter() + .filter_map(|param| match param.kind { + GenericParamKindAST::Lifetime { ref bounds, .. } => { + if !bounds.is_empty() { + let spans: Vec<_> = bounds.iter().map(|b| b.ident.span).collect(); + self.err_handler().span_err(spans, + "lifetime bounds cannot be used in this context"); + } + None + } + _ => Some(param.ident.span), }).collect(); if !non_lifetime_param_spans.is_empty() { self.err_handler().span_err(non_lifetime_param_spans, "only lifetime parameters can be used in this context"); } - - // Check: No bounds on lifetime parameters - for param in params.iter() { - match *param { - GenericParamAST::Lifetime(ref l) => { - if !l.bounds.is_empty() { - let spans: Vec<_> = l.bounds.iter().map(|b| b.ident.span).collect(); - self.err_handler().span_err(spans, - "lifetime bounds cannot be used in this context"); - } - } - GenericParamAST::Type(_) => {} - } - } } } @@ -335,22 +329,21 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::TraitAlias(Generics { ref params, .. }, ..) => { for param in params { - if let GenericParamAST::Type(TyParam { - ident, - ref bounds, - ref default, - .. - }) = *param - { - if !bounds.is_empty() { - self.err_handler().span_err(ident.span, - "type parameters on the left side of a \ - trait alias cannot be bounded"); - } - if !default.is_none() { - self.err_handler().span_err(ident.span, - "type parameters on the left side of a \ - trait alias cannot have defaults"); + match param.kind { + GenericParamKindAST::Lifetime { .. } => {} + GenericParamKindAST::Type { ref bounds, ref default, .. } => { + if !bounds.is_empty() { + self.err_handler().span_err(param.ident.span, + "type parameters on the left side \ + of a trait alias cannot be \ + bounded"); + } + if !default.is_none() { + self.err_handler().span_err(param.ident.span, + "type parameters on the left side \ + of a trait alias cannot have \ + defaults"); + } } } } @@ -413,24 +406,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> { let mut seen_non_lifetime_param = false; let mut seen_default = None; for param in &g.params { - match (param, seen_non_lifetime_param) { - (&GenericParamAST::Lifetime(ref ld), true) => { + match (¶m.kind, seen_non_lifetime_param) { + (GenericParamKindAST::Lifetime { .. }, true) => { self.err_handler() - .span_err(ld.lifetime.ident.span, "lifetime parameters must be leading"); + .span_err(param.ident.span, "lifetime parameters must be leading"); }, - (&GenericParamAST::Lifetime(_), false) => {} - _ => { + (GenericParamKindAST::Lifetime { .. }, false) => {} + (GenericParamKindAST::Type { ref default, .. }, _) => { seen_non_lifetime_param = true; + if default.is_some() { + seen_default = Some(param.ident.span); + } else if let Some(span) = seen_default { + self.err_handler() + .span_err(span, "type parameters with a default must be trailing"); + break; + } } } - - if let GenericParamAST::Type(ref ty_param @ TyParam { default: Some(_), .. }) = *param { - seen_default = Some(ty_param.ident.span); - } else if let Some(span) = seen_default { - self.err_handler() - .span_err(span, "type parameters with a default must be trailing"); - break - } } for predicate in &g.where_clause.predicates { if let WherePredicate::EqPredicate(ref predicate) = *predicate { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index d70a7e2b827..37264eb3382 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -56,7 +56,7 @@ use syntax::util::lev_distance::find_best_match_for_name; use syntax::visit::{self, FnKind, Visitor}; use syntax::attr; use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind}; -use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamAST, Generics}; +use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, GenericParamKindAST, Generics}; use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; use syntax::ast::{Label, Local, Mutability, Pat, PatKind, Path}; use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind}; @@ -797,31 +797,43 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { // put all the parameters on the ban list and then remove // them one by one as they are processed and become available. let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind); + let mut found_default = false; default_ban_rib.bindings.extend(generics.params.iter() - .filter_map(|p| if let GenericParamAST::Type(ref tp) = *p { Some(tp) } else { None }) - .skip_while(|p| p.default.is_none()) - .map(|p| (Ident::with_empty_ctxt(p.ident.name), Def::Err))); + .filter_map(|param| match param.kind { + GenericParamKindAST::Lifetime { .. } => None, + GenericParamKindAST::Type { ref default, .. } => { + if default.is_some() { + found_default = true; + } + if found_default { + return Some((Ident::with_empty_ctxt(param.ident.name), Def::Err)); + } + None + } + })); for param in &generics.params { - match *param { - GenericParamAST::Lifetime(_) => self.visit_generic_param(param), - GenericParamAST::Type(ref ty_param) => { - for bound in &ty_param.bounds { + match param.kind { + GenericParamKindAST::Lifetime { .. } => self.visit_generic_param(param), + GenericParamKindAST::Type { ref bounds, ref default, .. } => { + for bound in bounds { self.visit_ty_param_bound(bound); } - if let Some(ref ty) = ty_param.default { + if let Some(ref ty) = default { self.ribs[TypeNS].push(default_ban_rib); self.visit_ty(ty); default_ban_rib = self.ribs[TypeNS].pop().unwrap(); } // Allow all following defaults to refer to this type parameter. - default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(ty_param.ident.name)); + default_ban_rib.bindings.remove(&Ident::with_empty_ctxt(param.ident.name)); } } } - for p in &generics.where_clause.predicates { self.visit_where_predicate(p); } + for p in &generics.where_clause.predicates { + self.visit_where_predicate(p); + } } } @@ -2198,25 +2210,28 @@ impl<'a> Resolver<'a> { let mut function_type_rib = Rib::new(rib_kind); let mut seen_bindings = FxHashMap(); for param in &generics.params { - if let GenericParamAST::Type(ref type_parameter) = *param { - let ident = type_parameter.ident.modern(); - debug!("with_type_parameter_rib: {}", type_parameter.id); + match param.kind { + GenericParamKindAST::Type { .. } => { + let ident = param.ident.modern(); + debug!("with_type_parameter_rib: {}", param.id); - if seen_bindings.contains_key(&ident) { - let span = seen_bindings.get(&ident).unwrap(); - let err = ResolutionError::NameAlreadyUsedInTypeParameterList( - ident.name, - span, - ); - resolve_error(self, type_parameter.ident.span, err); + if seen_bindings.contains_key(&ident) { + let span = seen_bindings.get(&ident).unwrap(); + let err = ResolutionError::NameAlreadyUsedInTypeParameterList( + ident.name, + span, + ); + resolve_error(self, param.ident.span, err); + } + seen_bindings.entry(ident).or_insert(param.ident.span); + + // plain insert (no renaming) + let def_id = self.definitions.local_def_id(param.id); + let def = Def::TyParam(def_id); + function_type_rib.bindings.insert(ident, def); + self.record_def(param.id, PathResolution::new(def)); } - seen_bindings.entry(ident).or_insert(type_parameter.ident.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)); + _ => {} } } 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 303406dac76..94552e08a8c 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -370,35 +370,38 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { id: NodeId, ) { for param in &generics.params { - if let ast::GenericParamAST::Type(ref ty_param) = *param { - let param_ss = ty_param.ident.span; - let name = escape(self.span.snippet(param_ss)); - // Append $id to name to make sure each one is unique - let qualname = format!("{}::{}${}", prefix, name, id); - if !self.span.filter_generated(Some(param_ss), full_span) { - let id = ::id_from_node_id(ty_param.id, &self.save_ctxt); - let span = self.span_from_span(param_ss); + match param.kind { + ast::GenericParamKindAST::Lifetime { .. } => {} + ast::GenericParamKindAST::Type { .. } => { + let param_ss = param.ident.span; + let name = escape(self.span.snippet(param_ss)); + // Append $id to name to make sure each one is unique. + let qualname = format!("{}::{}${}", prefix, name, id); + if !self.span.filter_generated(Some(param_ss), full_span) { + let id = ::id_from_node_id(param.id, &self.save_ctxt); + let span = self.span_from_span(param_ss); - self.dumper.dump_def( - &Access { - public: false, - reachable: false, - }, - Def { - kind: DefKind::Type, - id, - span, - name, - qualname, - value: String::new(), - parent: None, - children: vec![], - decl_id: None, - docs: String::new(), - sig: None, - attributes: vec![], - }, - ); + self.dumper.dump_def( + &Access { + public: false, + reachable: false, + }, + Def { + kind: DefKind::Type, + id, + span, + name, + qualname, + value: String::new(), + parent: None, + children: vec![], + decl_id: None, + docs: String::new(), + sig: None, + attributes: vec![], + }, + ); + } } } } @@ -1479,14 +1482,17 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc fn visit_generics(&mut self, generics: &'l ast::Generics) { for param in &generics.params { - if let ast::GenericParamAST::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) + match param.kind { + ast::GenericParamKindAST::Lifetime { .. } => {} + ast::GenericParamKindAST::Type { ref bounds, ref default, .. } => { + for bound in bounds { + 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) = default { + self.visit_ty(&ty); } - } - if let Some(ref ty) = ty_param.default { - self.visit_ty(&ty); } } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index a634e979363..f656b013c0a 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -934,9 +934,9 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String { sig.push_str(&generics .params .iter() - .map(|param| match *param { - ast::GenericParamAST::Lifetime(ref l) => l.lifetime.ident.name.to_string(), - ast::GenericParamAST::Type(ref t) => t.ident.to_string(), + .map(|param| match param.kind { + ast::GenericParamKindAST::Lifetime { .. } => param.ident.name.to_string(), + ast::GenericParamKindAST::Type { .. } => param.ident.to_string(), }) .collect::>() .join(", ")); diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index f5384683506..8e8e0dfa182 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -223,9 +223,9 @@ impl Sig for ast::Ty { text.push_str("for<"); text.push_str(&f.generic_params .iter() - .filter_map(|p| match *p { - ast::GenericParamAST::Lifetime(ref l) => { - Some(l.lifetime.ident.to_string()) + .filter_map(|param| match param.kind { + ast::GenericParamKindAST::Lifetime { .. } => { + Some(param.ident.to_string()) } _ => None, }) @@ -617,45 +617,34 @@ impl Sig for ast::Generics { let mut defs = vec![]; for param in &self.params { - match *param { - ast::GenericParamAST::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() + let mut param_text = param.ident.to_string(); + defs.push(SigElement { + id: id_from_node_id(param.id, scx), + start: offset + text.len(), + end: offset + text.len() + param_text.len(), + }); + match param.kind { + ast::GenericParamKindAST::Lifetime { ref bounds, .. } => { + if !bounds.is_empty() { + param_text.push_str(": "); + let bounds = bounds.iter() .map(|l| l.ident.to_string()) .collect::>() .join(" + "); - l_text.push_str(&bounds); + param_text.push_str(&bounds); // FIXME add lifetime bounds refs. } - text.push_str(&l_text); - text.push(','); } - ast::GenericParamAST::Type(ref t) => { - let mut t_text = t.ident.to_string(); - defs.push(SigElement { - id: id_from_node_id(t.id, scx), - start: offset + text.len(), - end: offset + text.len() + t_text.len(), - }); - - if !t.bounds.is_empty() { - t_text.push_str(": "); - t_text.push_str(&pprust::bounds_to_string(&t.bounds)); + ast::GenericParamKindAST::Type { ref bounds, .. } => { + if !bounds.is_empty() { + param_text.push_str(": "); + param_text.push_str(&pprust::bounds_to_string(bounds)); // FIXME descend properly into bounds. } - text.push_str(&t_text); - text.push(','); } } + text.push_str(¶m_text); + text.push(','); } text.push('>'); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 17df8dd7027..c354edc5aaf 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -58,14 +58,6 @@ impl fmt::Debug for Lifetime { } } -/// A lifetime definition, e.g. `'a: 'b+'c+'d` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct LifetimeDef { - pub attrs: ThinVec, - pub lifetime: Lifetime, - pub bounds: Vec -} - /// A "Path" is essentially Rust's notion of a name. /// /// It's represented as a sequence of identifiers, @@ -329,31 +321,38 @@ pub enum TraitBoundModifier { pub type TyParamBounds = Vec; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct TyParam { - pub attrs: ThinVec, - pub ident: Ident, - pub id: NodeId, - pub bounds: TyParamBounds, - pub default: Option>, +pub enum GenericParamKindAST { + /// A lifetime definition, e.g. `'a: 'b+'c+'d`. + Lifetime { + bounds: Vec, + lifetime: Lifetime, + }, + Type { + bounds: TyParamBounds, + default: Option>, + } } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum GenericParamAST { - Lifetime(LifetimeDef), - Type(TyParam), +pub struct GenericParamAST { + pub ident: Ident, + pub id: NodeId, + pub attrs: ThinVec, + + pub kind: GenericParamKindAST, } impl GenericParamAST { pub fn is_lifetime_param(&self) -> bool { - match *self { - GenericParamAST::Lifetime(_) => true, + match self.kind { + GenericParamKindAST::Lifetime { .. } => true, _ => false, } } pub fn is_type_param(&self) -> bool { - match *self { - GenericParamAST::Type(_) => true, + match self.kind { + GenericParamKindAST::Type { .. } => true, _ => false, } } @@ -383,10 +382,8 @@ impl Generics { pub fn span_for_name(&self, name: &str) -> Option { for param in &self.params { - if let GenericParamAST::Type(ref t) = *param { - if t.ident.name == name { - return Some(t.ident.span); - } + if param.ident.name == name { + return Some(param.ident.span); } } None diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 1c74a2bd5be..42745c14965 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -69,7 +69,7 @@ pub trait AstBuilder { id: ast::Ident, attrs: Vec, bounds: ast::TyParamBounds, - default: Option>) -> ast::TyParam; + default: Option>) -> ast::GenericParamAST; fn trait_ref(&self, path: ast::Path) -> ast::TraitRef; fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef; @@ -80,7 +80,7 @@ pub trait AstBuilder { ident: ast::Ident, attrs: Vec, bounds: Vec) - -> ast::LifetimeDef; + -> ast::GenericParamAST; // statements fn stmt_expr(&self, expr: P) -> ast::Stmt; @@ -437,13 +437,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ident: ast::Ident, attrs: Vec, bounds: ast::TyParamBounds, - default: Option>) -> ast::TyParam { - ast::TyParam { + default: Option>) -> ast::GenericParamAST { + ast::GenericParamAST { ident: ident.with_span_pos(span), id: ast::DUMMY_NODE_ID, attrs: attrs.into(), - bounds, - default, + kind: ast::GenericParamKindAST::Type { + bounds, + default, + } } } @@ -475,11 +477,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ident: ast::Ident, attrs: Vec, bounds: Vec) - -> ast::LifetimeDef { - ast::LifetimeDef { + -> ast::GenericParamAST { + let lifetime = self.lifetime(span, ident); + ast::GenericParamAST { + ident: lifetime.ident, + id: lifetime.id, attrs: attrs.into(), - lifetime: self.lifetime(span, ident), - bounds, + kind: ast::GenericParamKindAST::Lifetime { + lifetime, + bounds, + } } } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1e09c7b2206..2f43487e036 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -687,38 +687,23 @@ pub fn noop_fold_ty_param_bound(tpb: TyParamBound, fld: &mut T) } } -pub fn noop_fold_ty_param(tp: TyParam, fld: &mut T) -> TyParam { - let TyParam {attrs, id, ident, bounds, default} = tp; - let attrs: Vec<_> = attrs.into(); - TyParam { - attrs: attrs.into_iter() - .flat_map(|x| fld.fold_attribute(x).into_iter()) - .collect::>() - .into(), - id: fld.new_id(id), - ident: fld.fold_ident(ident), - bounds: fld.fold_bounds(bounds), - default: default.map(|x| fld.fold_ty(x)), - } -} - pub fn noop_fold_generic_param(param: GenericParamAST, fld: &mut T) -> GenericParamAST { match param { - GenericParamAST::Lifetime(l) => { - let attrs: Vec<_> = l.attrs.into(); + GenericParamAST::Lifetime { bounds, lifetime } => { + let attrs: Vec<_> = param.attrs.into(); GenericParamAST::Lifetime(LifetimeDef { attrs: attrs.into_iter() .flat_map(|x| fld.fold_attribute(x).into_iter()) .collect::>() .into(), lifetime: Lifetime { - id: fld.new_id(l.lifetime.id), - ident: fld.fold_ident(l.lifetime.ident), + id: fld.new_id(param.id), + ident: fld.fold_ident(param.ident), }, - bounds: l.bounds.move_map(|l| noop_fold_lifetime(l, fld)), + bounds: bounds.move_map(|l| noop_fold_lifetime(l, fld)), }) } - GenericParamAST::Type(t) => GenericParamAST::Type(fld.fold_ty_param(t)), + GenericParamAST::Type { .. } => GenericParamAST::Type(fld.fold_ty_param(param)), } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index be4a4b8b11f..2a1fc6b291c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -21,10 +21,10 @@ use ast::EnumDef; use ast::{Expr, ExprKind, RangeLimits}; use ast::{Field, FnDecl}; use ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; -use ast::GenericParamAST; +use ast::{GenericParamAST, GenericParamKindAST}; use ast::GenericArgAST; use ast::{Ident, ImplItem, IsAuto, Item, ItemKind}; -use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind}; +use ast::{Label, Lifetime, Lit, LitKind}; use ast::Local; use ast::MacStmtStyle; use ast::{Mac, Mac_, MacDelimiter}; @@ -36,7 +36,7 @@ use ast::{VariantData, StructField}; use ast::StrStyle; use ast::SelfKind; use ast::{TraitItem, TraitRef, TraitObjectSyntax}; -use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; +use ast::{Ty, TyKind, TypeBinding, TyParamBounds}; use ast::{Visibility, VisibilityKind, WhereClause, CrateSugar}; use ast::{UseTree, UseTreeKind}; use ast::{BinOpKind, UnOp}; @@ -1311,9 +1311,7 @@ impl<'a> Parser<'a> { let lo = self.span; let (name, node, generics) = if self.eat_keyword(keywords::Type) { - let (generics, TyParam {ident, bounds, default, ..}) = - self.parse_trait_item_assoc_ty(vec![])?; - (ident, TraitItemKind::Type(bounds, default), generics) + self.parse_trait_item_assoc_ty()? } else if self.is_const_item() { self.expect_keyword(keywords::Const)?; let ident = self.parse_ident()?; @@ -4805,7 +4803,9 @@ impl<'a> Parser<'a> { } /// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )? - fn parse_ty_param(&mut self, preceding_attrs: Vec) -> PResult<'a, TyParam> { + fn parse_ty_param(&mut self, + preceding_attrs: Vec) + -> PResult<'a, GenericParamAST> { let ident = self.parse_ident()?; // Parse optional colon and param bounds. @@ -4821,19 +4821,21 @@ impl<'a> Parser<'a> { None }; - Ok(TyParam { - attrs: preceding_attrs.into(), + Ok(GenericParamAST { ident, + attrs: preceding_attrs.into(), id: ast::DUMMY_NODE_ID, - bounds, - default, + kind: GenericParamKindAST::Type { + bounds, + default, + } }) } /// Parses the following grammar: /// TraitItemAssocTy = Ident ["<"...">"] [":" [TyParamBounds]] ["where" ...] ["=" Ty] - fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec) - -> PResult<'a, (ast::Generics, TyParam)> { + fn parse_trait_item_assoc_ty(&mut self) + -> PResult<'a, (Ident, TraitItemKind, ast::Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -4852,13 +4854,7 @@ impl<'a> Parser<'a> { }; self.expect(&token::Semi)?; - Ok((generics, TyParam { - attrs: preceding_attrs.into(), - ident, - id: ast::DUMMY_NODE_ID, - bounds, - default, - })) + Ok((ident, TraitItemKind::Type(bounds, default), generics)) } /// Parses (possibly empty) list of lifetime and type parameters, possibly including @@ -4876,18 +4872,22 @@ impl<'a> Parser<'a> { } else { Vec::new() }; - params.push(ast::GenericParamAST::Lifetime(LifetimeDef { + params.push(ast::GenericParamAST { + ident: lifetime.ident, + id: lifetime.id, attrs: attrs.into(), - lifetime, - bounds, - })); + kind: ast::GenericParamKindAST::Lifetime { + 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. - params.push(ast::GenericParamAST::Type(self.parse_ty_param(attrs)?)); + params.push(self.parse_ty_param(attrs)?); seen_ty_param = true; } else { // Check for trailing attributes and stop parsing. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a7a85a4c71f..1626135400d 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2878,12 +2878,24 @@ impl<'a> State<'a> { self.s.word("<")?; self.commasep(Inconsistent, &generic_params, |s, param| { - match *param { - ast::GenericParamAST::Lifetime(ref lifetime_def) => { - s.print_outer_attributes_inline(&lifetime_def.attrs)?; - s.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds) + match param.kind { + ast::GenericParamKindAST::Lifetime { ref bounds, ref lifetime } => { + s.print_outer_attributes_inline(¶m.attrs)?; + s.print_lifetime_bounds(lifetime, bounds) }, - ast::GenericParamAST::Type(ref ty_param) => s.print_ty_param(ty_param), + ast::GenericParamKindAST::Type { ref bounds, ref default } => { + s.print_outer_attributes_inline(¶m.attrs)?; + s.print_ident(param.ident)?; + s.print_bounds(":", bounds)?; + match default { + Some(ref default) => { + s.s.space()?; + s.word_space("=")?; + s.print_type(default) + } + _ => Ok(()) + } + } } })?; @@ -2891,20 +2903,6 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> { - self.print_outer_attributes_inline(¶m.attrs)?; - self.print_ident(param.ident)?; - self.print_bounds(":", ¶m.bounds)?; - match param.default { - Some(ref default) => { - self.s.space()?; - self.word_space("=")?; - self.print_type(default) - } - _ => Ok(()) - } - } - pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause) -> io::Result<()> { if where_clause.predicates.is_empty() { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 091673bfba9..c919f6c355c 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -491,17 +491,17 @@ pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyPar } pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParamAST) { - match *param { - GenericParamAST::Lifetime(ref l) => { - visitor.visit_ident(l.lifetime.ident); - walk_list!(visitor, visit_lifetime, &l.bounds); - walk_list!(visitor, visit_attribute, &*l.attrs); + match param.kind { + GenericParamKindAST::Lifetime { ref bounds, ref lifetime, .. } => { + visitor.visit_ident(param.ident); + walk_list!(visitor, visit_lifetime, bounds); + walk_list!(visitor, visit_attribute, param.attrs.iter()); } - GenericParamAST::Type(ref t) => { + GenericParamKindAST::Type { ref bounds, ref default, .. } => { visitor.visit_ident(t.ident); - walk_list!(visitor, visit_ty_param_bound, &t.bounds); - walk_list!(visitor, visit_ty, &t.default); - walk_list!(visitor, visit_attribute, &*t.attrs); + walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_ty, default); + walk_list!(visitor, visit_attribute, param.attrs.iter()); } } } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 4bc8d208bab..cbf7b1e0876 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -192,8 +192,8 @@ use std::collections::HashSet; use std::vec; use rustc_target::spec::abi::Abi; -use syntax::ast::{self, BinOpKind, EnumDef, Expr, GenericParamAST, Generics, Ident, PatKind}; -use syntax::ast::{VariantData, GenericArgAST}; +use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; +use syntax::ast::{VariantData, GenericParamKindAST, GenericArgAST}; use syntax::attr; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ext::build::AstBuilder; @@ -547,9 +547,9 @@ impl<'a> TraitDef<'a> { // Create the generic parameters params.extend(generics.params.iter().map(|param| { - match *param { - ref l @ GenericParamAST::Lifetime(_) => l.clone(), - GenericParamAST::Type(ref ty_param) => { + match param.kind { + GenericParamKindAST::Lifetime { .. } => param.clone(), + GenericParamKindAST::Type { bounds: ref ty_bounds, .. } => { // I don't think this can be moved out of the loop, since // a TyParamBound requires an ast id let mut bounds: Vec<_> = @@ -564,12 +564,11 @@ impl<'a> TraitDef<'a> { bounds.push(cx.typarambound(trait_path.clone())); // also add in any bounds from the declaration - for declared_bound in ty_param.bounds.iter() { + for declared_bound in ty_bounds { bounds.push((*declared_bound).clone()); } - let ty_param = cx.typaram(self.span, ty_param.ident, vec![], bounds, None); - GenericParamAST::Type(ty_param) + cx.typaram(self.span, param.ident, vec![], bounds, None) } } })); @@ -607,8 +606,8 @@ impl<'a> TraitDef<'a> { // Extra scope required here so ty_params goes out of scope before params is moved let mut ty_params = params.iter() - .filter_map(|param| match *param { - ast::GenericParamAST::Type(ref t) => Some(t), + .filter_map(|param| match param.kind { + ast::GenericParamKindAST::Type { .. } => Some(param), _ => None, }) .peekable(); @@ -668,17 +667,16 @@ impl<'a> TraitDef<'a> { // Create the type parameters on the `self` path. let self_ty_params: Vec> = generics.params .iter() - .filter_map(|param| match *param { - GenericParamAST::Type(ref ty_param) - => Some(cx.ty_ident(self.span, ty_param.ident)), + .filter_map(|param| match param.kind { + GenericParamKindAST::Type { .. } => Some(cx.ty_ident(self.span, param.ident)), _ => None, }) .collect(); let self_lifetimes: Vec = generics.params .iter() - .filter_map(|param| match *param { - GenericParamAST::Lifetime(ref ld) => Some(ld.lifetime), + .filter_map(|param| match param.kind { + GenericParamKindAST::Lifetime { ref lifetime, .. } => Some(*lifetime), _ => None, }) .collect(); diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index 22487e7bfe3..c9f274ed210 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, GenericParamAST, Generics, Ident, SelfKind, GenericArgAST}; +use syntax::ast::{Expr, GenericParamKindAST, Generics, Ident, SelfKind, GenericArgAST}; use syntax::ext::base::ExtCtxt; use syntax::ext::build::AstBuilder; use syntax::codemap::{respan, DUMMY_SP}; @@ -191,9 +191,9 @@ impl<'a> Ty<'a> { Self_ => { let ty_params: Vec> = self_generics.params .iter() - .filter_map(|param| match *param { - GenericParamAST::Type(ref ty_param) => { - Some(cx.ty_ident(span, ty_param.ident)) + .filter_map(|param| match param.kind { + GenericParamKindAST::Type { .. } => { + Some(cx.ty_ident(span, param.ident)) } _ => None, }) @@ -201,8 +201,8 @@ impl<'a> Ty<'a> { let lifetimes: Vec = self_generics.params .iter() - .filter_map(|param| match *param { - GenericParamAST::Lifetime(ref ld) => Some(ld.lifetime), + .filter_map(|param| match param.kind { + GenericParamKindAST::Lifetime { ref lifetime, .. } => Some(*lifetime), _ => None, }) .collect(); @@ -234,7 +234,7 @@ fn mk_ty_param(cx: &ExtCtxt, bounds: &[Path], self_ident: Ident, self_generics: &Generics) - -> ast::TyParam { + -> ast::GenericParamAST { let bounds = bounds.iter() .map(|b| { let path = b.to_path(cx, span, self_ident, self_generics); @@ -244,7 +244,7 @@ fn mk_ty_param(cx: &ExtCtxt, cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None) } -fn mk_generics(params: Vec, span: Span) -> Generics { +fn mk_generics(params: Vec, span: Span) -> Generics { Generics { params, where_clause: ast::WhereClause { @@ -282,16 +282,13 @@ impl<'a> LifetimeBounds<'a> { let bounds = bounds.iter() .map(|b| cx.lifetime(span, Ident::from_str(b))) .collect(); - let lifetime_def = cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds); - GenericParamAST::Lifetime(lifetime_def) + cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds) }) .chain(self.bounds .iter() .map(|t| { let (name, ref bounds) = *t; - GenericParamAST::Type(mk_ty_param( - cx, span, name, &[], &bounds, self_ty, self_generics - )) + mk_ty_param(cx, span, name, &[], &bounds, self_ty, self_generics) }) ) .collect(); diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 9bc19bb5ede..6813ce4c265 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -134,9 +134,12 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String { match item.node { ast::ItemKind::Struct(_, ast::Generics { ref params, .. }) | ast::ItemKind::Enum(_, ast::Generics { ref params, .. }) => { - for param in params.iter() { - if let ast::GenericParamAST::Type(ref ty) = *param { - typaram.push_str(&ty.ident.as_str()); + for param in params { + match param.kind { + ast::GenericParamKindAST::Type { .. } => { + typaram.push_str(¶m.ident.as_str()); + } + _ => {} } } }