diff options
| author | Jonas Platte <jplatte+git@posteo.de> | 2017-10-16 21:07:26 +0200 |
|---|---|---|
| committer | Jonas Platte <jplatte+git@posteo.de> | 2017-12-21 13:38:10 +0100 |
| commit | 78493ed21aaeb20a8d5f7bd08f26c0c9fd496ed4 (patch) | |
| tree | 628b8d1cc99f88db6f47d5f07e1ff3d10b8adb3c /src/libsyntax_ext | |
| parent | ab7abfcf3457ebc67ac7fef5c3028a6ae4402156 (diff) | |
| download | rust-78493ed21aaeb20a8d5f7bd08f26c0c9fd496ed4.tar.gz rust-78493ed21aaeb20a8d5f7bd08f26c0c9fd496ed4.zip | |
Add GenericParam, refactor Generics in ast, hir, rustdoc
The Generics now contain one Vec of an enum for the generic parameters, rather than two separate Vec's for lifetime and type parameters. Additionally, places that previously used Vec<LifetimeDef> now use Vec<GenericParam> instead.
Diffstat (limited to 'src/libsyntax_ext')
| -rw-r--r-- | src/libsyntax_ext/deriving/clone.rs | 26 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/generic/mod.rs | 152 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/generic/ty.rs | 49 | ||||
| -rw-r--r-- | src/libsyntax_ext/deriving/mod.rs | 10 |
4 files changed, 138 insertions, 99 deletions
diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 35def632fc1..f23d22b0c36 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 2b565ca51e9..29f5196c9bd 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<ast::Name> = 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<ast::Name> = 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<ast::Lifetime> = generics.lifetimes + let self_lifetimes: Vec<ast::Lifetime> = 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 e4faf652389..cc3e8b6e6b7 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<ast::Lifetime> = 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<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>, span: Span) - -> Generics { +fn mk_generics(params: Vec<GenericParam>, 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 a6696b53369..d769732381c 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()); + } } } |
