diff options
| author | bors <bors@rust-lang.org> | 2018-06-21 20:58:51 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-06-21 20:58:51 +0000 |
| commit | 662c70a59f79919640465b8753f790af822e96c8 (patch) | |
| tree | 6cdf8eebd7ef3e59549aa057f85475d86286359b /src/libsyntax | |
| parent | f790780451a724dce9be0ba03ff217955036ff88 (diff) | |
| parent | daf7e359a10306c004bdffd06b6432998d70b858 (diff) | |
| download | rust-662c70a59f79919640465b8753f790af822e96c8.tar.gz rust-662c70a59f79919640465b8753f790af822e96c8.zip | |
Auto merge of #48149 - varkor:generics-generalisation, r=petrochenkov
The Great Generics Generalisation: HIR Edition This is essentially a followup to https://github.com/rust-lang/rust/pull/45930, consolidating the use of separate lifetime and type vectors into single kinds vectors wherever possible. This is intended to provide more of the groundwork for const generics (https://github.com/rust-lang/rust/issues/44580). r? @eddyb cc @yodaldevoid
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 164 | ||||
| -rw-r--r-- | src/libsyntax/attr.rs | 15 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 75 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 159 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 125 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 159 | ||||
| -rw-r--r-- | src/libsyntax/test.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/util/node_count.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 77 |
10 files changed, 360 insertions, 428 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 76fa463a631..c6de2c4da39 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -10,9 +10,8 @@ // The Rust abstract syntax tree. -pub use self::TyParamBound::*; pub use self::UnsafeSource::*; -pub use self::PathParameters::*; +pub use self::GenericArgs::*; pub use symbol::{Ident, Symbol as Name}; pub use util::ThinVec; pub use util::parser::ExprPrecedence; @@ -58,14 +57,6 @@ impl fmt::Debug for Lifetime { } } -/// A lifetime definition, e.g. `'a: 'b+'c+'d` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct LifetimeDef { - pub attrs: ThinVec<Attribute>, - pub lifetime: Lifetime, - pub bounds: Vec<Lifetime> -} - /// A "Path" is essentially Rust's notion of a name. /// /// It's represented as a sequence of identifiers, @@ -135,30 +126,30 @@ pub struct PathSegment { /// `Some` means that parameter list is supplied (`Path<X, Y>`) /// but it can be empty (`Path<>`). /// `P` is used as a size optimization for the common case with no parameters. - pub parameters: Option<P<PathParameters>>, + pub args: Option<P<GenericArgs>>, } impl PathSegment { pub fn from_ident(ident: Ident) -> Self { - PathSegment { ident, parameters: None } + PathSegment { ident, args: None } } pub fn crate_root(span: Span) -> Self { PathSegment::from_ident(Ident::new(keywords::CrateRoot.name(), span)) } } -/// Parameters of a path segment. +/// Arguments of a path segment. /// /// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum PathParameters { +pub enum GenericArgs { /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>` - AngleBracketed(AngleBracketedParameterData), + AngleBracketed(AngleBracketedArgs), /// The `(A,B)` and `C` in `Foo(A,B) -> C` - Parenthesized(ParenthesizedParameterData), + Parenthesized(ParenthesisedArgs), } -impl PathParameters { +impl GenericArgs { pub fn span(&self) -> Span { match *self { AngleBracketed(ref data) => data.span, @@ -167,36 +158,40 @@ impl PathParameters { } } +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum GenericArg { + Lifetime(Lifetime), + Type(P<Ty>), +} + /// A path like `Foo<'a, T>` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Default)] -pub struct AngleBracketedParameterData { +pub struct AngleBracketedArgs { /// Overall span pub span: Span, - /// The lifetime parameters for this path segment. - pub lifetimes: Vec<Lifetime>, - /// The type parameters for this path segment, if present. - pub types: Vec<P<Ty>>, + /// The arguments for this path segment. + pub args: Vec<GenericArg>, /// Bindings (equality constraints) on associated types, if present. /// /// E.g., `Foo<A=Bar>`. pub bindings: Vec<TypeBinding>, } -impl Into<Option<P<PathParameters>>> for AngleBracketedParameterData { - fn into(self) -> Option<P<PathParameters>> { - Some(P(PathParameters::AngleBracketed(self))) +impl Into<Option<P<GenericArgs>>> for AngleBracketedArgs { + fn into(self) -> Option<P<GenericArgs>> { + Some(P(GenericArgs::AngleBracketed(self))) } } -impl Into<Option<P<PathParameters>>> for ParenthesizedParameterData { - fn into(self) -> Option<P<PathParameters>> { - Some(P(PathParameters::Parenthesized(self))) +impl Into<Option<P<GenericArgs>>> for ParenthesisedArgs { + fn into(self) -> Option<P<GenericArgs>> { + Some(P(GenericArgs::Parenthesized(self))) } } /// A path like `Foo(A,B) -> C` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct ParenthesizedParameterData { +pub struct ParenthesisedArgs { /// Overall span pub span: Span, @@ -273,64 +268,52 @@ pub const CRATE_NODE_ID: NodeId = NodeId(0); /// small, positive ids. pub const DUMMY_NODE_ID: NodeId = NodeId(!0); +/// A modifier on a bound, currently this is only used for `?Sized`, where the +/// modifier is `Maybe`. Negative bounds should also be handled here. +#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] +pub enum TraitBoundModifier { + None, + Maybe, +} + /// The AST represents all type param bounds as types. /// typeck::collect::compute_bounds matches these against /// the "special" built-in traits (see middle::lang_items) and /// detects Copy, Send and Sync. #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TyParamBound { - TraitTyParamBound(PolyTraitRef, TraitBoundModifier), - RegionTyParamBound(Lifetime) +pub enum GenericBound { + Trait(PolyTraitRef, TraitBoundModifier), + Outlives(Lifetime) } -impl TyParamBound { +impl GenericBound { pub fn span(&self) -> Span { match self { - &TraitTyParamBound(ref t, ..) => t.span, - &RegionTyParamBound(ref l) => l.ident.span, + &GenericBound::Trait(ref t, ..) => t.span, + &GenericBound::Outlives(ref l) => l.ident.span, } } } -/// A modifier on a bound, currently this is only used for `?Sized`, where the -/// modifier is `Maybe`. Negative bounds should also be handled here. -#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum TraitBoundModifier { - None, - Maybe, -} - -pub type TyParamBounds = Vec<TyParamBound>; +pub type GenericBounds = Vec<GenericBound>; #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct TyParam { - pub attrs: ThinVec<Attribute>, - pub ident: Ident, - pub id: NodeId, - pub bounds: TyParamBounds, - pub default: Option<P<Ty>>, +pub enum GenericParamKind { + /// A lifetime definition, e.g. `'a: 'b+'c+'d`. + Lifetime, + Type { + default: Option<P<Ty>>, + } } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum GenericParam { - Lifetime(LifetimeDef), - Type(TyParam), -} - -impl GenericParam { - pub fn is_lifetime_param(&self) -> bool { - match *self { - GenericParam::Lifetime(_) => true, - _ => false, - } - } +pub struct GenericParam { + pub id: NodeId, + pub ident: Ident, + pub attrs: ThinVec<Attribute>, + pub bounds: GenericBounds, - pub fn is_type_param(&self) -> bool { - match *self { - GenericParam::Type(_) => true, - _ => false, - } - } + pub kind: GenericParamKind, } /// Represents lifetime, type and const parameters attached to a declaration of @@ -342,31 +325,6 @@ pub struct Generics { pub span: Span, } -impl Generics { - pub fn is_lt_parameterized(&self) -> bool { - self.params.iter().any(|param| param.is_lifetime_param()) - } - - pub fn is_type_parameterized(&self) -> bool { - self.params.iter().any(|param| param.is_type_param()) - } - - pub fn is_parameterized(&self) -> bool { - !self.params.is_empty() - } - - pub fn span_for_name(&self, name: &str) -> Option<Span> { - for param in &self.params { - if let GenericParam::Type(ref t) = *param { - if t.ident.name == name { - return Some(t.ident.span); - } - } - } - None - } -} - impl Default for Generics { /// Creates an instance of `Generics`. fn default() -> Generics { @@ -422,7 +380,7 @@ pub struct WhereBoundPredicate { /// The type being bounded pub bounded_ty: P<Ty>, /// Trait and lifetime bounds (`Clone+Send+'static`) - pub bounds: TyParamBounds, + pub bounds: GenericBounds, } /// A lifetime predicate. @@ -432,7 +390,7 @@ pub struct WhereBoundPredicate { pub struct WhereRegionPredicate { pub span: Span, pub lifetime: Lifetime, - pub bounds: Vec<Lifetime>, + pub bounds: GenericBounds, } /// An equality predicate (unsupported). @@ -968,11 +926,11 @@ impl Expr { } } - fn to_bound(&self) -> Option<TyParamBound> { + fn to_bound(&self) -> Option<GenericBound> { match &self.node { ExprKind::Path(None, path) => - Some(TraitTyParamBound(PolyTraitRef::new(Vec::new(), path.clone(), self.span), - TraitBoundModifier::None)), + Some(GenericBound::Trait(PolyTraitRef::new(Vec::new(), path.clone(), self.span), + TraitBoundModifier::None)), _ => None, } } @@ -1393,7 +1351,7 @@ pub struct TraitItem { pub enum TraitItemKind { Const(P<Ty>, Option<P<Expr>>), Method(MethodSig, Option<P<Block>>), - Type(TyParamBounds, Option<P<Ty>>), + Type(GenericBounds, Option<P<Ty>>), Macro(Mac), } @@ -1578,10 +1536,10 @@ pub enum TyKind { Path(Option<QSelf>, Path), /// A trait object type `Bound1 + Bound2 + Bound3` /// where `Bound` is a trait or a lifetime. - TraitObject(TyParamBounds, TraitObjectSyntax), + TraitObject(GenericBounds, TraitObjectSyntax), /// An `impl Bound1 + Bound2 + Bound3` type /// where `Bound` is a trait or a lifetime. - ImplTrait(TyParamBounds), + ImplTrait(GenericBounds), /// No-op; kept solely so that we can pretty-print faithfully Paren(P<Ty>), /// Unused for now @@ -2102,11 +2060,11 @@ pub enum ItemKind { /// A Trait declaration (`trait` or `pub trait`). /// /// E.g. `trait Foo { .. }`, `trait Foo<T> { .. }` or `auto trait Foo {}` - Trait(IsAuto, Unsafety, Generics, TyParamBounds, Vec<TraitItem>), + Trait(IsAuto, Unsafety, Generics, GenericBounds, Vec<TraitItem>), /// Trait alias /// /// E.g. `trait Foo = Bar + Quux;` - TraitAlias(Generics, TyParamBounds), + TraitAlias(Generics, GenericBounds), /// An implementation. /// /// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }` diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 2389ed799cf..ded493fe395 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -1446,17 +1446,12 @@ impl HasAttrs for Stmt { impl HasAttrs for GenericParam { fn attrs(&self) -> &[ast::Attribute] { - match self { - GenericParam::Lifetime(lifetime) => lifetime.attrs(), - GenericParam::Type(ty) => ty.attrs(), - } + &self.attrs } - fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self { - match self { - GenericParam::Lifetime(lifetime) => GenericParam::Lifetime(lifetime.map_attrs(f)), - GenericParam::Type(ty) => GenericParam::Type(ty.map_attrs(f)), - } + fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(mut self, f: F) -> Self { + self.attrs = self.attrs.map_attrs(f); + self } } @@ -1479,5 +1474,5 @@ macro_rules! derive_has_attrs { derive_has_attrs! { Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm, - ast::Field, ast::FieldPat, ast::Variant_, ast::LifetimeDef, ast::TyParam + ast::Field, ast::FieldPat, ast::Variant_ } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 4a6f06dcc17..9044cab05d6 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -30,10 +30,9 @@ pub trait AstBuilder { fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path; fn path_all(&self, sp: Span, global: bool, - idents: Vec<ast::Ident> , - lifetimes: Vec<ast::Lifetime>, - types: Vec<P<ast::Ty>>, - bindings: Vec<ast::TypeBinding> ) + idents: Vec<ast::Ident>, + args: Vec<ast::GenericArg>, + bindings: Vec<ast::TypeBinding>) -> ast::Path; fn qpath(&self, self_type: P<ast::Ty>, @@ -43,8 +42,7 @@ pub trait AstBuilder { fn qpath_all(&self, self_type: P<ast::Ty>, trait_path: ast::Path, ident: ast::Ident, - lifetimes: Vec<ast::Lifetime>, - types: Vec<P<ast::Ty>>, + args: Vec<ast::GenericArg>, bindings: Vec<ast::TypeBinding>) -> (ast::QSelf, ast::Path); @@ -70,19 +68,19 @@ pub trait AstBuilder { span: Span, id: ast::Ident, attrs: Vec<ast::Attribute>, - bounds: ast::TyParamBounds, - default: Option<P<ast::Ty>>) -> ast::TyParam; + bounds: ast::GenericBounds, + default: Option<P<ast::Ty>>) -> ast::GenericParam; fn trait_ref(&self, path: ast::Path) -> ast::TraitRef; fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef; - fn typarambound(&self, path: ast::Path) -> ast::TyParamBound; + fn trait_bound(&self, path: ast::Path) -> ast::GenericBound; fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime; fn lifetime_def(&self, span: Span, ident: ast::Ident, attrs: Vec<ast::Attribute>, - bounds: Vec<ast::Lifetime>) - -> ast::LifetimeDef; + bounds: ast::GenericBounds) + -> ast::GenericParam; // statements fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt; @@ -304,34 +302,33 @@ pub trait AstBuilder { impl<'a> AstBuilder for ExtCtxt<'a> { fn path(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path { - self.path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new()) + self.path_all(span, false, strs, vec![], vec![]) } fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path { self.path(span, vec![id]) } fn path_global(&self, span: Span, strs: Vec<ast::Ident> ) -> ast::Path { - self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new()) + self.path_all(span, true, strs, vec![], vec![]) } fn path_all(&self, span: Span, global: bool, mut idents: Vec<ast::Ident> , - lifetimes: Vec<ast::Lifetime>, - types: Vec<P<ast::Ty>>, + args: Vec<ast::GenericArg>, bindings: Vec<ast::TypeBinding> ) -> ast::Path { let last_ident = idents.pop().unwrap(); - let mut segments: Vec<ast::PathSegment> = Vec::new(); + let mut segments: Vec<ast::PathSegment> = vec![]; segments.extend(idents.into_iter().map(|ident| { ast::PathSegment::from_ident(ident.with_span_pos(span)) })); - let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() { - ast::AngleBracketedParameterData { lifetimes, types, bindings, span }.into() + let args = if !args.is_empty() || !bindings.is_empty() { + ast::AngleBracketedArgs { args, bindings, span }.into() } else { None }; - segments.push(ast::PathSegment { ident: last_ident.with_span_pos(span), parameters }); + segments.push(ast::PathSegment { ident: last_ident.with_span_pos(span), args }); let mut path = ast::Path { span, segments }; if global { if let Some(seg) = path.make_root() { @@ -349,7 +346,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { trait_path: ast::Path, ident: ast::Ident) -> (ast::QSelf, ast::Path) { - self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![]) + self.qpath_all(self_type, trait_path, ident, vec![], vec![]) } /// Constructs a qualified path. @@ -359,17 +356,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self_type: P<ast::Ty>, trait_path: ast::Path, ident: ast::Ident, - lifetimes: Vec<ast::Lifetime>, - types: Vec<P<ast::Ty>>, + args: Vec<ast::GenericArg>, bindings: Vec<ast::TypeBinding>) -> (ast::QSelf, ast::Path) { let mut path = trait_path; - let parameters = if !lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty() { - ast::AngleBracketedParameterData { lifetimes, types, bindings, span: ident.span }.into() + let args = if !args.is_empty() || !bindings.is_empty() { + ast::AngleBracketedArgs { args, bindings, span: ident.span }.into() } else { None }; - path.segments.push(ast::PathSegment { ident, parameters }); + path.segments.push(ast::PathSegment { ident, args }); (ast::QSelf { ty: self_type, @@ -428,8 +424,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.path_all(DUMMY_SP, true, self.std_path(&["option", "Option"]), - Vec::new(), - vec![ ty ], + vec![ast::GenericArg::Type(ty)], Vec::new())) } @@ -441,14 +436,16 @@ impl<'a> AstBuilder for ExtCtxt<'a> { span: Span, ident: ast::Ident, attrs: Vec<ast::Attribute>, - bounds: ast::TyParamBounds, - default: Option<P<ast::Ty>>) -> ast::TyParam { - ast::TyParam { + bounds: ast::GenericBounds, + default: Option<P<ast::Ty>>) -> ast::GenericParam { + ast::GenericParam { ident: ident.with_span_pos(span), id: ast::DUMMY_NODE_ID, attrs: attrs.into(), bounds, - default, + kind: ast::GenericParamKind::Type { + default, + } } } @@ -467,8 +464,9 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } } - fn typarambound(&self, path: ast::Path) -> ast::TyParamBound { - ast::TraitTyParamBound(self.poly_trait_ref(path.span, path), ast::TraitBoundModifier::None) + fn trait_bound(&self, path: ast::Path) -> ast::GenericBound { + ast::GenericBound::Trait(self.poly_trait_ref(path.span, path), + ast::TraitBoundModifier::None) } fn lifetime(&self, span: Span, ident: ast::Ident) -> ast::Lifetime { @@ -479,12 +477,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> { span: Span, ident: ast::Ident, attrs: Vec<ast::Attribute>, - bounds: Vec<ast::Lifetime>) - -> ast::LifetimeDef { - ast::LifetimeDef { + bounds: ast::GenericBounds) + -> ast::GenericParam { + let lifetime = self.lifetime(span, ident); + ast::GenericParam { + ident: lifetime.ident, + id: lifetime.id, attrs: attrs.into(), - lifetime: self.lifetime(span, ident), bounds, + kind: ast::GenericParamKind::Lifetime, } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index a2ea6a21484..be4cf197be4 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1797,7 +1797,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, associated_type_defaults, ti.span, "associated type defaults are unstable"); } - if ti.generics.is_parameterized() { + if !ti.generics.params.is_empty() { gate_feature_post!(&self, generic_associated_types, ti.span, "generic associated types are unstable"); } @@ -1824,7 +1824,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, const_fn, ii.span, "const fn is unstable"); } } - ast::ImplItemKind::Type(_) if ii.generics.is_parameterized() => { + ast::ImplItemKind::Type(_) if !ii.generics.params.is_empty() => { gate_feature_post!(&self, generic_associated_types, ii.span, "generic associated types are unstable"); } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 8544ef330dc..93248fe3bfa 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -132,10 +132,21 @@ pub trait Folder : Sized { noop_fold_exprs(es, self) } + fn fold_generic_arg(&mut self, arg: GenericArg) -> GenericArg { + match arg { + GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.fold_lifetime(lt)), + GenericArg::Type(ty) => GenericArg::Type(self.fold_ty(ty)), + } + } + fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> { noop_fold_ty(t, self) } + fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime { + noop_fold_lifetime(l, self) + } + fn fold_ty_binding(&mut self, t: TypeBinding) -> TypeBinding { noop_fold_ty_binding(t, self) } @@ -172,18 +183,18 @@ pub trait Folder : Sized { noop_fold_qpath(qs, p, self) } - fn fold_path_parameters(&mut self, p: PathParameters) -> PathParameters { - noop_fold_path_parameters(p, self) + fn fold_generic_args(&mut self, p: GenericArgs) -> GenericArgs { + noop_fold_generic_args(p, self) } - fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedParameterData) - -> AngleBracketedParameterData + fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedArgs) + -> AngleBracketedArgs { noop_fold_angle_bracketed_parameter_data(p, self) } - fn fold_parenthesized_parameter_data(&mut self, p: ParenthesizedParameterData) - -> ParenthesizedParameterData + fn fold_parenthesized_parameter_data(&mut self, p: ParenthesisedArgs) + -> ParenthesisedArgs { noop_fold_parenthesized_parameter_data(p, self) } @@ -233,10 +244,6 @@ pub trait Folder : Sized { noop_fold_variant_data(vdata, self) } - fn fold_ty_param(&mut self, tp: TyParam) -> TyParam { - noop_fold_ty_param(tp, self) - } - fn fold_generic_param(&mut self, param: GenericParam) -> GenericParam { noop_fold_generic_param(param, self) } @@ -261,18 +268,16 @@ pub trait Folder : Sized { noop_fold_interpolated(nt, self) } - fn fold_opt_bounds(&mut self, b: Option<TyParamBounds>) - -> Option<TyParamBounds> { + fn fold_opt_bounds(&mut self, b: Option<GenericBounds>) -> Option<GenericBounds> { noop_fold_opt_bounds(b, self) } - fn fold_bounds(&mut self, b: TyParamBounds) - -> TyParamBounds { + fn fold_bounds(&mut self, b: GenericBounds) -> GenericBounds { noop_fold_bounds(b, self) } - fn fold_ty_param_bound(&mut self, tpb: TyParamBound) -> TyParamBound { - noop_fold_ty_param_bound(tpb, self) + fn fold_param_bound(&mut self, tpb: GenericBound) -> GenericBound { + noop_fold_param_bound(tpb, self) } fn fold_mt(&mut self, mt: MutTy) -> MutTy { @@ -385,10 +390,10 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { TyKind::Typeof(fld.fold_anon_const(expr)) } TyKind::TraitObject(bounds, syntax) => { - TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b)), syntax) + TyKind::TraitObject(bounds.move_map(|b| fld.fold_param_bound(b)), syntax) } TyKind::ImplTrait(bounds) => { - TyKind::ImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b))) + TyKind::ImplTrait(bounds.move_map(|b| fld.fold_param_bound(b))) } TyKind::Mac(mac) => { TyKind::Mac(fld.fold_mac(mac)) @@ -433,9 +438,9 @@ pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize { pub fn noop_fold_path<T: Folder>(Path { segments, span }: Path, fld: &mut T) -> Path { Path { - segments: segments.move_map(|PathSegment {ident, parameters}| PathSegment { + segments: segments.move_map(|PathSegment { ident, args }| PathSegment { ident: fld.fold_ident(ident), - parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))), + args: args.map(|args| args.map(|args| fld.fold_generic_args(args))), }), span: fld.new_span(span) } @@ -454,36 +459,40 @@ pub fn noop_fold_qpath<T: Folder>(qself: Option<QSelf>, (qself, fld.fold_path(path)) } -pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters, fld: &mut T) - -> PathParameters +pub fn noop_fold_generic_args<T: Folder>(generic_args: GenericArgs, fld: &mut T) -> GenericArgs { - match path_parameters { - PathParameters::AngleBracketed(data) => - PathParameters::AngleBracketed(fld.fold_angle_bracketed_parameter_data(data)), - PathParameters::Parenthesized(data) => - PathParameters::Parenthesized(fld.fold_parenthesized_parameter_data(data)), + match generic_args { + GenericArgs::AngleBracketed(data) => { + GenericArgs::AngleBracketed(fld.fold_angle_bracketed_parameter_data(data)) + } + GenericArgs::Parenthesized(data) => { + GenericArgs::Parenthesized(fld.fold_parenthesized_parameter_data(data)) + } } } -pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedParameterData, +pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedArgs, fld: &mut T) - -> AngleBracketedParameterData + -> AngleBracketedArgs { - let AngleBracketedParameterData { lifetimes, types, bindings, span } = data; - AngleBracketedParameterData { lifetimes: lifetimes.move_map(|l| noop_fold_lifetime(l, fld)), - types: types.move_map(|ty| fld.fold_ty(ty)), - bindings: bindings.move_map(|b| fld.fold_ty_binding(b)), - span: fld.new_span(span) } + let AngleBracketedArgs { args, bindings, span } = data; + AngleBracketedArgs { + args: args.move_map(|arg| fld.fold_generic_arg(arg)), + bindings: bindings.move_map(|b| fld.fold_ty_binding(b)), + span: fld.new_span(span) + } } -pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData, +pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesisedArgs, fld: &mut T) - -> ParenthesizedParameterData + -> ParenthesisedArgs { - let ParenthesizedParameterData { inputs, output, span } = data; - ParenthesizedParameterData { inputs: inputs.move_map(|ty| fld.fold_ty(ty)), - output: output.map(|ty| fld.fold_ty(ty)), - span: fld.new_span(span) } + let ParenthesisedArgs { inputs, output, span } = data; + ParenthesisedArgs { + inputs: inputs.move_map(|ty| fld.fold_ty(ty)), + output: output.map(|ty| fld.fold_ty(ty)), + span: fld.new_span(span) + } } pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> { @@ -667,47 +676,33 @@ pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> { }) } -pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T) - -> TyParamBound - where T: Folder { - match tpb { - TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier), - RegionTyParamBound(lifetime) => RegionTyParamBound(noop_fold_lifetime(lifetime, fld)), - } -} - -pub fn noop_fold_ty_param<T: Folder>(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::<Vec<_>>() - .into(), - id: fld.new_id(id), - ident: fld.fold_ident(ident), - bounds: fld.fold_bounds(bounds), - default: default.map(|x| fld.fold_ty(x)), +pub fn noop_fold_param_bound<T>(pb: GenericBound, fld: &mut T) -> GenericBound where T: Folder { + match pb { + GenericBound::Trait(ty, modifier) => { + GenericBound::Trait(fld.fold_poly_trait_ref(ty), modifier) + } + GenericBound::Outlives(lifetime) => { + GenericBound::Outlives(noop_fold_lifetime(lifetime, fld)) + } } } pub fn noop_fold_generic_param<T: Folder>(param: GenericParam, fld: &mut T) -> GenericParam { - match param { - GenericParam::Lifetime(l) => { - let attrs: Vec<_> = l.attrs.into(); - GenericParam::Lifetime(LifetimeDef { - attrs: attrs.into_iter() + let attrs: Vec<_> = param.attrs.into(); + GenericParam { + ident: fld.fold_ident(param.ident), + id: fld.new_id(param.id), + attrs: attrs.into_iter() .flat_map(|x| fld.fold_attribute(x).into_iter()) .collect::<Vec<_>>() .into(), - lifetime: Lifetime { - id: fld.new_id(l.lifetime.id), - ident: fld.fold_ident(l.lifetime.ident), - }, - bounds: l.bounds.move_map(|l| noop_fold_lifetime(l, fld)), - }) + bounds: param.bounds.move_map(|l| noop_fold_param_bound(l, fld)), + kind: match param.kind { + GenericParamKind::Lifetime => GenericParamKind::Lifetime, + GenericParamKind::Type { default } => GenericParamKind::Type { + default: default.map(|ty| fld.fold_ty(ty)) + } } - GenericParam::Type(t) => GenericParam::Type(fld.fold_ty_param(t)), } } @@ -765,7 +760,7 @@ pub fn noop_fold_where_predicate<T: Folder>( ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { bound_generic_params: fld.fold_generic_params(bound_generic_params), bounded_ty: fld.fold_ty(bounded_ty), - bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)), + bounds: bounds.move_map(|x| fld.fold_param_bound(x)), span: fld.new_span(span) }) } @@ -775,7 +770,7 @@ pub fn noop_fold_where_predicate<T: Folder>( ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { span: fld.new_span(span), lifetime: noop_fold_lifetime(lifetime, fld), - bounds: bounds.move_map(|bound| noop_fold_lifetime(bound, fld)) + bounds: bounds.move_map(|bound| noop_fold_param_bound(bound, fld)) }) } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, @@ -854,14 +849,14 @@ pub fn noop_fold_mt<T: Folder>(MutTy {ty, mutbl}: MutTy, folder: &mut T) -> MutT } } -pub fn noop_fold_opt_bounds<T: Folder>(b: Option<TyParamBounds>, folder: &mut T) - -> Option<TyParamBounds> { +pub fn noop_fold_opt_bounds<T: Folder>(b: Option<GenericBounds>, folder: &mut T) + -> Option<GenericBounds> { b.map(|bounds| folder.fold_bounds(bounds)) } -fn noop_fold_bounds<T: Folder>(bounds: TyParamBounds, folder: &mut T) - -> TyParamBounds { - bounds.move_map(|bound| folder.fold_ty_param_bound(bound)) +fn noop_fold_bounds<T: Folder>(bounds: GenericBounds, folder: &mut T) + -> GenericBounds { + bounds.move_map(|bound| folder.fold_param_bound(bound)) } pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> { @@ -1184,8 +1179,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu ExprKind::MethodCall( PathSegment { ident: folder.fold_ident(seg.ident), - parameters: seg.parameters.map(|ps| { - ps.map(|ps| folder.fold_path_parameters(ps)) + args: seg.args.map(|args| { + args.map(|args| folder.fold_generic_args(args)) }), }, folder.fold_exprs(args)) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1735951da2f..6f78ae9ebca 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -9,8 +9,8 @@ // except according to those terms. use rustc_target::spec::abi::{self, Abi}; -use ast::{AngleBracketedParameterData, ParenthesizedParameterData, AttrStyle, BareFnTy}; -use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; +use ast::{AngleBracketedArgs, ParenthesisedArgs, AttrStyle, BareFnTy}; +use ast::{GenericBound, TraitBoundModifier}; use ast::Unsafety; use ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind}; use ast::Block; @@ -21,9 +21,10 @@ use ast::EnumDef; use ast::{Expr, ExprKind, RangeLimits}; use ast::{Field, FnDecl}; use ast::{ForeignItem, ForeignItemKind, FunctionRetTy}; -use ast::GenericParam; +use ast::{GenericParam, GenericParamKind}; +use ast::GenericArg; use ast::{Ident, ImplItem, IsAuto, Item, ItemKind}; -use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind}; +use ast::{Label, Lifetime, Lit, LitKind}; use ast::Local; use ast::MacStmtStyle; use ast::{Mac, Mac_, MacDelimiter}; @@ -35,7 +36,7 @@ use ast::{VariantData, StructField}; use ast::StrStyle; use ast::SelfKind; use ast::{TraitItem, TraitRef, TraitObjectSyntax}; -use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds}; +use ast::{Ty, TyKind, TypeBinding, GenericBounds}; use ast::{Visibility, VisibilityKind, WhereClause, CrateSugar}; use ast::{UseTree, UseTreeKind}; use ast::{BinOpKind, UnOp}; @@ -1245,8 +1246,7 @@ impl<'a> Parser<'a> { } /// parse a TyKind::BareFn type: - fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) - -> PResult<'a, TyKind> { + fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> { /* [unsafe] [extern "ABI"] fn (S) -> T @@ -1311,9 +1311,7 @@ impl<'a> Parser<'a> { let lo = self.span; let (name, node, generics) = if self.eat_keyword(keywords::Type) { - let (generics, TyParam {ident, bounds, default, ..}) = - self.parse_trait_item_assoc_ty(vec![])?; - (ident, TraitItemKind::Type(bounds, default), generics) + self.parse_trait_item_assoc_ty()? } else if self.is_const_item() { self.expect_keyword(keywords::Const)?; let ident = self.parse_ident()?; @@ -1446,7 +1444,7 @@ impl<'a> Parser<'a> { TyKind::TraitObject(ref bounds, TraitObjectSyntax::None) if maybe_bounds && bounds.len() == 1 && !trailing_plus => { let path = match bounds[0] { - TraitTyParamBound(ref pt, ..) => pt.trait_ref.path.clone(), + GenericBound::Trait(ref pt, ..) => pt.trait_ref.path.clone(), _ => self.bug("unexpected lifetime bound"), }; self.parse_remaining_bounds(Vec::new(), path, lo, true)? @@ -1511,7 +1509,7 @@ impl<'a> Parser<'a> { } } else if self.eat_keyword(keywords::Impl) { // Always parse bounds greedily for better error recovery. - let bounds = self.parse_ty_param_bounds()?; + let bounds = self.parse_generic_bounds()?; impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; TyKind::ImplTrait(bounds) } else if self.check_keyword(keywords::Dyn) && @@ -1519,13 +1517,13 @@ impl<'a> Parser<'a> { !can_continue_type_after_non_fn_ident(t)) { self.bump(); // `dyn` // Always parse bounds greedily for better error recovery. - let bounds = self.parse_ty_param_bounds()?; + let bounds = self.parse_generic_bounds()?; impl_dyn_multi = bounds.len() > 1 || self.prev_token_kind == PrevTokenKind::Plus; TyKind::TraitObject(bounds, TraitObjectSyntax::Dyn) } else if self.check(&token::Question) || self.check_lifetime() && self.look_ahead(1, |t| t.is_like_plus()) { // Bound list (trait object type) - TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?, + TyKind::TraitObject(self.parse_generic_bounds_common(allow_plus)?, TraitObjectSyntax::None) } else if self.eat_lt() { // Qualified path @@ -1568,10 +1566,10 @@ impl<'a> Parser<'a> { fn parse_remaining_bounds(&mut self, generic_params: Vec<GenericParam>, path: ast::Path, lo: Span, parse_plus: bool) -> PResult<'a, TyKind> { let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span)); - let mut bounds = vec![TraitTyParamBound(poly_trait_ref, TraitBoundModifier::None)]; + let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)]; if parse_plus { self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded - bounds.append(&mut self.parse_ty_param_bounds()?); + bounds.append(&mut self.parse_generic_bounds()?); } Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) } @@ -1596,7 +1594,7 @@ impl<'a> Parser<'a> { } self.bump(); // `+` - let bounds = self.parse_ty_param_bounds()?; + let bounds = self.parse_generic_bounds()?; let sum_span = ty.span.to(self.prev_span); let mut err = struct_span_err!(self.sess.span_diagnostic, sum_span, E0178, @@ -1612,7 +1610,7 @@ impl<'a> Parser<'a> { s.print_mutability(mut_ty.mutbl)?; s.popen()?; s.print_type(&mut_ty.ty)?; - s.print_bounds(" +", &bounds)?; + s.print_type_bounds(" +", &bounds)?; s.pclose() }); err.span_suggestion_with_applicability( @@ -1894,7 +1892,7 @@ impl<'a> Parser<'a> { -> PResult<'a, ast::Path> { maybe_whole!(self, NtPath, |path| { if style == PathStyle::Mod && - path.segments.iter().any(|segment| segment.parameters.is_some()) { + path.segments.iter().any(|segment| segment.args.is_some()) { self.diagnostic().span_err(path.span, "unexpected generic arguments in path"); } path @@ -1969,12 +1967,12 @@ impl<'a> Parser<'a> { .span_label(self.prev_span, "try removing `::`").emit(); } - let parameters = if self.eat_lt() { + let args = if self.eat_lt() { // `<'a, T, A = U>` - let (lifetimes, types, bindings) = self.parse_generic_args()?; + let (args, bindings) = self.parse_generic_args()?; self.expect_gt()?; let span = lo.to(self.prev_span); - AngleBracketedParameterData { lifetimes, types, bindings, span }.into() + AngleBracketedArgs { args, bindings, span }.into() } else { // `(T, U) -> R` self.bump(); // `(` @@ -1990,10 +1988,10 @@ impl<'a> Parser<'a> { None }; let span = lo.to(self.prev_span); - ParenthesizedParameterData { inputs, output, span }.into() + ParenthesisedArgs { inputs, output, span }.into() }; - PathSegment { ident, parameters } + PathSegment { ident, args } } else { // Generic arguments are not found. PathSegment::from_ident(ident) @@ -2543,8 +2541,8 @@ impl<'a> Parser<'a> { } _ => { // Field access `expr.f` - if let Some(parameters) = segment.parameters { - self.span_err(parameters.span(), + if let Some(args) = segment.args { + self.span_err(args.span(), "field expressions may not have generic arguments"); } @@ -4737,7 +4735,7 @@ impl<'a> Parser<'a> { // LT_BOUND = LIFETIME (e.g. `'a`) // TY_BOUND = TY_BOUND_NOPAREN | (TY_BOUND_NOPAREN) // TY_BOUND_NOPAREN = [?] [for<LT_PARAM_DEFS>] SIMPLE_PATH (e.g. `?for<'a: 'b> m::Trait<'a>`) - fn parse_ty_param_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, TyParamBounds> { + fn parse_generic_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, GenericBounds> { let mut bounds = Vec::new(); loop { // This needs to be syncronized with `Token::can_begin_bound`. @@ -4754,7 +4752,7 @@ impl<'a> Parser<'a> { self.span_err(question_span, "`?` may only modify trait bounds, not lifetime bounds"); } - bounds.push(RegionTyParamBound(self.expect_lifetime())); + bounds.push(GenericBound::Outlives(self.expect_lifetime())); if has_parens { self.expect(&token::CloseDelim(token::Paren))?; self.span_err(self.prev_span, @@ -4772,7 +4770,7 @@ impl<'a> Parser<'a> { } else { TraitBoundModifier::None }; - bounds.push(TraitTyParamBound(poly_trait, modifier)); + bounds.push(GenericBound::Trait(poly_trait, modifier)); } } else { break @@ -4786,16 +4784,16 @@ impl<'a> Parser<'a> { return Ok(bounds); } - fn parse_ty_param_bounds(&mut self) -> PResult<'a, TyParamBounds> { - self.parse_ty_param_bounds_common(true) + fn parse_generic_bounds(&mut self) -> PResult<'a, GenericBounds> { + self.parse_generic_bounds_common(true) } // Parse bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. // BOUND = LT_BOUND (e.g. `'a`) - fn parse_lt_param_bounds(&mut self) -> Vec<Lifetime> { + fn parse_lt_param_bounds(&mut self) -> GenericBounds { let mut lifetimes = Vec::new(); while self.check_lifetime() { - lifetimes.push(self.expect_lifetime()); + lifetimes.push(ast::GenericBound::Outlives(self.expect_lifetime())); if !self.eat_plus() { break @@ -4805,12 +4803,14 @@ impl<'a> Parser<'a> { } /// Matches typaram = IDENT (`?` unbound)? optbounds ( EQ ty )? - fn parse_ty_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, TyParam> { + fn parse_ty_param(&mut self, + preceding_attrs: Vec<Attribute>) + -> PResult<'a, GenericParam> { let ident = self.parse_ident()?; // Parse optional colon and param bounds. let bounds = if self.eat(&token::Colon) { - self.parse_ty_param_bounds()? + self.parse_generic_bounds()? } else { Vec::new() }; @@ -4821,25 +4821,27 @@ impl<'a> Parser<'a> { None }; - Ok(TyParam { - attrs: preceding_attrs.into(), + Ok(GenericParam { ident, id: ast::DUMMY_NODE_ID, + attrs: preceding_attrs.into(), bounds, - default, + kind: GenericParamKind::Type { + default, + } }) } /// Parses the following grammar: - /// TraitItemAssocTy = Ident ["<"...">"] [":" [TyParamBounds]] ["where" ...] ["=" Ty] - fn parse_trait_item_assoc_ty(&mut self, preceding_attrs: Vec<Attribute>) - -> PResult<'a, (ast::Generics, TyParam)> { + /// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] + fn parse_trait_item_assoc_ty(&mut self) + -> PResult<'a, (Ident, TraitItemKind, ast::Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; // Parse optional colon and param bounds. let bounds = if self.eat(&token::Colon) { - self.parse_ty_param_bounds()? + self.parse_generic_bounds()? } else { Vec::new() }; @@ -4852,13 +4854,7 @@ impl<'a> Parser<'a> { }; self.expect(&token::Semi)?; - Ok((generics, TyParam { - attrs: preceding_attrs.into(), - ident, - id: ast::DUMMY_NODE_ID, - bounds, - default, - })) + Ok((ident, TraitItemKind::Type(bounds, default), generics)) } /// Parses (possibly empty) list of lifetime and type parameters, possibly including @@ -4876,18 +4872,20 @@ impl<'a> Parser<'a> { } else { Vec::new() }; - params.push(ast::GenericParam::Lifetime(LifetimeDef { + params.push(ast::GenericParam { + ident: lifetime.ident, + id: lifetime.id, attrs: attrs.into(), - lifetime, bounds, - })); + kind: ast::GenericParamKind::Lifetime, + }); if seen_ty_param { self.span_err(self.prev_span, "lifetime parameters must be declared prior to type parameters"); } } else if self.check_ident() { // Parse type parameter. - params.push(ast::GenericParam::Type(self.parse_ty_param(attrs)?)); + params.push(self.parse_ty_param(attrs)?); seen_ty_param = true; } else { // Check for trailing attributes and stop parsing. @@ -4936,16 +4934,16 @@ impl<'a> Parser<'a> { /// Parses (possibly empty) list of lifetime and type arguments and associated type bindings, /// possibly including trailing comma. - fn parse_generic_args(&mut self) -> PResult<'a, (Vec<Lifetime>, Vec<P<Ty>>, Vec<TypeBinding>)> { - let mut lifetimes = Vec::new(); - let mut types = Vec::new(); + fn parse_generic_args(&mut self) + -> PResult<'a, (Vec<GenericArg>, Vec<TypeBinding>)> { + let mut args = Vec::new(); let mut bindings = Vec::new(); let mut seen_type = false; let mut seen_binding = false; loop { if self.check_lifetime() && self.look_ahead(1, |t| !t.is_like_plus()) { // Parse lifetime argument. - lifetimes.push(self.expect_lifetime()); + args.push(GenericArg::Lifetime(self.expect_lifetime())); if seen_type || seen_binding { self.span_err(self.prev_span, "lifetime parameters must be declared prior to type parameters"); @@ -4965,11 +4963,12 @@ impl<'a> Parser<'a> { seen_binding = true; } else if self.check_type() { // Parse type argument. - types.push(self.parse_ty()?); + let ty_param = self.parse_ty()?; if seen_binding { - self.span_err(types[types.len() - 1].span, + self.span_err(ty_param.span, "type parameters must be declared prior to associated type bindings"); } + args.push(GenericArg::Type(ty_param)); seen_type = true; } else { break @@ -4979,7 +4978,7 @@ impl<'a> Parser<'a> { break } } - Ok((lifetimes, types, bindings)) + Ok((args, bindings)) } /// Parses an optional `where` clause and places it in `generics`. @@ -5037,7 +5036,7 @@ impl<'a> Parser<'a> { // or with mandatory equality sign and the second type. let ty = self.parse_ty()?; if self.eat(&token::Colon) { - let bounds = self.parse_ty_param_bounds()?; + let bounds = self.parse_generic_bounds()?; where_clause.predicates.push(ast::WherePredicate::BoundPredicate( ast::WhereBoundPredicate { span: lo.to(self.prev_span), @@ -5537,14 +5536,14 @@ impl<'a> Parser<'a> { // Parse optional colon and supertrait bounds. let bounds = if self.eat(&token::Colon) { - self.parse_ty_param_bounds()? + self.parse_generic_bounds()? } else { Vec::new() }; if self.eat(&token::Eq) { // it's a trait alias - let bounds = self.parse_ty_param_bounds()?; + let bounds = self.parse_generic_bounds()?; tps.where_clause = self.parse_where_clause()?; self.expect(&token::Semi)?; if unsafety != Unsafety::Normal { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 87edfd69e2b..7a55919f422 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -12,8 +12,8 @@ pub use self::AnnNode::*; use rustc_target::spec::abi::{self, Abi}; use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}; -use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier}; -use ast::{Attribute, MacDelimiter}; +use ast::{SelfKind, GenericBound, TraitBoundModifier}; +use ast::{Attribute, MacDelimiter, GenericArg}; use util::parser::{self, AssocOp, Fixity}; use attr; use codemap::{self, CodeMap}; @@ -292,8 +292,8 @@ pub fn ty_to_string(ty: &ast::Ty) -> String { to_string(|s| s.print_type(ty)) } -pub fn bounds_to_string(bounds: &[ast::TyParamBound]) -> String { - to_string(|s| s.print_bounds("", bounds)) +pub fn bounds_to_string(bounds: &[ast::GenericBound]) -> String { + to_string(|s| s.print_type_bounds("", bounds)) } pub fn pat_to_string(pat: &ast::Pat) -> String { @@ -308,8 +308,8 @@ pub fn expr_to_string(e: &ast::Expr) -> String { to_string(|s| s.print_expr(e)) } -pub fn lifetime_to_string(e: &ast::Lifetime) -> String { - to_string(|s| s.print_lifetime(e)) +pub fn lifetime_to_string(lt: &ast::Lifetime) -> String { + to_string(|s| s.print_lifetime(*lt)) } pub fn tt_to_string(tt: tokenstream::TokenTree) -> String { @@ -1008,15 +1008,21 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_opt_lifetime(&mut self, - lifetime: &Option<ast::Lifetime>) -> io::Result<()> { - if let Some(l) = *lifetime { - self.print_lifetime(&l)?; + pub fn print_opt_lifetime(&mut self, lifetime: &Option<ast::Lifetime>) -> io::Result<()> { + if let Some(lt) = *lifetime { + self.print_lifetime(lt)?; self.nbsp()?; } Ok(()) } + pub fn print_generic_arg(&mut self, generic_arg: &GenericArg) -> io::Result<()> { + match generic_arg { + GenericArg::Lifetime(lt) => self.print_lifetime(*lt), + GenericArg::Type(ty) => self.print_type(ty), + } + } + pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> { self.maybe_print_comment(ty.span.lo())?; self.ibox(0)?; @@ -1071,10 +1077,10 @@ impl<'a> State<'a> { } ast::TyKind::TraitObject(ref bounds, syntax) => { let prefix = if syntax == ast::TraitObjectSyntax::Dyn { "dyn" } else { "" }; - self.print_bounds(prefix, &bounds[..])?; + self.print_type_bounds(prefix, &bounds[..])?; } ast::TyKind::ImplTrait(ref bounds) => { - self.print_bounds("impl", &bounds[..])?; + self.print_type_bounds("impl", &bounds[..])?; } ast::TyKind::Array(ref ty, ref length) => { self.s.word("[")?; @@ -1171,13 +1177,13 @@ impl<'a> State<'a> { fn print_associated_type(&mut self, ident: ast::Ident, - bounds: Option<&ast::TyParamBounds>, + bounds: Option<&ast::GenericBounds>, ty: Option<&ast::Ty>) -> io::Result<()> { self.word_space("type")?; self.print_ident(ident)?; if let Some(bounds) = bounds { - self.print_bounds(":", bounds)?; + self.print_type_bounds(":", bounds)?; } if let Some(ty) = ty { self.s.space()?; @@ -1322,7 +1328,7 @@ impl<'a> State<'a> { self.print_unsafety(unsafety)?; self.word_nbsp("impl")?; - if generics.is_parameterized() { + if !generics.params.is_empty() { self.print_generic_params(&generics.params)?; self.s.space()?; } @@ -1358,7 +1364,7 @@ impl<'a> State<'a> { self.print_generic_params(&generics.params)?; let mut real_bounds = Vec::with_capacity(bounds.len()); for b in bounds.iter() { - if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b { + if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b { self.s.space()?; self.word_space("for ?")?; self.print_trait_ref(&ptr.trait_ref)?; @@ -1366,7 +1372,7 @@ impl<'a> State<'a> { real_bounds.push(b.clone()); } } - self.print_bounds(":", &real_bounds[..])?; + self.print_type_bounds(":", &real_bounds[..])?; self.print_where_clause(&generics.where_clause)?; self.s.word(" ")?; self.bopen()?; @@ -1384,7 +1390,7 @@ impl<'a> State<'a> { let mut real_bounds = Vec::with_capacity(bounds.len()); // FIXME(durka) this seems to be some quite outdated syntax for b in bounds.iter() { - if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b { + if let GenericBound::Trait(ref ptr, ast::TraitBoundModifier::Maybe) = *b { self.s.space()?; self.word_space("for ?")?; self.print_trait_ref(&ptr.trait_ref)?; @@ -1393,7 +1399,7 @@ impl<'a> State<'a> { } } self.nbsp()?; - self.print_bounds("=", &real_bounds[..])?; + self.print_type_bounds("=", &real_bounds[..])?; self.print_where_clause(&generics.where_clause)?; self.s.word(";")?; } @@ -1984,8 +1990,8 @@ impl<'a> State<'a> { self.print_expr_maybe_paren(&args[0], parser::PREC_POSTFIX)?; self.s.word(".")?; self.print_ident(segment.ident)?; - if let Some(ref parameters) = segment.parameters { - self.print_path_parameters(parameters, true)?; + if let Some(ref args) = segment.args { + self.print_generic_args(args, true)?; } self.print_call_post(base_args) } @@ -2428,8 +2434,8 @@ impl<'a> State<'a> { if segment.ident.name != keywords::CrateRoot.name() && segment.ident.name != keywords::DollarCrate.name() { self.print_ident(segment.ident)?; - if let Some(ref parameters) = segment.parameters { - self.print_path_parameters(parameters, colons_before_params)?; + if let Some(ref args) = segment.args { + self.print_generic_args(args, colons_before_params)?; } } else if segment.ident.name == keywords::DollarCrate.name() { self.print_dollar_crate(segment.ident.span.ctxt())?; @@ -2455,44 +2461,30 @@ impl<'a> State<'a> { self.s.word("::")?; let item_segment = path.segments.last().unwrap(); self.print_ident(item_segment.ident)?; - match item_segment.parameters { - Some(ref parameters) => self.print_path_parameters(parameters, colons_before_params), + match item_segment.args { + Some(ref args) => self.print_generic_args(args, colons_before_params), None => Ok(()), } } - fn print_path_parameters(&mut self, - parameters: &ast::PathParameters, - colons_before_params: bool) - -> io::Result<()> + fn print_generic_args(&mut self, + args: &ast::GenericArgs, + colons_before_params: bool) + -> io::Result<()> { if colons_before_params { self.s.word("::")? } - match *parameters { - ast::PathParameters::AngleBracketed(ref data) => { + match *args { + ast::GenericArgs::AngleBracketed(ref data) => { self.s.word("<")?; - let mut comma = false; - for lifetime in &data.lifetimes { - if comma { - self.word_space(",")? - } - self.print_lifetime(lifetime)?; - comma = true; - } + self.commasep(Inconsistent, &data.args, |s, generic_arg| { + s.print_generic_arg(generic_arg) + })?; - if !data.types.is_empty() { - if comma { - self.word_space(",")? - } - self.commasep( - Inconsistent, - &data.types, - |s, ty| s.print_type(ty))?; - comma = true; - } + let mut comma = data.args.len() != 0; for binding in data.bindings.iter() { if comma { @@ -2508,7 +2500,7 @@ impl<'a> State<'a> { self.s.word(">")? } - ast::PathParameters::Parenthesized(ref data) => { + ast::GenericArgs::Parenthesized(ref data) => { self.s.word("(")?; self.commasep( Inconsistent, @@ -2816,9 +2808,9 @@ impl<'a> State<'a> { } } - pub fn print_bounds(&mut self, + pub fn print_type_bounds(&mut self, prefix: &str, - bounds: &[ast::TyParamBound]) + bounds: &[ast::GenericBound]) -> io::Result<()> { if !bounds.is_empty() { self.s.word(prefix)?; @@ -2834,32 +2826,25 @@ impl<'a> State<'a> { } match bound { - TraitTyParamBound(tref, modifier) => { + GenericBound::Trait(tref, modifier) => { if modifier == &TraitBoundModifier::Maybe { self.s.word("?")?; } self.print_poly_trait_ref(tref)?; } - RegionTyParamBound(lt) => { - self.print_lifetime(lt)?; - } + GenericBound::Outlives(lt) => self.print_lifetime(*lt)?, } } } Ok(()) } - pub fn print_lifetime(&mut self, - lifetime: &ast::Lifetime) - -> io::Result<()> - { + pub fn print_lifetime(&mut self, lifetime: ast::Lifetime) -> io::Result<()> { self.print_name(lifetime.ident.name) } - pub fn print_lifetime_bounds(&mut self, - lifetime: &ast::Lifetime, - bounds: &[ast::Lifetime]) - -> io::Result<()> + pub fn print_lifetime_bounds(&mut self, lifetime: ast::Lifetime, bounds: &ast::GenericBounds) + -> io::Result<()> { self.print_lifetime(lifetime)?; if !bounds.is_empty() { @@ -2868,7 +2853,10 @@ impl<'a> State<'a> { if i != 0 { self.s.word(" + ")?; } - self.print_lifetime(bound)?; + match bound { + ast::GenericBound::Outlives(lt) => self.print_lifetime(*lt)?, + _ => panic!(), + } } } Ok(()) @@ -2885,12 +2873,25 @@ impl<'a> State<'a> { self.s.word("<")?; self.commasep(Inconsistent, &generic_params, |s, param| { - match *param { - ast::GenericParam::Lifetime(ref lifetime_def) => { - s.print_outer_attributes_inline(&lifetime_def.attrs)?; - s.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds) + match param.kind { + ast::GenericParamKind::Lifetime => { + s.print_outer_attributes_inline(¶m.attrs)?; + let lt = ast::Lifetime { id: param.id, ident: param.ident }; + s.print_lifetime_bounds(lt, ¶m.bounds) }, - ast::GenericParam::Type(ref ty_param) => s.print_ty_param(ty_param), + ast::GenericParamKind::Type { ref default } => { + s.print_outer_attributes_inline(¶m.attrs)?; + s.print_ident(param.ident)?; + s.print_type_bounds(":", ¶m.bounds)?; + match default { + Some(ref default) => { + s.s.space()?; + s.word_space("=")?; + s.print_type(default) + } + _ => Ok(()) + } + } } })?; @@ -2898,20 +2899,6 @@ impl<'a> State<'a> { Ok(()) } - pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> { - self.print_outer_attributes_inline(¶m.attrs)?; - self.print_ident(param.ident)?; - self.print_bounds(":", ¶m.bounds)?; - match param.default { - Some(ref default) => { - self.s.space()?; - self.word_space("=")?; - self.print_type(default) - } - _ => Ok(()) - } - } - pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause) -> io::Result<()> { if where_clause.predicates.is_empty() { @@ -2935,12 +2922,12 @@ impl<'a> State<'a> { }) => { self.print_formal_generic_params(bound_generic_params)?; self.print_type(bounded_ty)?; - self.print_bounds(":", bounds)?; + self.print_type_bounds(":", bounds)?; } ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, ref bounds, ..}) => { - self.print_lifetime_bounds(lifetime, bounds)?; + self.print_lifetime_bounds(*lifetime, bounds)?; } ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref lhs_ty, ref rhs_ty, diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index da7deb3c4cf..f896fa351b0 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -353,7 +353,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { match (has_output, has_should_panic_attr) { (true, true) => No(BadTestSignature::ShouldPanicOnlyWithNoArgs), - (true, false) => if generics.is_parameterized() { + (true, false) => if !generics.params.is_empty() { No(BadTestSignature::WrongTypeSignature) } else { Yes diff --git a/src/libsyntax/util/node_count.rs b/src/libsyntax/util/node_count.rs index d4c6b4b158b..ebb3081c1fd 100644 --- a/src/libsyntax/util/node_count.rs +++ b/src/libsyntax/util/node_count.rs @@ -95,9 +95,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_trait_ref(self, t) } - fn visit_ty_param_bound(&mut self, bounds: &TyParamBound) { + fn visit_param_bound(&mut self, bounds: &GenericBound) { self.count += 1; - walk_ty_param_bound(self, bounds) + walk_param_bound(self, bounds) } fn visit_poly_trait_ref(&mut self, t: &PolyTraitRef, m: &TraitBoundModifier) { self.count += 1; @@ -137,9 +137,9 @@ impl<'ast> Visitor<'ast> for NodeCounter { self.count += 1; walk_use_tree(self, use_tree, id) } - fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &PathParameters) { + fn visit_generic_args(&mut self, path_span: Span, generic_args: &GenericArgs) { self.count += 1; - walk_path_parameters(self, path_span, path_parameters) + walk_generic_args(self, path_span, generic_args) } fn visit_assoc_type_binding(&mut self, type_binding: &TypeBinding) { self.count += 1; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index adda39c62ed..613f1a4f113 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -73,7 +73,9 @@ pub trait Visitor<'ast>: Sized { fn visit_expr(&mut self, ex: &'ast Expr) { walk_expr(self, ex) } fn visit_expr_post(&mut self, _ex: &'ast Expr) { } fn visit_ty(&mut self, t: &'ast Ty) { walk_ty(self, t) } - fn visit_generic_param(&mut self, param: &'ast GenericParam) { walk_generic_param(self, param) } + fn visit_generic_param(&mut self, param: &'ast GenericParam) { + walk_generic_param(self, param) + } fn visit_generics(&mut self, g: &'ast Generics) { walk_generics(self, g) } fn visit_where_predicate(&mut self, p: &'ast WherePredicate) { walk_where_predicate(self, p) @@ -84,8 +86,8 @@ pub trait Visitor<'ast>: Sized { fn visit_trait_item(&mut self, ti: &'ast TraitItem) { walk_trait_item(self, ti) } fn visit_impl_item(&mut self, ii: &'ast ImplItem) { walk_impl_item(self, ii) } fn visit_trait_ref(&mut self, t: &'ast TraitRef) { walk_trait_ref(self, t) } - fn visit_ty_param_bound(&mut self, bounds: &'ast TyParamBound) { - walk_ty_param_bound(self, bounds) + fn visit_param_bound(&mut self, bounds: &'ast GenericBound) { + walk_param_bound(self, bounds) } fn visit_poly_trait_ref(&mut self, t: &'ast PolyTraitRef, m: &'ast TraitBoundModifier) { walk_poly_trait_ref(self, t, m) @@ -128,8 +130,14 @@ pub trait Visitor<'ast>: Sized { fn visit_path_segment(&mut self, path_span: Span, path_segment: &'ast PathSegment) { walk_path_segment(self, path_span, path_segment) } - fn visit_path_parameters(&mut self, path_span: Span, path_parameters: &'ast PathParameters) { - walk_path_parameters(self, path_span, path_parameters) + fn visit_generic_args(&mut self, path_span: Span, generic_args: &'ast GenericArgs) { + walk_generic_args(self, path_span, generic_args) + } + fn visit_generic_arg(&mut self, generic_arg: &'ast GenericArg) { + match generic_arg { + GenericArg::Lifetime(lt) => self.visit_lifetime(lt), + GenericArg::Type(ty) => self.visit_ty(ty), + } } fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) { walk_assoc_type_binding(self, type_binding) @@ -268,12 +276,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { } ItemKind::Trait(.., ref generics, ref bounds, ref methods) => { visitor.visit_generics(generics); - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_trait_item, methods); } ItemKind::TraitAlias(ref generics, ref bounds) => { visitor.visit_generics(generics); - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); } ItemKind::Mac(ref mac) => visitor.visit_mac(mac), ItemKind::MacroDef(ref ts) => visitor.visit_mac_def(ts, item.id), @@ -333,7 +341,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) { } TyKind::TraitObject(ref bounds, ..) | TyKind::ImplTrait(ref bounds) => { - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); } TyKind::Typeof(ref expression) => { visitor.visit_anon_const(expression) @@ -375,23 +383,22 @@ pub fn walk_path_segment<'a, V: Visitor<'a>>(visitor: &mut V, path_span: Span, segment: &'a PathSegment) { visitor.visit_ident(segment.ident); - if let Some(ref parameters) = segment.parameters { - visitor.visit_path_parameters(path_span, parameters); + if let Some(ref args) = segment.args { + visitor.visit_generic_args(path_span, args); } } -pub fn walk_path_parameters<'a, V>(visitor: &mut V, - _path_span: Span, - path_parameters: &'a PathParameters) +pub fn walk_generic_args<'a, V>(visitor: &mut V, + _path_span: Span, + generic_args: &'a GenericArgs) where V: Visitor<'a>, { - match *path_parameters { - PathParameters::AngleBracketed(ref data) => { - walk_list!(visitor, visit_ty, &data.types); - walk_list!(visitor, visit_lifetime, &data.lifetimes); + match *generic_args { + GenericArgs::AngleBracketed(ref data) => { + walk_list!(visitor, visit_generic_arg, &data.args); walk_list!(visitor, visit_assoc_type_binding, &data.bindings); } - PathParameters::Parenthesized(ref data) => { + GenericArgs::Parenthesized(ref data) => { walk_list!(visitor, visit_ty, &data.inputs); walk_list!(visitor, visit_ty, &data.output); } @@ -472,30 +479,20 @@ pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) { // Empty! } -pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyParamBound) { +pub fn walk_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a GenericBound) { match *bound { - TraitTyParamBound(ref typ, ref modifier) => { - visitor.visit_poly_trait_ref(typ, modifier); - } - RegionTyParamBound(ref lifetime) => { - visitor.visit_lifetime(lifetime); - } + GenericBound::Trait(ref typ, ref modifier) => visitor.visit_poly_trait_ref(typ, modifier), + GenericBound::Outlives(ref lifetime) => visitor.visit_lifetime(lifetime), } } pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) { - match *param { - GenericParam::Lifetime(ref l) => { - visitor.visit_ident(l.lifetime.ident); - walk_list!(visitor, visit_lifetime, &l.bounds); - walk_list!(visitor, visit_attribute, &*l.attrs); - } - GenericParam::Type(ref t) => { - visitor.visit_ident(t.ident); - walk_list!(visitor, visit_ty_param_bound, &t.bounds); - walk_list!(visitor, visit_ty, &t.default); - walk_list!(visitor, visit_attribute, &*t.attrs); - } + visitor.visit_ident(param.ident); + walk_list!(visitor, visit_attribute, param.attrs.iter()); + walk_list!(visitor, visit_param_bound, ¶m.bounds); + match param.kind { + GenericParamKind::Lifetime => {} + GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default), } } @@ -511,14 +508,14 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a ref bound_generic_params, ..}) => { visitor.visit_ty(bounded_ty); - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_generic_param, bound_generic_params); } WherePredicate::RegionPredicate(WhereRegionPredicate{ref lifetime, ref bounds, ..}) => { visitor.visit_lifetime(lifetime); - walk_list!(visitor, visit_lifetime, bounds); + walk_list!(visitor, visit_param_bound, bounds); } WherePredicate::EqPredicate(WhereEqPredicate{ref lhs_ty, ref rhs_ty, @@ -579,7 +576,7 @@ pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, trait_item: &'a Trai &sig.decl, trait_item.span, trait_item.id); } TraitItemKind::Type(ref bounds, ref default) => { - walk_list!(visitor, visit_ty_param_bound, bounds); + walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, default); } TraitItemKind::Macro(ref mac) => { |
