diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2014-11-06 13:31:18 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2014-11-06 13:31:18 -0800 |
| commit | 76d2abe0e7fb33ed41137a0c99fbbc2905d8ca91 (patch) | |
| tree | 1ea979f4b18b619db872eded0bbdb7971e6cc379 /src/libsyntax | |
| parent | 08ddfc10e4170ac5f4522a71c0d1aea8cf799f29 (diff) | |
| parent | d0fa4c6239accc08aae11d9db3e13d4153add432 (diff) | |
| download | rust-76d2abe0e7fb33ed41137a0c99fbbc2905d8ca91.tar.gz rust-76d2abe0e7fb33ed41137a0c99fbbc2905d8ca91.zip | |
rollup merge of #18630 : nikomatsakis/purge-the-bars
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 113 | ||||
| -rw-r--r-- | src/libsyntax/ast_map/mod.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/ast_util.rs | 18 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 9 | ||||
| -rw-r--r-- | src/libsyntax/ext/concat_idents.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 73 | ||||
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 24 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 266 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 112 | ||||
| -rw-r--r-- | src/libsyntax/std_inject.rs | 7 | ||||
| -rw-r--r-- | src/libsyntax/test.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 35 |
13 files changed, 391 insertions, 281 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 078e393eb28..6a354fa20e1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -171,7 +171,7 @@ pub struct Path { /// module (like paths in an import). pub global: bool, /// The segments in the path: the things separated by `::`. - pub segments: Vec<PathSegment> , + pub segments: Vec<PathSegment>, } /// A segment of a path: an identifier, an optional lifetime, and a set of @@ -180,12 +180,107 @@ pub struct Path { pub struct PathSegment { /// The identifier portion of this path segment. pub identifier: Ident, + + /// Type/lifetime parameters attached to this path. They come in + /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that + /// this is more than just simple syntactic sugar; the use of + /// parens affects the region binding rules, so we preserve the + /// distinction. + pub parameters: PathParameters, +} + +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub enum PathParameters { + AngleBracketedParameters(AngleBracketedParameterData), + ParenthesizedParameters(ParenthesizedParameterData), +} + +impl PathParameters { + pub fn none() -> PathParameters { + AngleBracketedParameters(AngleBracketedParameterData { + lifetimes: Vec::new(), + types: OwnedSlice::empty(), + }) + } + + pub fn is_empty(&self) -> bool { + match *self { + AngleBracketedParameters(ref data) => data.is_empty(), + + // Even if the user supplied no types, something like + // `X()` is equivalent to `X<(),()>`. + ParenthesizedParameters(..) => false, + } + } + + pub fn has_lifetimes(&self) -> bool { + match *self { + AngleBracketedParameters(ref data) => !data.lifetimes.is_empty(), + ParenthesizedParameters(_) => false, + } + } + + pub fn has_types(&self) -> bool { + match *self { + AngleBracketedParameters(ref data) => !data.types.is_empty(), + ParenthesizedParameters(..) => true, + } + } + + pub fn types(&self) -> Vec<&P<Ty>> { + /*! + * Returns the types that the user wrote. Note that these do not + * necessarily map to the type parameters in the parenthesized case. + */ + match *self { + AngleBracketedParameters(ref data) => { + data.types.iter().collect() + } + ParenthesizedParameters(ref data) => { + data.inputs.iter() + .chain(data.output.iter()) + .collect() + } + } + } + + pub fn lifetimes(&self) -> Vec<&Lifetime> { + match *self { + AngleBracketedParameters(ref data) => { + data.lifetimes.iter().collect() + } + ParenthesizedParameters(_) => { + Vec::new() + } + } + } +} + +/// A path like `Foo<'a, T>` +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub struct AngleBracketedParameterData { /// The lifetime parameters for this path segment. pub lifetimes: Vec<Lifetime>, /// The type parameters for this path segment, if present. pub types: OwnedSlice<P<Ty>>, } +impl AngleBracketedParameterData { + fn is_empty(&self) -> bool { + self.lifetimes.is_empty() && self.types.is_empty() + } +} + +/// A path like `Foo(A,B) -> C` +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +pub struct ParenthesizedParameterData { + /// `(A,B)` + pub inputs: Vec<P<Ty>>, + + /// `C` + pub output: Option<P<Ty>>, +} + pub type CrateNum = u32; pub type NodeId = u32; @@ -213,21 +308,12 @@ pub const DUMMY_NODE_ID: NodeId = -1; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum TyParamBound { TraitTyParamBound(TraitRef), - UnboxedFnTyParamBound(P<UnboxedFnBound>), RegionTyParamBound(Lifetime) } pub type TyParamBounds = OwnedSlice<TyParamBound>; #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] -pub struct UnboxedFnBound { - pub path: Path, - pub decl: P<FnDecl>, - pub lifetimes: Vec<LifetimeDef>, - pub ref_id: NodeId, -} - -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub struct TyParam { pub ident: Ident, pub id: NodeId, @@ -995,12 +1081,6 @@ pub struct BareFnTy { } #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] -pub struct UnboxedFnTy { - pub kind: UnboxedClosureKind, - pub decl: P<FnDecl>, -} - -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] pub enum Ty_ { TyNil, TyBot, /* bottom type */ @@ -1012,7 +1092,6 @@ pub enum Ty_ { TyClosure(P<ClosureTy>), TyProc(P<ClosureTy>), TyBareFn(P<BareFnTy>), - TyUnboxedFn(P<UnboxedFnTy>), TyTup(Vec<P<Ty>> ), TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType` diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index f049b964ff3..3adb062864e 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -848,9 +848,6 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { TyBareFn(ref fd) => { self.visit_fn_decl(&*fd.decl); } - TyUnboxedFn(ref fd) => { - self.visit_fn_decl(&*fd.decl); - } _ => {} } visit::walk_ty(self, ty); diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 3aa60236d70..2e3a15bfd4b 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -171,8 +171,10 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path { segments: vec!( ast::PathSegment { identifier: identifier, - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { + lifetimes: Vec::new(), + types: OwnedSlice::empty(), + }) } ), } @@ -681,11 +683,11 @@ pub fn segments_name_eq(a : &[ast::PathSegment], b : &[ast::PathSegment]) -> boo false } else { for (idx,seg) in a.iter().enumerate() { - if (seg.identifier.name != b[idx].identifier.name) + if seg.identifier.name != b[idx].identifier.name // FIXME #7743: ident -> name problems in lifetime comparison? - || (seg.lifetimes != b[idx].lifetimes) // can types contain idents? - || (seg.types != b[idx].types) { + || seg.parameters != b[idx].parameters + { return false; } } @@ -747,12 +749,10 @@ impl PostExpansionMethod for Method { mod test { use ast::*; use super::*; - use owned_slice::OwnedSlice; fn ident_to_segment(id : &Ident) -> PathSegment { - PathSegment {identifier:id.clone(), - lifetimes: Vec::new(), - types: OwnedSlice::empty()} + PathSegment {identifier: id.clone(), + parameters: PathParameters::none()} } #[test] fn idents_name_eq_test() { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index dc4eaf7d7ad..5921d630b89 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -313,14 +313,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> { .map(|ident| { ast::PathSegment { identifier: ident, - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), } }).collect(); segments.push(ast::PathSegment { identifier: last_identifier, - lifetimes: lifetimes, - types: OwnedSlice::from_vec(types), + parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { + lifetimes: lifetimes, + types: OwnedSlice::from_vec(types), + }) }); ast::Path { span: sp, diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index e5e93a7d8b3..aa18b1be31a 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -12,7 +12,6 @@ use ast; use codemap::Span; use ext::base::*; use ext::base; -use owned_slice::OwnedSlice; use parse::token; use parse::token::{str_to_ident}; use ptr::P; @@ -52,8 +51,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree] segments: vec!( ast::PathSegment { identifier: res, - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), } ) } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 7701f495f72..80b158a54d3 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -313,11 +313,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { experimental and likely to be removed"); }, - ast::TyUnboxedFn(..) => { - self.gate_feature("unboxed_closure_sugar", - t.span, - "unboxed closure trait sugar is experimental"); - } _ => {} } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 6535c8e89fd..cd4a3d10c48 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -166,6 +166,22 @@ pub trait Folder { noop_fold_path(p, self) } + fn fold_path_parameters(&mut self, p: PathParameters) -> PathParameters { + noop_fold_path_parameters(p, self) + } + + fn fold_angle_bracketed_parameter_data(&mut self, p: AngleBracketedParameterData) + -> AngleBracketedParameterData + { + noop_fold_angle_bracketed_parameter_data(p, self) + } + + fn fold_parenthesized_parameter_data(&mut self, p: ParenthesizedParameterData) + -> ParenthesizedParameterData + { + noop_fold_parenthesized_parameter_data(p, self) + } + fn fold_local(&mut self, l: P<Local>) -> P<Local> { noop_fold_local(l, self) } @@ -408,12 +424,6 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { decl: fld.fold_fn_decl(decl) })) } - TyUnboxedFn(f) => { - TyUnboxedFn(f.map(|UnboxedFnTy {decl, kind}| UnboxedFnTy { - decl: fld.fold_fn_decl(decl), - kind: kind, - })) - } TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))), TyParen(ty) => TyParen(fld.fold_ty(ty)), TyPath(path, bounds, id) => { @@ -480,15 +490,43 @@ pub fn noop_fold_uint<T: Folder>(i: uint, _: &mut T) -> uint { pub fn noop_fold_path<T: Folder>(Path {global, segments, span}: Path, fld: &mut T) -> Path { Path { global: global, - segments: segments.move_map(|PathSegment {identifier, lifetimes, types}| PathSegment { + segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment { identifier: fld.fold_ident(identifier), - lifetimes: fld.fold_lifetimes(lifetimes), - types: types.move_map(|typ| fld.fold_ty(typ)), + parameters: fld.fold_path_parameters(parameters), }), span: fld.new_span(span) } } +pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters, fld: &mut T) + -> PathParameters +{ + match path_parameters { + AngleBracketedParameters(data) => + AngleBracketedParameters(fld.fold_angle_bracketed_parameter_data(data)), + ParenthesizedParameters(data) => + ParenthesizedParameters(fld.fold_parenthesized_parameter_data(data)), + } +} + +pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedParameterData, + fld: &mut T) + -> AngleBracketedParameterData +{ + let AngleBracketedParameterData { lifetimes, types } = data; + AngleBracketedParameterData { lifetimes: fld.fold_lifetimes(lifetimes), + types: types.move_map(|ty| fld.fold_ty(ty)) } +} + +pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData, + fld: &mut T) + -> ParenthesizedParameterData +{ + let ParenthesizedParameterData { inputs, output } = data; + ParenthesizedParameterData { inputs: inputs.move_map(|ty| fld.fold_ty(ty)), + output: output.map(|ty| fld.fold_ty(ty)) } +} + pub fn noop_fold_local<T: Folder>(l: P<Local>, fld: &mut T) -> P<Local> { l.map(|Local {id, pat, ty, init, source, span}| Local { id: fld.new_id(id), @@ -671,23 +709,6 @@ pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T) match tpb { TraitTyParamBound(ty) => TraitTyParamBound(fld.fold_trait_ref(ty)), RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)), - UnboxedFnTyParamBound(bound) => { - match *bound { - UnboxedFnBound { - ref path, - ref decl, - ref lifetimes, - ref_id - } => { - UnboxedFnTyParamBound(P(UnboxedFnBound { - path: fld.fold_path(path.clone()), - decl: fld.fold_fn_decl(decl.clone()), - lifetimes: fld.fold_lifetime_defs(lifetimes.clone()), - ref_id: fld.new_id(ref_id), - })) - } - } - } } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 83499ec54c6..996708b2174 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -749,8 +749,7 @@ mod test { segments: vec!( ast::PathSegment { identifier: str_to_ident("a"), - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), } ), }), @@ -768,13 +767,11 @@ mod test { segments: vec!( ast::PathSegment { identifier: str_to_ident("a"), - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), }, ast::PathSegment { identifier: str_to_ident("b"), - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), } ) }), @@ -952,8 +949,7 @@ mod test { segments: vec!( ast::PathSegment { identifier: str_to_ident("d"), - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), } ), }), @@ -974,8 +970,7 @@ mod test { segments: vec!( ast::PathSegment { identifier: str_to_ident("b"), - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), } ), }), @@ -1022,8 +1017,7 @@ mod test { ast::PathSegment { identifier: str_to_ident("int"), - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), } ), }, None, ast::DUMMY_NODE_ID), @@ -1072,10 +1066,8 @@ mod test { identifier: str_to_ident( "b"), - lifetimes: - Vec::new(), - types: - OwnedSlice::empty() + parameters: + ast::PathParameters::none(), } ), }), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 10bb9ef3625..18dd7074d28 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -53,9 +53,8 @@ use ast::{TtNonterminal, TupleVariantKind, Ty, Ty_, TyBot}; use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn}; use ast::{TyTypeof, TyInfer, TypeMethod}; use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyQPath}; -use ast::{TyRptr, TyTup, TyU32, TyUnboxedFn, TyUniq, TyVec, UnUniq}; +use ast::{TyRptr, TyTup, TyU32, TyUniq, TyVec, UnUniq}; use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind}; -use ast::{UnboxedFnBound, UnboxedFnTy, UnboxedFnTyParamBound}; use ast::{UnnamedField, UnsafeBlock}; use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; @@ -1127,19 +1126,16 @@ impl<'a> Parser<'a> { Vec::new() }; - let (optional_unboxed_closure_kind, inputs) = if self.eat(&token::OrOr) { - (None, Vec::new()) + let inputs = if self.eat(&token::OrOr) { + Vec::new() } else { self.expect_or(); - let optional_unboxed_closure_kind = - self.parse_optional_unboxed_closure_kind(); - let inputs = self.parse_seq_to_before_or( &token::Comma, |p| p.parse_arg_general(false)); self.expect_or(); - (optional_unboxed_closure_kind, inputs) + inputs }; let bounds = self.parse_colon_then_ty_param_bounds(); @@ -1152,23 +1148,13 @@ impl<'a> Parser<'a> { variadic: false }); - match optional_unboxed_closure_kind { - Some(unboxed_closure_kind) => { - TyUnboxedFn(P(UnboxedFnTy { - kind: unboxed_closure_kind, - decl: decl, - })) - } - None => { - TyClosure(P(ClosureTy { - fn_style: fn_style, - onceness: onceness, - bounds: bounds, - decl: decl, - lifetimes: lifetime_defs, - })) - } - } + TyClosure(P(ClosureTy { + fn_style: fn_style, + onceness: onceness, + bounds: bounds, + decl: decl, + lifetimes: lifetime_defs, + })) } pub fn parse_unsafety(&mut self) -> FnStyle { @@ -1487,9 +1473,9 @@ impl<'a> Parser<'a> { trait_name: trait_name.path, item_name: item_name, })) - } else if self.token == token::ModSep - || self.token.is_ident() - || self.token.is_path() { + } else if self.token == token::ModSep || + self.token.is_ident() || + self.token.is_path() { // NAMED TYPE let mode = if plus_allowed { LifetimeAndTypesAndBounds @@ -1706,50 +1692,18 @@ impl<'a> Parser<'a> { // Parse any number of segments and bound sets. A segment is an // identifier followed by an optional lifetime and a set of types. // A bound set is a set of type parameter bounds. - let mut segments = Vec::new(); - loop { - // First, parse an identifier. - let identifier = self.parse_ident(); - - // Parse the '::' before type parameters if it's required. If - // it is required and wasn't present, then we're done. - if mode == LifetimeAndTypesWithColons && - !self.eat(&token::ModSep) { - segments.push(ast::PathSegment { - identifier: identifier, - lifetimes: Vec::new(), - types: OwnedSlice::empty(), - }); - break + let segments = match mode { + LifetimeAndTypesWithoutColons | + LifetimeAndTypesAndBounds => { + self.parse_path_segments_without_colons() } - - // Parse the `<` before the lifetime and types, if applicable. - let (any_lifetime_or_types, lifetimes, types) = { - if mode != NoTypesAllowed && self.eat_lt(false) { - let (lifetimes, types) = - self.parse_generic_values_after_lt(); - (true, lifetimes, OwnedSlice::from_vec(types)) - } else { - (false, Vec::new(), OwnedSlice::empty()) - } - }; - - // Assemble and push the result. - segments.push(ast::PathSegment { - identifier: identifier, - lifetimes: lifetimes, - types: types, - }); - - // We're done if we don't see a '::', unless the mode required - // a double colon to get here in the first place. - if !(mode == LifetimeAndTypesWithColons && - !any_lifetime_or_types) { - if !self.eat(&token::ModSep) { - break - } + LifetimeAndTypesWithColons => { + self.parse_path_segments_with_colons() } - } + NoTypesAllowed => { + self.parse_path_segments_without_types() + } + }; // Next, parse a plus and bounded type parameters, if // applicable. We need to remember whether the separate was @@ -1792,6 +1746,123 @@ impl<'a> Parser<'a> { } } + /// Examples: + /// - `a::b<T,U>::c<V,W>` + /// - `a::b<T,U>::c(V) -> W` + /// - `a::b<T,U>::c(V)` + pub fn parse_path_segments_without_colons(&mut self) -> Vec<ast::PathSegment> { + let mut segments = Vec::new(); + loop { + // First, parse an identifier. + let identifier = self.parse_ident(); + + // Parse types, optionally. + let parameters = if self.eat_lt(false) { + let (lifetimes, types) = self.parse_generic_values_after_lt(); + + ast::AngleBracketedParameters(ast::AngleBracketedParameterData { + lifetimes: lifetimes, + types: OwnedSlice::from_vec(types), + }) + } else if self.eat(&token::OpenDelim(token::Paren)) { + let inputs = self.parse_seq_to_end( + &token::CloseDelim(token::Paren), + seq_sep_trailing_allowed(token::Comma), + |p| p.parse_ty(true)); + + let output_ty = if self.eat(&token::RArrow) { + Some(self.parse_ty(true)) + } else { + None + }; + + ast::ParenthesizedParameters(ast::ParenthesizedParameterData { + inputs: inputs, + output: output_ty + }) + } else { + ast::PathParameters::none() + }; + + // Assemble and push the result. + segments.push(ast::PathSegment { identifier: identifier, + parameters: parameters }); + + // Continue only if we see a `::` + if !self.eat(&token::ModSep) { + return segments; + } + } + } + + /// Examples: + /// - `a::b::<T,U>::c` + pub fn parse_path_segments_with_colons(&mut self) -> Vec<ast::PathSegment> { + let mut segments = Vec::new(); + loop { + // First, parse an identifier. + let identifier = self.parse_ident(); + + // If we do not see a `::`, stop. + if !self.eat(&token::ModSep) { + segments.push(ast::PathSegment { + identifier: identifier, + parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { + lifetimes: Vec::new(), + types: OwnedSlice::empty(), + }) + }); + return segments; + } + + // Check for a type segment. + if self.eat_lt(false) { + // Consumed `a::b::<`, go look for types + let (lifetimes, types) = self.parse_generic_values_after_lt(); + segments.push(ast::PathSegment { + identifier: identifier, + parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { + lifetimes: lifetimes, + types: OwnedSlice::from_vec(types), + }), + }); + + // Consumed `a::b::<T,U>`, check for `::` before proceeding + if !self.eat(&token::ModSep) { + return segments; + } + } else { + // Consumed `a::`, go look for `b` + segments.push(ast::PathSegment { + identifier: identifier, + parameters: ast::PathParameters::none(), + }); + } + } + } + + + /// Examples: + /// - `a::b::c` + pub fn parse_path_segments_without_types(&mut self) -> Vec<ast::PathSegment> { + let mut segments = Vec::new(); + loop { + // First, parse an identifier. + let identifier = self.parse_ident(); + + // Assemble and push the result. + segments.push(ast::PathSegment { + identifier: identifier, + parameters: ast::PathParameters::none() + }); + + // If we do not see a `::`, stop. + if !self.eat(&token::ModSep) { + return segments; + } + } + } + /// parses 0 or 1 lifetime pub fn parse_opt_lifetime(&mut self) -> Option<ast::Lifetime> { match self.token { @@ -3389,13 +3460,9 @@ impl<'a> Parser<'a> { }, _ => { if !enum_path.global && - enum_path.segments.len() == 1 && - enum_path.segments[0] - .lifetimes - .len() == 0 && - enum_path.segments[0] - .types - .len() == 0 { + enum_path.segments.len() == 1 && + enum_path.segments[0].parameters.is_empty() + { // it could still be either an enum // or an identifier pattern, resolve // will sort it out: @@ -3854,31 +3921,11 @@ impl<'a> Parser<'a> { token::ModSep | token::Ident(..) => { let path = self.parse_path(LifetimeAndTypesWithoutColons).path; - if self.token == token::OpenDelim(token::Paren) { - self.bump(); - let inputs = self.parse_seq_to_end( - &token::CloseDelim(token::Paren), - seq_sep_trailing_allowed(token::Comma), - |p| p.parse_arg_general(false)); - let (return_style, output) = self.parse_ret_ty(); - result.push(UnboxedFnTyParamBound(P(UnboxedFnBound { - path: path, - decl: P(FnDecl { - inputs: inputs, - output: output, - cf: return_style, - variadic: false, - }), - lifetimes: lifetime_defs, - ref_id: ast::DUMMY_NODE_ID, - }))); - } else { - result.push(TraitTyParamBound(ast::TraitRef { - path: path, - ref_id: ast::DUMMY_NODE_ID, - lifetimes: lifetime_defs, - })) - } + result.push(TraitTyParamBound(ast::TraitRef { + path: path, + ref_id: ast::DUMMY_NODE_ID, + lifetimes: lifetime_defs, + })) } _ => break, } @@ -3894,8 +3941,7 @@ impl<'a> Parser<'a> { fn trait_ref_from_ident(ident: Ident, span: Span) -> ast::TraitRef { let segment = ast::PathSegment { identifier: ident, - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none() }; let path = ast::Path { span: span, @@ -5611,8 +5657,7 @@ impl<'a> Parser<'a> { segments: path.into_iter().map(|identifier| { ast::PathSegment { identifier: identifier, - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), } }).collect() }; @@ -5646,8 +5691,7 @@ impl<'a> Parser<'a> { segments: path.into_iter().map(|identifier| { ast::PathSegment { identifier: identifier, - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), } }).collect() }; @@ -5664,8 +5708,7 @@ impl<'a> Parser<'a> { segments: path.into_iter().map(|identifier| { ast::PathSegment { identifier: identifier, - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), } }).collect() }; @@ -5686,8 +5729,7 @@ impl<'a> Parser<'a> { segments: path.into_iter().map(|identifier| { ast::PathSegment { identifier: identifier, - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), } }).collect() }; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 106e3f1faae..2448eacbb39 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -13,7 +13,7 @@ use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind}; use ast::{FnOnceUnboxedClosureKind}; use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound}; use ast::{RequiredMethod, ProvidedMethod, TypeImplItem, TypeTraitItem}; -use ast::{UnboxedClosureKind, UnboxedFnTyParamBound}; +use ast::{UnboxedClosureKind}; use ast; use ast_util; use owned_slice::OwnedSlice; @@ -699,7 +699,6 @@ impl<'a> State<'a> { None, &OwnedSlice::empty(), Some(&generics), - None, None)); } ast::TyClosure(ref f) => { @@ -719,7 +718,6 @@ impl<'a> State<'a> { None, &f.bounds, Some(&generics), - None, None)); } ast::TyProc(ref f) => { @@ -739,21 +737,8 @@ impl<'a> State<'a> { None, &f.bounds, Some(&generics), - None, None)); } - ast::TyUnboxedFn(ref f) => { - try!(self.print_ty_fn(None, - None, - ast::NormalFn, - ast::Many, - &*f.decl, - None, - &OwnedSlice::empty(), - None, - None, - Some(f.kind))); - } ast::TyPath(ref path, ref bounds, _) => { try!(self.print_bounded_path(path, bounds)); } @@ -1212,8 +1197,7 @@ impl<'a> State<'a> { Some(m.ident), &OwnedSlice::empty(), Some(&m.generics), - Some(&m.explicit_self.node), - None)); + Some(&m.explicit_self.node))); word(&mut self.s, ";") } @@ -1995,14 +1979,34 @@ impl<'a> State<'a> { try!(self.print_ident(segment.identifier)); - if !segment.lifetimes.is_empty() || !segment.types.is_empty() { - if colons_before_params { - try!(word(&mut self.s, "::")) - } + try!(self.print_path_parameters(&segment.parameters, colons_before_params)); + } + + match *opt_bounds { + None => Ok(()), + Some(ref bounds) => self.print_bounds("+", bounds) + } + } + + fn print_path_parameters(&mut self, + parameters: &ast::PathParameters, + colons_before_params: bool) + -> IoResult<()> + { + if parameters.is_empty() { + return Ok(()); + } + + if colons_before_params { + try!(word(&mut self.s, "::")) + } + + match *parameters { + ast::AngleBracketedParameters(ref data) => { try!(word(&mut self.s, "<")); let mut comma = false; - for lifetime in segment.lifetimes.iter() { + for lifetime in data.lifetimes.iter() { if comma { try!(self.word_space(",")) } @@ -2010,24 +2014,38 @@ impl<'a> State<'a> { comma = true; } - if !segment.types.is_empty() { + if !data.types.is_empty() { if comma { try!(self.word_space(",")) } try!(self.commasep( Inconsistent, - segment.types.as_slice(), + data.types.as_slice(), |s, ty| s.print_type(&**ty))); } try!(word(&mut self.s, ">")) } - } - match *opt_bounds { - None => Ok(()), - Some(ref bounds) => self.print_bounds("+", bounds) + ast::ParenthesizedParameters(ref data) => { + try!(word(&mut self.s, "(")); + try!(self.commasep( + Inconsistent, + data.inputs.as_slice(), + |s, ty| s.print_type(&**ty))); + try!(word(&mut self.s, ")")); + + match data.output { + None => { } + Some(ref ty) => { + try!(self.word_space("->")); + try!(self.print_type(&**ty)); + } + } + } } + + Ok(()) } fn print_path(&mut self, path: &ast::Path, @@ -2373,15 +2391,6 @@ impl<'a> State<'a> { RegionTyParamBound(ref lt) => { self.print_lifetime(lt) } - UnboxedFnTyParamBound(ref unboxed_function_type) => { - try!(self.print_path(&unboxed_function_type.path, - false)); - try!(self.popen()); - try!(self.print_fn_args(&*unboxed_function_type.decl, - None)); - try!(self.pclose()); - self.print_fn_output(&*unboxed_function_type.decl) - } }) } Ok(()) @@ -2641,9 +2650,7 @@ impl<'a> State<'a> { id: Option<ast::Ident>, bounds: &OwnedSlice<ast::TyParamBound>, generics: Option<&ast::Generics>, - opt_explicit_self: Option<&ast::ExplicitSelf_>, - opt_unboxed_closure_kind: - Option<ast::UnboxedClosureKind>) + opt_explicit_self: Option<&ast::ExplicitSelf_>) -> IoResult<()> { try!(self.ibox(indent_unit)); @@ -2660,9 +2667,7 @@ impl<'a> State<'a> { try!(self.print_fn_style(fn_style)); try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi)); try!(self.print_onceness(onceness)); - if opt_unboxed_closure_kind.is_none() { - try!(word(&mut self.s, "fn")); - } + try!(word(&mut self.s, "fn")); } match id { @@ -2676,30 +2681,15 @@ impl<'a> State<'a> { match generics { Some(g) => try!(self.print_generics(g)), _ => () } try!(zerobreak(&mut self.s)); - if opt_unboxed_closure_kind.is_some() || opt_sigil == Some('&') { + if opt_sigil == Some('&') { try!(word(&mut self.s, "|")); } else { try!(self.popen()); } - match opt_unboxed_closure_kind { - Some(ast::FnUnboxedClosureKind) => { - try!(word(&mut self.s, "&")); - try!(self.word_space(":")); - } - Some(ast::FnMutUnboxedClosureKind) => { - try!(word(&mut self.s, "&mut")); - try!(self.word_space(":")); - } - Some(ast::FnOnceUnboxedClosureKind) => { - try!(self.word_space(":")); - } - None => {} - } - try!(self.print_fn_args(decl, opt_explicit_self)); - if opt_unboxed_closure_kind.is_some() || opt_sigil == Some('&') { + if opt_sigil == Some('&') { try!(word(&mut self.s, "|")); } else { if decl.variadic { diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 0f86fb751da..6a4ab365a50 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -14,7 +14,6 @@ use codemap::DUMMY_SP; use codemap; use fold::Folder; use fold; -use owned_slice::OwnedSlice; use parse::token::InternedString; use parse::token::special_idents; use parse::token; @@ -181,13 +180,11 @@ impl<'a> fold::Folder for PreludeInjector<'a> { segments: vec!( ast::PathSegment { identifier: token::str_to_ident("std"), - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), }, ast::PathSegment { identifier: token::str_to_ident("prelude"), - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), }), }; diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 37586f6abd7..a7db8e800a9 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -453,8 +453,7 @@ fn path_node(ids: Vec<ast::Ident> ) -> ast::Path { global: false, segments: ids.into_iter().map(|identifier| ast::PathSegment { identifier: identifier, - lifetimes: Vec::new(), - types: OwnedSlice::empty(), + parameters: ast::PathParameters::none(), }).collect() } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 86ee23d71a6..9751abacbd3 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -365,12 +365,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { visitor.visit_ty(&*function_declaration.decl.output); walk_lifetime_decls(visitor, &function_declaration.lifetimes); } - TyUnboxedFn(ref function_declaration) => { - for argument in function_declaration.decl.inputs.iter() { - visitor.visit_ty(&*argument.ty) - } - visitor.visit_ty(&*function_declaration.decl.output); - } TyPath(ref path, ref opt_bounds, id) => { visitor.visit_path(path, id); match *opt_bounds { @@ -407,11 +401,23 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) { for segment in path.segments.iter() { visitor.visit_ident(path.span, segment.identifier); - for typ in segment.types.iter() { - visitor.visit_ty(&**typ); - } - for lifetime in segment.lifetimes.iter() { - visitor.visit_lifetime_ref(lifetime); + match segment.parameters { + ast::AngleBracketedParameters(ref data) => { + for typ in data.types.iter() { + visitor.visit_ty(&**typ); + } + for lifetime in data.lifetimes.iter() { + visitor.visit_lifetime_ref(lifetime); + } + } + ast::ParenthesizedParameters(ref data) => { + for typ in data.inputs.iter() { + visitor.visit_ty(&**typ); + } + for typ in data.output.iter() { + visitor.visit_ty(&**typ); + } + } } } } @@ -493,13 +499,6 @@ pub fn walk_ty_param_bounds<'v, V: Visitor<'v>>(visitor: &mut V, TraitTyParamBound(ref typ) => { walk_trait_ref_helper(visitor, typ) } - UnboxedFnTyParamBound(ref function_declaration) => { - for argument in function_declaration.decl.inputs.iter() { - visitor.visit_ty(&*argument.ty) - } - visitor.visit_ty(&*function_declaration.decl.output); - walk_lifetime_decls(visitor, &function_declaration.lifetimes); - } RegionTyParamBound(ref lifetime) => { visitor.visit_lifetime_ref(lifetime); } |
