diff options
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ast.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/ast_util.rs | 8 | ||||
| -rw-r--r-- | src/libsyntax/codemap.rs | 28 | ||||
| -rw-r--r-- | src/libsyntax/ext/build.rs | 23 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/decodable.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic/mod.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/generic/ty.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/ext/deriving/mod.rs | 13 | ||||
| -rw-r--r-- | src/libsyntax/ext/format.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/quote.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_parser.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/fold.rs | 10 | ||||
| -rw-r--r-- | src/libsyntax/owned_slice.rs | 104 | ||||
| -rw-r--r-- | src/libsyntax/parse/mod.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/parse/obsolete.rs | 12 | ||||
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 213 | ||||
| -rw-r--r-- | src/libsyntax/parse/token.rs | 12 | ||||
| -rw-r--r-- | src/libsyntax/print/pprust.rs | 54 | ||||
| -rw-r--r-- | src/libsyntax/test.rs | 3 | ||||
| -rw-r--r-- | src/libsyntax/visit.rs | 20 |
20 files changed, 209 insertions, 342 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 3d33774aa55..28d5fbb9689 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -276,11 +276,9 @@ impl PathParameters { } } + /// Returns the types that the user wrote. Note that these do not necessarily map to the type + /// parameters in the parenthesized case. 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() @@ -1151,7 +1149,9 @@ pub enum Ty_ { /// A path (`module::module::...::Type`) or primitive /// /// Type parameters are stored in the Path itself - TyPath(Path, Option<TyParamBounds>, NodeId), // for #7264; see above + TyPath(Path, NodeId), + /// Something like `A+B`. Note that `B` must always be a path. + TyObjectSum(P<Ty>, TyParamBounds), /// A type like `for<'a> Foo<&'a Bar>` TyPolyTraitRef(TyParamBounds), /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType` diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 043e79bffd9..aa693976fe4 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -454,7 +454,7 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { fn visit_ty(&mut self, typ: &Ty) { self.operation.visit_id(typ.id); match typ.node { - TyPath(_, _, id) => self.operation.visit_id(id), + TyPath(_, id) => self.operation.visit_id(id), _ => {} } visit::walk_ty(self, typ) @@ -569,6 +569,7 @@ pub fn compute_id_range_for_inlined_item(item: &InlinedItem) -> IdRange { visitor.result } +/// Computes the id range for a single fn body, ignoring nested items. pub fn compute_id_range_for_fn_body(fk: visit::FnKind, decl: &FnDecl, body: &Block, @@ -576,11 +577,6 @@ pub fn compute_id_range_for_fn_body(fk: visit::FnKind, id: NodeId) -> IdRange { - /*! - * Computes the id range for a single fn body, - * ignoring nested items. - */ - let mut visitor = IdRangeComputingVisitor { result: IdRange::max() }; diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index b019b31de5f..27e8c265e5c 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -10,18 +10,12 @@ // // ignore-lexer-test FIXME #15679 -/*! - -The CodeMap tracks all the source code used within a single crate, mapping -from integer byte positions to the original source code location. Each bit of -source parsed during crate parsing (typically files, in-memory strings, or -various bits of macro expansion) cover a continuous range of bytes in the -CodeMap and are represented by FileMaps. Byte positions are stored in `spans` -and used pervasively in the compiler. They are absolute positions within the -CodeMap, which upon request can be converted to line and column information, -source code snippets, etc. - -*/ +//! The CodeMap tracks all the source code used within a single crate, mapping from integer byte +//! positions to the original source code location. Each bit of source parsed during crate parsing +//! (typically files, in-memory strings, or various bits of macro expansion) cover a continuous +//! range of bytes in the CodeMap and are represented by FileMaps. Byte positions are stored in +//! `spans` and used pervasively in the compiler. They are absolute positions within the CodeMap, +//! which upon request can be converted to line and column information, source code snippets, etc. pub use self::MacroFormat::*; @@ -83,12 +77,10 @@ impl Sub<CharPos,CharPos> for CharPos { } } -/** -Spans represent a region of code, used for error reporting. Positions in spans -are *absolute* positions from the beginning of the codemap, not positions -relative to FileMaps. Methods on the CodeMap can be used to relate spans back -to the original source. -*/ +/// Spans represent a region of code, used for error reporting. Positions in spans +/// are *absolute* positions from the beginning of the codemap, not positions +/// relative to FileMaps. Methods on the CodeMap can be used to relate spans back +/// to the original source. #[deriving(Clone, Show, Hash)] pub struct Span { pub lo: BytePos, diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 2c7f9e889f8..bd01e5e6430 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -44,7 +44,8 @@ pub trait AstBuilder { fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy; fn ty(&self, span: Span, ty: ast::Ty_) -> P<ast::Ty>; - fn ty_path(&self, ast::Path, Option<OwnedSlice<ast::TyParamBound>>) -> P<ast::Ty>; + fn ty_path(&self, ast::Path) -> P<ast::Ty>; + fn ty_sum(&self, ast::Path, OwnedSlice<ast::TyParamBound>) -> P<ast::Ty>; fn ty_ident(&self, span: Span, idents: ast::Ident) -> P<ast::Ty>; fn ty_rptr(&self, span: Span, @@ -344,17 +345,21 @@ impl<'a> AstBuilder for ExtCtxt<'a> { }) } - fn ty_path(&self, path: ast::Path, bounds: Option<OwnedSlice<ast::TyParamBound>>) - -> P<ast::Ty> { + fn ty_path(&self, path: ast::Path) -> P<ast::Ty> { + self.ty(path.span, ast::TyPath(path, ast::DUMMY_NODE_ID)) + } + + fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice<ast::TyParamBound>) -> P<ast::Ty> { self.ty(path.span, - ast::TyPath(path, bounds, ast::DUMMY_NODE_ID)) + ast::TyObjectSum(self.ty_path(path), + bounds)) } // Might need to take bounds as an argument in the future, if you ever want // to generate a bounded existential trait type. fn ty_ident(&self, span: Span, ident: ast::Ident) -> P<ast::Ty> { - self.ty_path(self.path_ident(span, ident), None) + self.ty_path(self.path_ident(span, ident)) } fn ty_rptr(&self, @@ -386,7 +391,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.ident_of("Option") ), Vec::new(), - vec!( ty )), None) + vec!( ty ))) } fn ty_field_imm(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::TypeField { @@ -425,8 +430,10 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn ty_vars_global(&self, ty_params: &OwnedSlice<ast::TyParam>) -> Vec<P<ast::Ty>> { - ty_params.iter().map(|p| self.ty_path( - self.path_global(DUMMY_SP, vec!(p.ident)), None)).collect() + ty_params + .iter() + .map(|p| self.ty_path(self.path_global(DUMMY_SP, vec!(p.ident)))) + .collect() } fn trait_ref(&self, path: ast::Path) -> ast::TraitRef { diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index d0a03658386..e3cf2b68752 100644 --- a/src/libsyntax/ext/deriving/decodable.rs +++ b/src/libsyntax/ext/deriving/decodable.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -The compiler code necessary for `#[deriving(Decodable)]`. See -encodable.rs for more. -*/ +//! The compiler code necessary for `#[deriving(Decodable)]`. See encodable.rs for more. use ast; use ast::{MetaItem, Item, Expr, MutMutable}; diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index fcd4966683d..d5f472bd827 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -444,7 +444,7 @@ impl<'a> TraitDef<'a> { // Create the type of `self`. let self_type = cx.ty_path( cx.path_all(self.span, false, vec!( type_ident ), self_lifetimes, - self_ty_params.into_vec()), None); + self_ty_params.into_vec())); let attr = cx.attribute( self.span, diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs index 700ada8b4ad..01398273161 100644 --- a/src/libsyntax/ext/deriving/generic/ty.rs +++ b/src/libsyntax/ext/deriving/generic/ty.rs @@ -8,10 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -A mini version of ast::Ty, which is easier to use, and features an -explicit `Self` type to use when specifying impls to be derived. -*/ +//! A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use +//! when specifying impls to be derived. pub use self::PtrTy::*; pub use self::Ty::*; @@ -70,7 +68,7 @@ impl<'a> Path<'a> { self_ty: Ident, self_generics: &Generics) -> P<ast::Ty> { - cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None) + cx.ty_path(self.to_path(cx, span, self_ty, self_generics)) } pub fn to_path(&self, cx: &ExtCtxt, @@ -152,7 +150,7 @@ impl<'a> Ty<'a> { } Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) } Self => { - cx.ty_path(self.to_path(cx, span, self_ty, self_generics), None) + cx.ty_path(self.to_path(cx, span, self_ty, self_generics)) } Tuple(ref fields) => { let ty = ast::TyTup(fields.iter() diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index b8cebd8ea20..fccef47d1ea 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -8,15 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -The compiler code necessary to implement the `#[deriving]` extensions. - - -FIXME (#2810): hygiene. Search for "__" strings (in other files too). -We also assume "extra" is the standard library, and "std" is the core -library. - -*/ +//! The compiler code necessary to implement the `#[deriving]` extensions. +//! +//! FIXME (#2810): hygiene. Search for "__" strings (in other files too). We also assume "extra" is +//! the standard library, and "std" is the core library. use ast::{Item, MetaItem, MetaList, MetaNameValue, MetaWord}; use ext::base::ExtCtxt; diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 490246f8246..d7d6c636849 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -531,7 +531,7 @@ impl<'a, 'b> Context<'a, 'b> { true, Context::rtpath(self.ecx, "Argument"), vec![static_lifetime], vec![] - ), None); + )); lets.push(Context::item_static_array(self.ecx, static_args_name, piece_ty, diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index eaa3632cf49..3fca110a881 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -17,16 +17,12 @@ use parse::token::*; use parse::token; use ptr::P; -/** -* -* Quasiquoting works via token trees. -* -* This is registered as a set of expression syntax extension called quote! -* that lifts its argument token-tree to an AST representing the -* construction of the same token tree, with token::SubstNt interpreted -* as antiquotes (splices). -* -*/ +/// Quasiquoting works via token trees. +/// +/// This is registered as a set of expression syntax extension called quote! +/// that lifts its argument token-tree to an AST representing the +/// construction of the same token tree, with token::SubstNt interpreted +/// as antiquotes (splices). pub mod rt { use ast; diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index b4cd9779ae2..4785fe37293 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -514,7 +514,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal { "stmt" => token::NtStmt(p.parse_stmt(Vec::new())), "pat" => token::NtPat(p.parse_pat()), "expr" => token::NtExpr(p.parse_expr()), - "ty" => token::NtTy(p.parse_ty(false /* no need to disambiguate*/)), + "ty" => token::NtTy(p.parse_ty()), // this could be handled like a token, since it is one "ident" => match p.token { token::Ident(sn,b) => { p.bump(); token::NtIdent(box sn,b) } @@ -525,7 +525,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal { } }, "path" => { - token::NtPath(box p.parse_path(LifetimeAndTypesWithoutColons).path) + token::NtPath(box p.parse_path(LifetimeAndTypesWithoutColons)) } "meta" => token::NtMeta(p.parse_meta_item()), "tt" => { diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 6941c0e9c18..122f99cabb3 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -433,11 +433,13 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { } TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))), TyParen(ty) => TyParen(fld.fold_ty(ty)), - TyPath(path, bounds, id) => { + TyPath(path, id) => { let id = fld.new_id(id); - TyPath(fld.fold_path(path), - fld.fold_opt_bounds(bounds), - id) + TyPath(fld.fold_path(path), id) + } + TyObjectSum(ty, bounds) => { + TyObjectSum(fld.fold_ty(ty), + fld.fold_bounds(bounds)) } TyQPath(qpath) => { TyQPath(fld.fold_qpath(qpath)) diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index b31b20c80c2..43b428b5a1c 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -10,99 +10,39 @@ use std::fmt; use std::default::Default; -use std::hash; -use std::{mem, raw, ptr, slice, vec}; -use std::rt::heap::EMPTY; +use std::vec; use serialize::{Encodable, Decodable, Encoder, Decoder}; -/// A non-growable owned slice. This would preferably become `~[T]` -/// under DST. -#[unsafe_no_drop_flag] // data is set to null on destruction +/// A non-growable owned slice. This is a separate type to allow the +/// representation to change. +#[deriving(Hash, PartialEq, Eq, PartialOrd, Ord)] pub struct OwnedSlice<T> { - /// null iff len == 0 - data: *mut T, - len: uint, + data: Box<[T]> } impl<T:fmt::Show> fmt::Show for OwnedSlice<T> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - try!("OwnedSlice {{".fmt(fmt)); - for i in self.iter() { - try!(i.fmt(fmt)); - } - try!("}}".fmt(fmt)); - Ok(()) - } -} - -#[unsafe_destructor] -impl<T> Drop for OwnedSlice<T> { - fn drop(&mut self) { - if self.data.is_null() { return } - - // extract the vector - let v = mem::replace(self, OwnedSlice::empty()); - // free via the Vec destructor - v.into_vec(); + self.data.fmt(fmt) } } impl<T> OwnedSlice<T> { pub fn empty() -> OwnedSlice<T> { - OwnedSlice { data: ptr::null_mut(), len: 0 } + OwnedSlice { data: box [] } } #[inline(never)] - pub fn from_vec(mut v: Vec<T>) -> OwnedSlice<T> { - let len = v.len(); - - if len == 0 { - OwnedSlice::empty() - } else { - // drop excess capacity to avoid breaking sized deallocation - v.shrink_to_fit(); - - let p = v.as_mut_ptr(); - // we own the allocation now - unsafe { mem::forget(v) } - - OwnedSlice { data: p, len: len } - } + pub fn from_vec(v: Vec<T>) -> OwnedSlice<T> { + OwnedSlice { data: v.into_boxed_slice() } } #[inline(never)] pub fn into_vec(self) -> Vec<T> { - // null is ok, because len == 0 in that case, as required by Vec. - unsafe { - let ret = Vec::from_raw_parts(self.data, self.len, self.len); - // the vector owns the allocation now - mem::forget(self); - ret - } + self.data.into_vec() } pub fn as_slice<'a>(&'a self) -> &'a [T] { - let ptr = if self.data.is_null() { - // length zero, i.e. this will never be read as a T. - EMPTY as *const T - } else { - self.data as *const T - }; - - let slice: &[T] = unsafe {mem::transmute(raw::Slice { - data: ptr, - len: self.len - })}; - - slice - } - - pub fn get<'a>(&'a self, i: uint) -> &'a T { - self.as_slice().get(i).expect("OwnedSlice: index out of bounds") - } - - pub fn iter<'r>(&'r self) -> slice::Items<'r, T> { - self.as_slice().iter() + &*self.data } pub fn move_iter(self) -> vec::MoveItems<T> { @@ -112,10 +52,12 @@ impl<T> OwnedSlice<T> { pub fn map<U>(&self, f: |&T| -> U) -> OwnedSlice<U> { self.iter().map(f).collect() } +} - pub fn len(&self) -> uint { self.len } - - pub fn is_empty(&self) -> bool { self.len == 0 } +impl<T> Deref<[T]> for OwnedSlice<T> { + fn deref(&self) -> &[T] { + self.as_slice() + } } impl<T> Default for OwnedSlice<T> { @@ -130,20 +72,6 @@ impl<T: Clone> Clone for OwnedSlice<T> { } } -impl<S: hash::Writer, T: hash::Hash<S>> hash::Hash<S> for OwnedSlice<T> { - fn hash(&self, state: &mut S) { - self.as_slice().hash(state) - } -} - -impl<T: PartialEq> PartialEq for OwnedSlice<T> { - fn eq(&self, other: &OwnedSlice<T>) -> bool { - self.as_slice() == other.as_slice() - } -} - -impl<T: Eq> Eq for OwnedSlice<T> {} - impl<T> FromIterator<T> for OwnedSlice<T> { fn from_iter<I: Iterator<T>>(iter: I) -> OwnedSlice<T> { OwnedSlice::from_vec(iter.collect()) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 96659031e6a..b46f7cdfe22 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -1029,7 +1029,7 @@ mod test { parameters: ast::PathParameters::none(), } ), - }, None, ast::DUMMY_NODE_ID), + }, ast::DUMMY_NODE_ID), span:sp(10,13) }), pat: P(ast::Pat { diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index e2dee607c69..86a96fc5216 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -8,14 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/*! -Support for parsing unsupported, old syntaxes, for the -purpose of reporting errors. Parsing of these syntaxes -is tested by compile-test/obsolete-syntax.rs. - -Obsolete syntax that becomes too hard to parse can be -removed. -*/ +//! Support for parsing unsupported, old syntaxes, for the purpose of reporting errors. Parsing of +//! these syntaxes is tested by compile-test/obsolete-syntax.rs. +//! +//! Obsolete syntax that becomes too hard to parse can be removed. pub use self::ObsoleteSyntax::*; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c731a0005f8..447f2a376e1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -111,16 +111,6 @@ pub enum PathParsingMode { /// A path with a lifetime and type parameters with double colons before /// the type parameters; e.g. `foo::bar::<'a>::Baz::<T>` LifetimeAndTypesWithColons, - /// A path with a lifetime and type parameters with bounds before the last - /// set of type parameters only; e.g. `foo::bar<'a>::Baz+X+Y<T>` This - /// form does not use extra double colons. - LifetimeAndTypesAndBounds, -} - -/// A path paired with optional type bounds. -pub struct PathAndBounds { - pub path: ast::Path, - pub bounds: Option<ast::TyParamBounds>, } enum ItemOrViewItem { @@ -1053,17 +1043,9 @@ impl<'a> Parser<'a> { } } - pub fn parse_ty_path(&mut self, plus_allowed: bool) -> Ty_ { - let mode = if plus_allowed { - LifetimeAndTypesAndBounds - } else { - LifetimeAndTypesWithoutColons - }; - let PathAndBounds { - path, - bounds - } = self.parse_path(mode); - TyPath(path, bounds, ast::DUMMY_NODE_ID) + pub fn parse_ty_path(&mut self) -> Ty_ { + let path = self.parse_path(LifetimeAndTypesWithoutColons); + TyPath(path, ast::DUMMY_NODE_ID) } /// parse a TyBareFn type: @@ -1286,7 +1268,7 @@ impl<'a> Parser<'a> { let lo = self.span.lo; let ident = self.parse_ident(); self.expect(&token::Eq); - let typ = self.parse_ty(true); + let typ = self.parse_ty_sum(); let hi = self.span.hi; self.expect(&token::Semi); Typedef { @@ -1385,7 +1367,7 @@ impl<'a> Parser<'a> { /// Parse a possibly mutable type pub fn parse_mt(&mut self) -> MutTy { let mutbl = self.parse_mutability(); - let t = self.parse_ty(true); + let t = self.parse_ty(); MutTy { ty: t, mutbl: mutbl } } @@ -1396,7 +1378,7 @@ impl<'a> Parser<'a> { let mutbl = self.parse_mutability(); let id = self.parse_ident(); self.expect(&token::Colon); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); let hi = ty.span.hi; ast::TypeField { ident: id, @@ -1411,7 +1393,19 @@ impl<'a> Parser<'a> { if self.eat(&token::Not) { NoReturn(self.span) } else { - Return(self.parse_ty(true)) + let t = self.parse_ty(); + + // We used to allow `fn foo() -> &T + U`, but don't + // anymore. If we see it, report a useful error. This + // only makes sense because `parse_ret_ty` is only + // used in fn *declarations*, not fn types or where + // clauses (i.e., not when parsing something like + // `FnMut() -> T + Send`, where the `+` is legal). + if self.token == token::BinOp(token::Plus) { + self.warn("deprecated syntax: `()` are required, see RFC 248 for details"); + } + + Return(t) } } else { let pos = self.span.lo; @@ -1423,11 +1417,36 @@ impl<'a> Parser<'a> { } } + /// Parse a type in a context where `T1+T2` is allowed. + pub fn parse_ty_sum(&mut self) -> P<Ty> { + let lo = self.span.lo; + let lhs = self.parse_ty(); + + if !self.eat(&token::BinOp(token::Plus)) { + return lhs; + } + + let bounds = self.parse_ty_param_bounds(); + + // In type grammar, `+` is treated like a binary operator, + // and hence both L and R side are required. + if bounds.len() == 0 { + let last_span = self.last_span; + self.span_err(last_span, + "at least one type parameter bound \ + must be specified"); + } + + let sp = mk_sp(lo, self.last_span.hi); + let sum = ast::TyObjectSum(lhs, bounds); + P(Ty {id: ast::DUMMY_NODE_ID, node: sum, span: sp}) + } + /// Parse a type. /// /// The second parameter specifies whether the `+` binary operator is /// allowed in the type grammar. - pub fn parse_ty(&mut self, plus_allowed: bool) -> P<Ty> { + pub fn parse_ty(&mut self) -> P<Ty> { maybe_whole!(no_clone self, NtTy); let lo = self.span.lo; @@ -1441,7 +1460,7 @@ impl<'a> Parser<'a> { let mut ts = vec![]; let mut last_comma = false; while self.token != token::CloseDelim(token::Paren) { - ts.push(self.parse_ty(true)); + ts.push(self.parse_ty_sum()); if self.token == token::Comma { last_comma = true; self.bump(); @@ -1465,7 +1484,7 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector), _ => self.obsolete(last_span, ObsoleteOwnedType) } - TyTup(vec![self.parse_ty(false)]) + TyTup(vec![self.parse_ty()]) } else if self.token == token::BinOp(token::Star) { // STAR POINTER (bare pointer?) self.bump(); @@ -1473,7 +1492,7 @@ impl<'a> Parser<'a> { } else if self.token == token::OpenDelim(token::Bracket) { // VECTOR self.expect(&token::OpenDelim(token::Bracket)); - let t = self.parse_ty(true); + let t = self.parse_ty_sum(); // Parse the `, ..e` in `[ int, ..e ]` // where `e` is a const expression @@ -1514,7 +1533,7 @@ impl<'a> Parser<'a> { } else if self.token == token::Lt { // QUALIFIED PATH `<TYPE as TRAIT_REF>::item` self.bump(); - let self_type = self.parse_ty(true); + let self_type = self.parse_ty_sum(); self.expect_keyword(keywords::As); let trait_ref = self.parse_trait_ref(); self.expect(&token::Gt); @@ -1529,7 +1548,7 @@ impl<'a> Parser<'a> { self.token.is_ident() || self.token.is_path() { // NAMED TYPE - self.parse_ty_path(plus_allowed) + self.parse_ty_path() } else if self.eat(&token::Underscore) { // TYPE TO BE INFERRED TyInfer @@ -1563,7 +1582,7 @@ impl<'a> Parser<'a> { known as `*const T`"); MutImmutable }; - let t = self.parse_ty(true); + let t = self.parse_ty(); MutTy { ty: t, mutbl: mutbl } } @@ -1603,7 +1622,7 @@ impl<'a> Parser<'a> { special_idents::invalid) }; - let t = self.parse_ty(true); + let t = self.parse_ty_sum(); Arg { ty: t, @@ -1621,7 +1640,7 @@ impl<'a> Parser<'a> { pub fn parse_fn_block_arg(&mut self) -> Arg { let pat = self.parse_pat(); let t = if self.eat(&token::Colon) { - self.parse_ty(true) + self.parse_ty_sum() } else { P(Ty { id: ast::DUMMY_NODE_ID, @@ -1739,7 +1758,7 @@ impl<'a> Parser<'a> { /// mode. The `mode` parameter determines whether lifetimes, types, and/or /// bounds are permitted and whether `::` must precede type parameter /// groups. - pub fn parse_path(&mut self, mode: PathParsingMode) -> PathAndBounds { + pub fn parse_path(&mut self, mode: PathParsingMode) -> ast::Path { // Check for a whole path... let found = match self.token { token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()), @@ -1747,10 +1766,7 @@ impl<'a> Parser<'a> { }; match found { Some(token::Interpolated(token::NtPath(box path))) => { - return PathAndBounds { - path: path, - bounds: None - } + return path; } _ => {} } @@ -1762,8 +1778,7 @@ impl<'a> Parser<'a> { // identifier followed by an optional lifetime and a set of types. // A bound set is a set of type parameter bounds. let segments = match mode { - LifetimeAndTypesWithoutColons | - LifetimeAndTypesAndBounds => { + LifetimeAndTypesWithoutColons => { self.parse_path_segments_without_colons() } LifetimeAndTypesWithColons => { @@ -1774,44 +1789,14 @@ impl<'a> Parser<'a> { } }; - // Next, parse a plus and bounded type parameters, if - // applicable. We need to remember whether the separate was - // present for later, because in some contexts it's a parse - // error. - let opt_bounds = { - if mode == LifetimeAndTypesAndBounds && - self.eat(&token::BinOp(token::Plus)) - { - let bounds = self.parse_ty_param_bounds(); - - // For some reason that I do not fully understand, we - // do not permit an empty list in the case where it is - // introduced by a `+`, but we do for `:` and other - // separators. -nmatsakis - if bounds.len() == 0 { - let last_span = self.last_span; - self.span_err(last_span, - "at least one type parameter bound \ - must be specified"); - } - - Some(bounds) - } else { - None - } - }; - // Assemble the span. let span = mk_sp(lo, self.last_span.hi); // Assemble the result. - PathAndBounds { - path: ast::Path { - span: span, - global: is_global, - segments: segments, - }, - bounds: opt_bounds, + ast::Path { + span: span, + global: is_global, + segments: segments, } } @@ -1837,10 +1822,10 @@ impl<'a> Parser<'a> { let inputs = self.parse_seq_to_end( &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), - |p| p.parse_ty(true)); + |p| p.parse_ty_sum()); let output_ty = if self.eat(&token::RArrow) { - Some(self.parse_ty(true)) + Some(self.parse_ty()) } else { None }; @@ -1963,11 +1948,9 @@ impl<'a> Parser<'a> { } } + /// Parses `lifetime_defs = [ lifetime_defs { ',' lifetime_defs } ]` where `lifetime_def = + /// lifetime [':' lifetimes]` pub fn parse_lifetime_defs(&mut self) -> Vec<ast::LifetimeDef> { - /*! - * Parses `lifetime_defs = [ lifetime_defs { ',' lifetime_defs } ]` - * where `lifetime_def = lifetime [':' lifetimes]` - */ let mut res = Vec::new(); loop { @@ -2003,16 +1986,13 @@ impl<'a> Parser<'a> { } } - // matches lifetimes = ( lifetime ) | ( lifetime , lifetimes ) - // actually, it matches the empty one too, but putting that in there - // messes up the grammar.... + /// matches lifetimes = ( lifetime ) | ( lifetime , lifetimes ) actually, it matches the empty + /// one too, but putting that in there messes up the grammar.... + /// + /// Parses zero or more comma separated lifetimes. Expects each lifetime to be followed by + /// either a comma or `>`. Used when parsing type parameter lists, where we expect something + /// like `<'a, 'b, T>`. pub fn parse_lifetimes(&mut self, sep: token::Token) -> Vec<ast::Lifetime> { - /*! - * Parses zero or more comma separated lifetimes. - * Expects each lifetime to be followed by either - * a comma or `>`. Used when parsing type parameter - * lists, where we expect something like `<'a, 'b, T>`. - */ let mut res = Vec::new(); loop { @@ -2327,7 +2307,7 @@ impl<'a> Parser<'a> { !self.token.is_keyword(keywords::True) && !self.token.is_keyword(keywords::False) { let pth = - self.parse_path(LifetimeAndTypesWithColons).path; + self.parse_path(LifetimeAndTypesWithColons); // `!`, as an operator, is prefix, so we know this isn't that if self.token == token::Not { @@ -2898,7 +2878,7 @@ impl<'a> Parser<'a> { } None => { if as_prec > min_prec && self.eat_keyword(keywords::As) { - let rhs = self.parse_ty(false); + let rhs = self.parse_ty(); let _as = self.mk_expr(lhs.span.lo, rhs.span.hi, ExprCast(lhs, rhs)); @@ -3362,8 +3342,7 @@ impl<'a> Parser<'a> { }) { self.bump(); let end = if self.token.is_ident() || self.token.is_path() { - let path = self.parse_path(LifetimeAndTypesWithColons) - .path; + let path = self.parse_path(LifetimeAndTypesWithColons); let hi = self.span.hi; self.mk_expr(lo, hi, ExprPath(path)) } else { @@ -3433,8 +3412,7 @@ impl<'a> Parser<'a> { } } else { // parse an enum pat - let enum_path = self.parse_path(LifetimeAndTypesWithColons) - .path; + let enum_path = self.parse_path(LifetimeAndTypesWithColons); match self.token { token::OpenDelim(token::Brace) => { self.bump(); @@ -3548,7 +3526,7 @@ impl<'a> Parser<'a> { span: mk_sp(lo, lo), }); if self.eat(&token::Colon) { - ty = self.parse_ty(true); + ty = self.parse_ty_sum(); } let init = self.parse_initializer(); P(ast::Local { @@ -3577,7 +3555,7 @@ impl<'a> Parser<'a> { } let name = self.parse_ident(); self.expect(&token::Colon); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); spanned(lo, self.last_span.hi, ast::StructField_ { kind: NamedField(name, pr), id: ast::DUMMY_NODE_ID, @@ -3624,7 +3602,7 @@ impl<'a> Parser<'a> { // Potential trouble: if we allow macros with paths instead of // idents, we'd need to look ahead past the whole path here... - let pth = self.parse_path(NoTypesAllowed).path; + let pth = self.parse_path(NoTypesAllowed); self.bump(); let id = match self.token { @@ -3976,7 +3954,7 @@ impl<'a> Parser<'a> { let default = if self.token == token::Eq { self.bump(); - Some(self.parse_ty(true)) + Some(self.parse_ty_sum()) } else { None }; @@ -4032,7 +4010,7 @@ impl<'a> Parser<'a> { Some(token::Comma), |p| { p.forbid_lifetime(); - p.parse_ty(true) + p.parse_ty_sum() } ); (lifetimes, result.into_vec()) @@ -4265,7 +4243,7 @@ impl<'a> Parser<'a> { // Determine whether this is the fully explicit form, `self: // TYPE`. if self.eat(&token::Colon) { - SelfExplicit(self.parse_ty(false), self_ident) + SelfExplicit(self.parse_ty_sum(), self_ident) } else { SelfValue(self_ident) } @@ -4277,7 +4255,7 @@ impl<'a> Parser<'a> { // Determine whether this is the fully explicit form, // `self: TYPE`. if self.eat(&token::Colon) { - SelfExplicit(self.parse_ty(false), self_ident) + SelfExplicit(self.parse_ty_sum(), self_ident) } else { SelfValue(self_ident) } @@ -4466,7 +4444,7 @@ impl<'a> Parser<'a> { && (self.look_ahead(2, |t| *t == token::OpenDelim(token::Paren)) || self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace))) { // method macro. - let pth = self.parse_path(NoTypesAllowed).path; + let pth = self.parse_path(NoTypesAllowed); self.expect(&token::Not); // eat a matched-delimiter token tree: @@ -4564,30 +4542,25 @@ impl<'a> Parser<'a> { let could_be_trait = self.token != token::OpenDelim(token::Paren); // Parse the trait. - let mut ty = self.parse_ty(true); + let mut ty = self.parse_ty_sum(); // Parse traits, if necessary. let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) { // New-style trait. Reinterpret the type as a trait. let opt_trait_ref = match ty.node { - TyPath(ref path, None, node_id) => { + TyPath(ref path, node_id) => { Some(TraitRef { path: (*path).clone(), ref_id: node_id, }) } - TyPath(_, Some(_), _) => { - self.span_err(ty.span, - "bounded traits are only valid in type position"); - None - } _ => { self.span_err(ty.span, "not a trait"); None } }; - ty = self.parse_ty(true); + ty = self.parse_ty_sum(); opt_trait_ref } else { None @@ -4606,7 +4579,7 @@ impl<'a> Parser<'a> { /// Parse a::B<String,int> fn parse_trait_ref(&mut self) -> TraitRef { ast::TraitRef { - path: self.parse_path(LifetimeAndTypesWithoutColons).path, + path: self.parse_path(LifetimeAndTypesWithoutColons), ref_id: ast::DUMMY_NODE_ID, } } @@ -4638,7 +4611,7 @@ impl<'a> Parser<'a> { let mut generics = self.parse_generics(); if self.eat(&token::Colon) { - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); self.span_err(ty.span, "`virtual` structs have been removed from the language"); } @@ -4673,7 +4646,7 @@ impl<'a> Parser<'a> { let struct_field_ = ast::StructField_ { kind: UnnamedField(p.parse_visibility()), id: ast::DUMMY_NODE_ID, - ty: p.parse_ty(true), + ty: p.parse_ty_sum(), attrs: attrs, }; spanned(lo, p.span.hi, struct_field_) @@ -4830,7 +4803,7 @@ impl<'a> Parser<'a> { fn parse_item_const(&mut self, m: Option<Mutability>) -> ItemInfo { let id = self.parse_ident(); self.expect(&token::Colon); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); self.expect(&token::Eq); let e = self.parse_expr(); self.commit_expr_expecting(&*e, token::Semi); @@ -5023,7 +4996,7 @@ impl<'a> Parser<'a> { let ident = self.parse_ident(); self.expect(&token::Colon); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); let hi = self.span.hi; self.expect(&token::Semi); P(ForeignItem { @@ -5181,7 +5154,7 @@ impl<'a> Parser<'a> { let mut tps = self.parse_generics(); self.parse_where_clause(&mut tps); self.expect(&token::Eq); - let ty = self.parse_ty(true); + let ty = self.parse_ty_sum(); self.expect(&token::Semi); (ident, ItemTy(ty, tps), None) } @@ -5235,7 +5208,7 @@ impl<'a> Parser<'a> { &token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), seq_sep_trailing_allowed(token::Comma), - |p| p.parse_ty(true) + |p| p.parse_ty_sum() ); for ty in arg_tys.into_iter() { args.push(ast::VariantArg { @@ -5593,7 +5566,7 @@ impl<'a> Parser<'a> { // MACRO INVOCATION ITEM // item macro. - let pth = self.parse_path(NoTypesAllowed).path; + let pth = self.parse_path(NoTypesAllowed); self.expect(&token::Not); // a 'special' identifier (like what `macro_rules!` uses) diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 3a3407aedba..583ace977fe 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -421,13 +421,11 @@ macro_rules! declare_special_idents_and_keywords {( )* } - /** - * All the valid words that have meaning in the Rust language. - * - * Rust keywords are either 'strict' or 'reserved'. Strict keywords may not - * appear as identifiers at all. Reserved keywords are not used anywhere in - * the language and may not appear as identifiers. - */ + /// All the valid words that have meaning in the Rust language. + /// + /// Rust keywords are either 'strict' or 'reserved'. Strict keywords may not + /// appear as identifiers at all. Reserved keywords are not used anywhere in + /// the language and may not appear as identifiers. pub mod keywords { pub use self::Keyword::*; use ast; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 6960337c3e2..c12c3098279 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -61,7 +61,7 @@ pub struct State<'a> { literals: Option<Vec<comments::Literal> >, cur_cmnt_and_lit: CurrentCommentAndLiteral, boxes: Vec<pp::Breaks>, - ann: &'a PpAnn+'a, + ann: &'a (PpAnn+'a), encode_idents_with_hygiene: bool, } @@ -293,6 +293,10 @@ 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 pat_to_string(pat: &ast::Pat) -> String { $to_string(|s| s.print_pat(pat)) } @@ -739,11 +743,15 @@ impl<'a> State<'a> { Some(&generics), None)); } - ast::TyPath(ref path, ref bounds, _) => { - try!(self.print_bounded_path(path, bounds)); + ast::TyPath(ref path, _) => { + try!(self.print_path(path, false)); + } + ast::TyObjectSum(ref ty, ref bounds) => { + try!(self.print_type(&**ty)); + try!(self.print_bounds("+", bounds.as_slice())); } ast::TyPolyTraitRef(ref bounds) => { - try!(self.print_bounds("", bounds)); + try!(self.print_bounds("", bounds.as_slice())); } ast::TyQPath(ref qpath) => { try!(word(&mut self.s, "<")); @@ -970,7 +978,7 @@ impl<'a> State<'a> { } _ => {} } - try!(self.print_bounds(":", bounds)); + try!(self.print_bounds(":", bounds.as_slice())); try!(self.print_where_clause(generics)); try!(word(&mut self.s, " ")); try!(self.bopen()); @@ -1908,11 +1916,11 @@ impl<'a> State<'a> { self.print_expr(coll) } - fn print_path_(&mut self, - path: &ast::Path, - colons_before_params: bool, - opt_bounds: &Option<OwnedSlice<ast::TyParamBound>>) - -> IoResult<()> { + fn print_path(&mut self, + path: &ast::Path, + colons_before_params: bool) + -> IoResult<()> + { try!(self.maybe_print_comment(path.span.lo)); if path.global { try!(word(&mut self.s, "::")); @@ -1931,10 +1939,7 @@ impl<'a> State<'a> { try!(self.print_path_parameters(&segment.parameters, colons_before_params)); } - match *opt_bounds { - None => Ok(()), - Some(ref bounds) => self.print_bounds("+", bounds) - } + Ok(()) } fn print_path_parameters(&mut self, @@ -1997,17 +2002,6 @@ impl<'a> State<'a> { Ok(()) } - fn print_path(&mut self, path: &ast::Path, - colons_before_params: bool) -> IoResult<()> { - self.print_path_(path, colons_before_params, &None) - } - - fn print_bounded_path(&mut self, path: &ast::Path, - bounds: &Option<OwnedSlice<ast::TyParamBound>>) - -> IoResult<()> { - self.print_path_(path, false, bounds) - } - pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> { try!(self.maybe_print_comment(pat.span.lo)); try!(self.ann.pre(self, NodePat(pat))); @@ -2329,7 +2323,7 @@ impl<'a> State<'a> { pub fn print_bounds(&mut self, prefix: &str, - bounds: &OwnedSlice<ast::TyParamBound>) + bounds: &[ast::TyParamBound]) -> IoResult<()> { if !bounds.is_empty() { try!(word(&mut self.s, prefix)); @@ -2400,7 +2394,7 @@ impl<'a> State<'a> { s.print_lifetime_def(lifetime) } else { let idx = idx - generics.lifetimes.len(); - let param = generics.ty_params.get(idx); + let param = &generics.ty_params[idx]; s.print_ty_param(param) } })); @@ -2418,7 +2412,7 @@ impl<'a> State<'a> { _ => {} } try!(self.print_ident(param.ident)); - try!(self.print_bounds(":", ¶m.bounds)); + try!(self.print_bounds(":", param.bounds.as_slice())); match param.default { Some(ref default) => { try!(space(&mut self.s)); @@ -2447,7 +2441,7 @@ impl<'a> State<'a> { } try!(self.print_ident(predicate.ident)); - try!(self.print_bounds(":", &predicate.bounds)); + try!(self.print_bounds(":", predicate.bounds.as_slice())); } Ok(()) @@ -2664,7 +2658,7 @@ impl<'a> State<'a> { try!(self.pclose()); } - try!(self.print_bounds(":", bounds)); + try!(self.print_bounds(":", bounds.as_slice())); try!(self.print_fn_output(decl)); diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index f21a3185d6d..05828fc05f8 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -482,8 +482,7 @@ fn mk_tests(cx: &TestCtxt) -> P<ast::Item> { let ecx = &cx.ext_cx; let struct_type = ecx.ty_path(ecx.path(sp, vec![ecx.ident_of("self"), ecx.ident_of("test"), - ecx.ident_of("TestDescAndFn")]), - None); + ecx.ident_of("TestDescAndFn")])); let static_lt = ecx.lifetime(sp, token::special_idents::static_lifetime.name); // &'static [self::test::TestDescAndFn] let static_type = ecx.ty_rptr(sp, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 3f87dbc0740..1385fb982e5 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -92,14 +92,12 @@ pub trait Visitor<'v> { } fn visit_struct_field(&mut self, s: &'v StructField) { walk_struct_field(self, s) } fn visit_variant(&mut self, v: &'v Variant, g: &'v Generics) { walk_variant(self, v, g) } + + /// Visits an optional reference to a lifetime. The `span` is the span of some surrounding + /// reference should opt_lifetime be None. fn visit_opt_lifetime_ref(&mut self, _span: Span, opt_lifetime: &'v Option<Lifetime>) { - /*! - * Visits an optional reference to a lifetime. The `span` is - * the span of some surrounding reference should opt_lifetime - * be None. - */ match *opt_lifetime { Some(ref l) => self.visit_lifetime_ref(l), None => () @@ -404,14 +402,12 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { walk_fn_ret_ty(visitor, &function_declaration.decl.output); walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); } - TyPath(ref path, ref opt_bounds, id) => { + TyPath(ref path, id) => { visitor.visit_path(path, id); - match *opt_bounds { - Some(ref bounds) => { - walk_ty_param_bounds_helper(visitor, bounds); - } - None => { } - } + } + TyObjectSum(ref ty, ref bounds) => { + visitor.visit_ty(&**ty); + walk_ty_param_bounds_helper(visitor, bounds); } TyQPath(ref qpath) => { visitor.visit_ty(&*qpath.self_type); |
