diff options
| author | Johannes Hoff <johshoff@gmail.com> | 2014-12-24 13:22:11 +0100 |
|---|---|---|
| committer | Johannes Hoff <johshoff@gmail.com> | 2014-12-24 13:22:11 +0100 |
| commit | 0128159c95d0544e0c30b8b52ce3e7ce348fc114 (patch) | |
| tree | 8af4db0f2758f86434b895169122a9962fb79b21 /src/libsyntax | |
| parent | 8f827d33cab1be648120fc8ac34651d9cc079b5e (diff) | |
| parent | e64a8193b02ce72ef183274994a25eae281cb89c (diff) | |
| download | rust-0128159c95d0544e0c30b8b52ce3e7ce348fc114.tar.gz rust-0128159c95d0544e0c30b8b52ce3e7ce348fc114.zip | |
Merge branch 'master' into cfg_tmp_dir
Conflicts: src/etc/rustup.sh
Diffstat (limited to 'src/libsyntax')
63 files changed, 3044 insertions, 2374 deletions
diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 87693f39bbd..b1599cb807d 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -15,11 +15,18 @@ pub use self::AbiArchitecture::*; use std::fmt; -#[deriving(PartialEq)] -pub enum Os { OsWindows, OsMacos, OsLinux, OsAndroid, OsFreebsd, OsiOS, - OsDragonfly } +#[deriving(Copy, PartialEq)] +pub enum Os { + OsWindows, + OsMacos, + OsLinux, + OsAndroid, + OsFreebsd, + OsiOS, + OsDragonfly, +} -#[deriving(PartialEq, Eq, Hash, Encodable, Decodable, Clone)] +#[deriving(PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Clone, Copy)] pub enum Abi { // NB: This ordering MUST match the AbiDatas array below. // (This is ensured by the test indices_are_correct().) @@ -40,7 +47,7 @@ pub enum Abi { } #[allow(non_camel_case_types)] -#[deriving(PartialEq)] +#[deriving(Copy, PartialEq)] pub enum Architecture { X86, X86_64, @@ -49,6 +56,7 @@ pub enum Architecture { Mipsel } +#[deriving(Copy)] pub struct AbiData { abi: Abi, @@ -56,6 +64,7 @@ pub struct AbiData { name: &'static str, } +#[deriving(Copy)] pub enum AbiArchitecture { /// Not a real ABI (e.g., intrinsic) RustArch, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 5d4fd2704a2..0c8c17b080b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -20,7 +20,6 @@ pub use self::Decl_::*; pub use self::ExplicitSelf_::*; pub use self::Expr_::*; pub use self::FloatTy::*; -pub use self::FnStyle::*; pub use self::FunctionRetTy::*; pub use self::ForeignItem_::*; pub use self::ImplItem::*; @@ -32,7 +31,7 @@ pub use self::Lit_::*; pub use self::LitIntType::*; pub use self::LocalSource::*; pub use self::Mac_::*; -pub use self::MatchSource::*; +pub use self::MacStmtStyle::*; pub use self::MetaItem_::*; pub use self::Method_::*; pub use self::Mutability::*; @@ -80,7 +79,7 @@ use serialize::{Encodable, Decodable, Encoder, Decoder}; /// table) and a SyntaxContext to track renaming and /// macro expansion per Flatt et al., "Macros /// That Work Together" -#[deriving(Clone, Hash, PartialOrd, Eq, Ord)] +#[deriving(Clone, Copy, Hash, PartialOrd, Eq, Ord)] pub struct Ident { pub name: Name, pub ctxt: SyntaxContext @@ -158,7 +157,8 @@ pub const ILLEGAL_CTXT : SyntaxContext = 1; /// A name is a part of an identifier, representing a string or gensym. It's /// the result of interning. -#[deriving(Eq, Ord, PartialEq, PartialOrd, Hash, Encodable, Decodable, Clone)] +#[deriving(Eq, Ord, PartialEq, PartialOrd, Hash, + RustcEncodable, RustcDecodable, Clone, Copy)] pub struct Name(pub u32); impl Name { @@ -188,23 +188,24 @@ impl<S: Encoder<E>, E> Encodable<S, E> for Ident { } } -impl<D:Decoder<E>, E> Decodable<D, E> for Ident { +impl<D: Decoder<E>, E> Decodable<D, E> for Ident { fn decode(d: &mut D) -> Result<Ident, E> { - Ok(str_to_ident(try!(d.read_str()).as_slice())) + Ok(str_to_ident(try!(d.read_str())[])) } } /// Function name (not all functions have names) pub type FnIdent = Option<Ident>; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, + Show, Copy)] pub struct Lifetime { pub id: NodeId, pub span: Span, pub name: Name } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct LifetimeDef { pub lifetime: Lifetime, pub bounds: Vec<Lifetime> @@ -213,7 +214,7 @@ pub struct LifetimeDef { /// A "Path" is essentially Rust's notion of a name; for instance: /// std::cmp::PartialEq . It's represented as a sequence of identifiers, /// along with a bunch of supporting information. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Path { pub span: Span, /// A `::foo` path, is relative to the crate root rather than current @@ -225,7 +226,7 @@ pub struct Path { /// A segment of a path: an identifier, an optional lifetime, and a set of /// types. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct PathSegment { /// The identifier portion of this path segment. pub identifier: Ident, @@ -238,7 +239,7 @@ pub struct PathSegment { pub parameters: PathParameters, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum PathParameters { AngleBracketedParameters(AngleBracketedParameterData), ParenthesizedParameters(ParenthesizedParameterData), @@ -249,6 +250,7 @@ impl PathParameters { AngleBracketedParameters(AngleBracketedParameterData { lifetimes: Vec::new(), types: OwnedSlice::empty(), + bindings: OwnedSlice::empty(), }) } @@ -276,11 +278,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() @@ -303,25 +303,39 @@ impl PathParameters { } } } + + pub fn bindings(&self) -> Vec<&P<TypeBinding>> { + match *self { + AngleBracketedParameters(ref data) => { + data.bindings.iter().collect() + } + ParenthesizedParameters(_) => { + Vec::new() + } + } + } } /// A path like `Foo<'a, T>` -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, 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>>, + /// Bindings (equality constraints) on associated types, if present. + /// E.g., `Foo<A=Bar>`. + pub bindings: OwnedSlice<P<TypeBinding>>, } impl AngleBracketedParameterData { fn is_empty(&self) -> bool { - self.lifetimes.is_empty() && self.types.is_empty() + self.lifetimes.is_empty() && self.types.is_empty() && self.bindings.is_empty() } } /// A path like `Foo(A,B) -> C` -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct ParenthesizedParameterData { /// `(A,B)` pub inputs: Vec<P<Ty>>, @@ -334,7 +348,8 @@ pub type CrateNum = u32; pub type NodeId = u32; -#[deriving(Clone, Eq, Ord, PartialOrd, PartialEq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable, + RustcDecodable, Hash, Show, Copy)] pub struct DefId { pub krate: CrateNum, pub node: NodeId, @@ -354,7 +369,7 @@ pub const DUMMY_NODE_ID: NodeId = -1; /// typeck::collect::compute_bounds matches these against /// the "special" built-in traits (see middle::lang_items) and /// detects Copy, Send and Sync. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum TyParamBound { TraitTyParamBound(PolyTraitRef), RegionTyParamBound(Lifetime) @@ -362,7 +377,7 @@ pub enum TyParamBound { pub type TyParamBounds = OwnedSlice<TyParamBound>; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct TyParam { pub ident: Ident, pub id: NodeId, @@ -374,7 +389,7 @@ pub struct TyParam { /// Represents lifetimes and type parameters attached to a declaration /// of a function, enum, trait, etc. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Generics { pub lifetimes: Vec<LifetimeDef>, pub ty_params: OwnedSlice<TyParam>, @@ -393,25 +408,46 @@ impl Generics { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct WhereClause { pub id: NodeId, pub predicates: Vec<WherePredicate>, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] -pub struct WherePredicate { - pub id: NodeId, +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] +pub enum WherePredicate { + BoundPredicate(WhereBoundPredicate), + RegionPredicate(WhereRegionPredicate), + EqPredicate(WhereEqPredicate) +} + +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] +pub struct WhereBoundPredicate { pub span: Span, - pub ident: Ident, + pub bounded_ty: P<Ty>, pub bounds: OwnedSlice<TyParamBound>, } +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] +pub struct WhereRegionPredicate { + pub span: Span, + pub lifetime: Lifetime, + pub bounds: Vec<Lifetime>, +} + +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] +pub struct WhereEqPredicate { + pub id: NodeId, + pub span: Span, + pub path: Path, + pub ty: P<Ty>, +} + /// The set of MetaItems that define the compilation environment of the crate, /// used to drive conditional compilation pub type CrateConfig = Vec<P<MetaItem>> ; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Crate { pub module: Mod, pub attrs: Vec<Attribute>, @@ -422,7 +458,7 @@ pub struct Crate { pub type MetaItem = Spanned<MetaItem_>; -#[deriving(Clone, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum MetaItem_ { MetaWord(InternedString), MetaList(InternedString, Vec<P<MetaItem>>), @@ -454,7 +490,7 @@ impl PartialEq for MetaItem_ { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Block { pub view_items: Vec<ViewItem>, pub stmts: Vec<P<Stmt>>, @@ -464,27 +500,27 @@ pub struct Block { pub span: Span, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Pat { pub id: NodeId, pub node: Pat_, pub span: Span, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct FieldPat { pub ident: Ident, pub pat: P<Pat>, pub is_shorthand: bool, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum BindingMode { BindByRef(Mutability), BindByValue(Mutability), } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum PatWildKind { /// Represents the wildcard pattern `_` PatWildSingle, @@ -493,7 +529,7 @@ pub enum PatWildKind { PatWildMulti, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum Pat_ { /// Represents a wildcard pattern (either `_` or `..`) PatWild(PatWildKind), @@ -522,13 +558,13 @@ pub enum Pat_ { PatMac(Mac), } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum Mutability { MutMutable, MutImmutable, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum BinOp { BiAdd, BiSub, @@ -550,7 +586,7 @@ pub enum BinOp { BiGt, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum UnOp { UnUniq, UnDeref, @@ -560,7 +596,7 @@ pub enum UnOp { pub type Stmt = Spanned<Stmt_>; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum Stmt_ { /// Could be an item or a local (let) binding: StmtDecl(P<Decl>, NodeId), @@ -571,13 +607,25 @@ pub enum Stmt_ { /// Expr with trailing semi-colon (may have any type): StmtSemi(P<Expr>, NodeId), - /// bool: is there a trailing semi-colon? - StmtMac(Mac, bool), + StmtMac(Mac, MacStmtStyle), +} + +#[deriving(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] +pub enum MacStmtStyle { + /// The macro statement had a trailing semicolon, e.g. `foo! { ... };` + /// `foo!(...);`, `foo![...];` + MacStmtWithSemicolon, + /// The macro statement had braces; e.g. foo! { ... } + MacStmtWithBraces, + /// The macro statement had parentheses or brackets and no semicolon; e.g. + /// `foo!(...)`. All of these will end up being converted into macro + /// expressions. + MacStmtWithoutBraces, } /// Where a local declaration came from: either a true `let ... = /// ...;`, or one desugared from the pattern of a for loop. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum LocalSource { LocalLet, LocalFor, @@ -586,7 +634,7 @@ pub enum LocalSource { // FIXME (pending discussion of #1697, #2178...): local should really be // a refinement on pat. /// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;` -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Local { pub ty: P<Ty>, pub pat: P<Pat>, @@ -598,7 +646,7 @@ pub struct Local { pub type Decl = Spanned<Decl_>; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum Decl_ { /// A local (let) binding: DeclLocal(P<Local>), @@ -607,7 +655,7 @@ pub enum Decl_ { } /// represents one arm of a 'match' -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Arm { pub attrs: Vec<Attribute>, pub pats: Vec<P<Pat>>, @@ -615,7 +663,7 @@ pub struct Arm { pub body: P<Expr>, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Field { pub ident: SpannedIdent, pub expr: P<Expr>, @@ -624,29 +672,29 @@ pub struct Field { pub type SpannedIdent = Spanned<Ident>; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum BlockCheckMode { DefaultBlock, UnsafeBlock(UnsafeSource), } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum UnsafeSource { CompilerGenerated, UserProvided, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Expr { pub id: NodeId, pub node: Expr_, pub span: Span, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum Expr_ { /// First expr is the place; second expr is the value. - ExprBox(P<Expr>, P<Expr>), + ExprBox(Option<P<Expr>>, P<Expr>), ExprVec(Vec<P<Expr>>), ExprCall(P<Expr>, Vec<P<Expr>>), ExprMethodCall(SpannedIdent, Vec<P<Ty>>, Vec<P<Expr>>), @@ -668,15 +716,15 @@ pub enum Expr_ { ExprLoop(P<Block>, Option<Ident>), ExprMatch(P<Expr>, Vec<Arm>, MatchSource), ExprClosure(CaptureClause, Option<UnboxedClosureKind>, P<FnDecl>, P<Block>), - ExprProc(P<FnDecl>, P<Block>), ExprBlock(P<Block>), ExprAssign(P<Expr>, P<Expr>), ExprAssignOp(BinOp, P<Expr>, P<Expr>), - ExprField(P<Expr>, SpannedIdent, Vec<P<Ty>>), - ExprTupField(P<Expr>, Spanned<uint>, Vec<P<Ty>>), + ExprField(P<Expr>, SpannedIdent), + ExprTupField(P<Expr>, Spanned<uint>), ExprIndex(P<Expr>, P<Expr>), ExprSlice(P<Expr>, Option<P<Expr>>, Option<P<Expr>>, Mutability), + ExprRange(P<Expr>, Option<P<Expr>>), /// Variable reference, possibly containing `::` and/or /// type parameters, e.g. foo::bar::<baz> @@ -706,28 +754,28 @@ pub enum Expr_ { /// <Vec<T> as SomeTrait>::SomeAssociatedItem /// ^~~~~ ^~~~~~~~~ ^~~~~~~~~~~~~~~~~~ /// self_type trait_name item_name -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct QPath { pub self_type: P<Ty>, pub trait_ref: P<TraitRef>, pub item_name: Ident, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum MatchSource { - MatchNormal, - MatchIfLetDesugar, - MatchWhileLetDesugar, + Normal, + IfLetDesugar { contains_else_clause: bool }, + WhileLetDesugar, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum CaptureClause { CaptureByValue, CaptureByRef, } /// A delimited sequence of token trees -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Delimited { /// The type of delimiter pub delim: token::DelimToken, @@ -762,7 +810,7 @@ impl Delimited { } /// A sequence of token treesee -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct SequenceRepetition { /// The sequence of token trees pub tts: Vec<TokenTree>, @@ -776,7 +824,7 @@ pub struct SequenceRepetition { /// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star) /// for token sequences. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum KleeneOp { ZeroOrMore, OneOrMore, @@ -794,7 +842,7 @@ pub enum KleeneOp { /// /// The RHS of an MBE macro is the only place `SubstNt`s are substituted. /// Nothing special happens to misnamed or misplaced `SubstNt`s. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] #[doc="For macro invocations; parsing is delegated to the macro"] pub enum TokenTree { /// A single token @@ -884,14 +932,14 @@ pub type Mac = Spanned<Mac_>; /// is being invoked, and the vector of token-trees contains the source /// of the macro invocation. /// There's only one flavor, now, so this could presumably be simplified. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum Mac_ { // NB: the additional ident for a macro_rules-style macro is actually // stored in the enclosing item. Oog. MacInvocTT(Path, Vec<TokenTree> , SyntaxContext), // new macro-invocation } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum StrStyle { CookedStr, RawStr(uint) @@ -899,13 +947,13 @@ pub enum StrStyle { pub type Lit = Spanned<Lit_>; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum Sign { Minus, Plus } -impl<T: Int> Sign { +impl<T> Sign where T: Int { pub fn new(n: T) -> Sign { if n < Int::zero() { Minus @@ -915,7 +963,7 @@ impl<T: Int> Sign { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum LitIntType { SignedIntLit(IntTy, Sign), UnsignedIntLit(UintTy), @@ -932,7 +980,7 @@ impl LitIntType { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum Lit_ { LitStr(InternedString, StrStyle), LitBinary(Rc<Vec<u8> >), @@ -946,13 +994,13 @@ pub enum Lit_ { // NB: If you change this, you'll probably want to change the corresponding // type structure in middle/ty.rs as well. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct MutTy { pub ty: P<Ty>, pub mutbl: Mutability, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct TypeField { pub ident: Ident, pub mt: MutTy, @@ -961,11 +1009,11 @@ pub struct TypeField { /// Represents a required method in a trait declaration, /// one without a default implementation -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct TypeMethod { pub ident: Ident, pub attrs: Vec<Attribute>, - pub fn_style: FnStyle, + pub unsafety: Unsafety, pub abi: Abi, pub decl: P<FnDecl>, pub generics: Generics, @@ -979,26 +1027,26 @@ pub struct TypeMethod { /// a default implementation A trait method is either required (meaning it /// doesn't have an implementation, just a signature) or provided (meaning it /// has a default implementation). -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum TraitItem { RequiredMethod(TypeMethod), ProvidedMethod(P<Method>), TypeTraitItem(P<AssociatedType>), } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum ImplItem { MethodImplItem(P<Method>), TypeImplItem(P<Typedef>), } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct AssociatedType { pub attrs: Vec<Attribute>, pub ty_param: TyParam, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Typedef { pub id: NodeId, pub span: Span, @@ -1008,7 +1056,7 @@ pub struct Typedef { pub typ: P<Ty>, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] pub enum IntTy { TyI, TyI8, @@ -1033,7 +1081,7 @@ impl IntTy { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] pub enum UintTy { TyU, TyU8, @@ -1058,7 +1106,7 @@ impl fmt::Show for UintTy { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] pub enum FloatTy { TyF32, TyF64, @@ -1078,8 +1126,18 @@ impl FloatTy { } } +// Bind a type to an associated type: `A=Foo`. +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] +pub struct TypeBinding { + pub id: NodeId, + pub ident: Ident, + pub ty: P<Ty>, + pub span: Span, +} + + // NB PartialEq method appears below. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Ty { pub id: NodeId, pub node: Ty_, @@ -1087,7 +1145,7 @@ pub struct Ty { } /// Not represented directly in the AST, referred to by name through a ty_path. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum PrimTy { TyInt(IntTy), TyUint(UintTy), @@ -1097,7 +1155,7 @@ pub enum PrimTy { TyChar } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] pub enum Onceness { Once, Many @@ -1113,24 +1171,24 @@ impl fmt::Show for Onceness { } /// Represents the type of a closure -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct ClosureTy { pub lifetimes: Vec<LifetimeDef>, - pub fn_style: FnStyle, + pub unsafety: Unsafety, pub onceness: Onceness, pub decl: P<FnDecl>, pub bounds: TyParamBounds, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct BareFnTy { - pub fn_style: FnStyle, + pub unsafety: Unsafety, pub abi: Abi, pub lifetimes: Vec<LifetimeDef>, pub decl: P<FnDecl> } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] /// The different kinds of types recognized by the compiler pub enum Ty_ { TyVec(P<Ty>), @@ -1142,8 +1200,6 @@ pub enum Ty_ { TyRptr(Option<Lifetime>, MutTy), /// A closure (e.g. `|uint| -> bool`) TyClosure(P<ClosureTy>), - /// A procedure (e.g `proc(uint) -> bool`) - TyProc(P<ClosureTy>), /// A bare function (e.g. `fn(uint) -> bool`) TyBareFn(P<BareFnTy>), /// A tuple (`(A, B, C, D,...)`) @@ -1151,7 +1207,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` @@ -1165,19 +1223,19 @@ pub enum Ty_ { TyInfer, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum AsmDialect { AsmAtt, AsmIntel } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct InlineAsm { pub asm: InternedString, pub asm_str_style: StrStyle, pub outputs: Vec<(InternedString, P<Expr>, bool)>, pub inputs: Vec<(InternedString, P<Expr>)>, - pub clobbers: InternedString, + pub clobbers: Vec<InternedString>, pub volatile: bool, pub alignstack: bool, pub dialect: AsmDialect, @@ -1185,7 +1243,7 @@ pub struct InlineAsm { } /// represents an argument in a function header -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Arg { pub ty: P<Ty>, pub pat: P<Pat>, @@ -1213,31 +1271,29 @@ impl Arg { } /// represents the header (not the body) of a function declaration -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct FnDecl { pub inputs: Vec<Arg>, pub output: FunctionRetTy, pub variadic: bool } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)] -pub enum FnStyle { - /// Declared with "unsafe fn" - UnsafeFn, - /// Declared with "fn" - NormalFn, +#[deriving(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] +pub enum Unsafety { + Unsafe, + Normal, } -impl fmt::Show for FnStyle { +impl fmt::Show for Unsafety { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - NormalFn => "normal".fmt(f), - UnsafeFn => "unsafe".fmt(f), + Unsafety::Normal => "normal".fmt(f), + Unsafety::Unsafe => "unsafe".fmt(f), } } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum FunctionRetTy { /// Functions with return type ! that always /// raise an error or exit (i.e. never return to the caller) @@ -1256,7 +1312,7 @@ impl FunctionRetTy { } /// Represents the kind of 'self' associated with a method -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum ExplicitSelf_ { /// No self SelfStatic, @@ -1270,7 +1326,7 @@ pub enum ExplicitSelf_ { pub type ExplicitSelf = Spanned<ExplicitSelf_>; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Method { pub attrs: Vec<Attribute>, pub id: NodeId, @@ -1278,14 +1334,14 @@ pub struct Method { pub node: Method_, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum Method_ { /// Represents a method declaration MethDecl(Ident, Generics, Abi, ExplicitSelf, - FnStyle, + Unsafety, P<FnDecl>, P<Block>, Visibility), @@ -1293,7 +1349,7 @@ pub enum Method_ { MethMac(Mac), } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Mod { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token @@ -1303,31 +1359,31 @@ pub struct Mod { pub items: Vec<P<Item>>, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct ForeignMod { pub abi: Abi, pub view_items: Vec<ViewItem>, pub items: Vec<P<ForeignItem>>, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct VariantArg { pub ty: P<Ty>, pub id: NodeId, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum VariantKind { TupleVariantKind(Vec<VariantArg>), StructVariantKind(P<StructDef>), } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct EnumDef { pub variants: Vec<P<Variant>>, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Variant_ { pub name: Ident, pub attrs: Vec<Attribute>, @@ -1339,7 +1395,7 @@ pub struct Variant_ { pub type Variant = Spanned<Variant_>; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum PathListItem_ { PathListIdent { name: Ident, id: NodeId }, PathListMod { id: NodeId } @@ -1357,7 +1413,7 @@ pub type PathListItem = Spanned<PathListItem_>; pub type ViewPath = Spanned<ViewPath_>; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum ViewPath_ { /// `foo::bar::baz as quux` @@ -1374,7 +1430,7 @@ pub enum ViewPath_ { ViewPathList(Path, Vec<PathListItem> , NodeId) } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct ViewItem { pub node: ViewItem_, pub attrs: Vec<Attribute>, @@ -1382,7 +1438,7 @@ pub struct ViewItem { pub span: Span, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum ViewItem_ { /// Ident: name used to refer to this crate in the code /// optional (InternedString,StrStyle): if present, this is a location @@ -1398,17 +1454,17 @@ pub type Attribute = Spanned<Attribute_>; /// Distinguishes between Attributes that decorate items and Attributes that /// are contained as statements within items. These two cases need to be /// distinguished for pretty-printing. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum AttrStyle { AttrOuter, AttrInner, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub struct AttrId(pub uint); /// Doc-comments are promoted to attributes that have is_sugared_doc = true -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Attribute_ { pub id: AttrId, pub style: AttrStyle, @@ -1421,13 +1477,13 @@ pub struct Attribute_ { /// that the ref_id is for. The impl_id maps to the "self type" of this impl. /// If this impl is an ItemImpl, the impl_id is redundant (it could be the /// same as the impl's node id). -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct TraitRef { pub path: Path, pub ref_id: NodeId, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct PolyTraitRef { /// The `'a` in `<'a> Foo<&'a T>` pub bound_lifetimes: Vec<LifetimeDef>, @@ -1436,7 +1492,7 @@ pub struct PolyTraitRef { pub trait_ref: TraitRef } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum Visibility { Public, Inherited, @@ -1451,7 +1507,7 @@ impl Visibility { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct StructField_ { pub kind: StructFieldKind, pub id: NodeId, @@ -1470,7 +1526,7 @@ impl StructField_ { pub type StructField = Spanned<StructField_>; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum StructFieldKind { NamedField(Ident, Visibility), /// Element of a tuple-like struct @@ -1486,7 +1542,7 @@ impl StructFieldKind { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct StructDef { /// Fields, not including ctor pub fields: Vec<StructField>, @@ -1499,7 +1555,7 @@ pub struct StructDef { FIXME (#3300): Should allow items to be anonymous. Right now we just use dummy names for anon items. */ -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct Item { pub ident: Ident, pub attrs: Vec<Attribute>, @@ -1509,23 +1565,25 @@ pub struct Item { pub span: Span, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum Item_ { ItemStatic(P<Ty>, Mutability, P<Expr>), ItemConst(P<Ty>, P<Expr>), - ItemFn(P<FnDecl>, FnStyle, Abi, Generics, P<Block>), + ItemFn(P<FnDecl>, Unsafety, Abi, Generics, P<Block>), ItemMod(Mod), ItemForeignMod(ForeignMod), ItemTy(P<Ty>, Generics), ItemEnum(EnumDef, Generics), ItemStruct(P<StructDef>, Generics), /// Represents a Trait Declaration - ItemTrait(Generics, + ItemTrait(Unsafety, + Generics, Option<TraitRef>, // (optional) default bound not required for Self. // Currently, only Sized makes sense here. TyParamBounds, Vec<TraitItem>), - ItemImpl(Generics, + ItemImpl(Unsafety, + Generics, Option<TraitRef>, // (optional) trait this impl implements P<Ty>, // self Vec<ImplItem>), @@ -1551,7 +1609,7 @@ impl Item_ { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub struct ForeignItem { pub ident: Ident, pub attrs: Vec<Attribute>, @@ -1561,7 +1619,7 @@ pub struct ForeignItem { pub vis: Visibility, } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum ForeignItem_ { ForeignItemFn(P<FnDecl>, Generics), ForeignItemStatic(P<Ty>, /* is_mutbl */ bool), @@ -1576,7 +1634,7 @@ impl ForeignItem_ { } } -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum UnboxedClosureKind { FnUnboxedClosureKind, FnMutUnboxedClosureKind, @@ -1586,7 +1644,7 @@ pub enum UnboxedClosureKind { /// The data we save and restore about an inlined item or method. This is not /// part of the AST that we parse from a file, but it becomes part of the tree /// that we trans. -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)] pub enum InlinedItem { IIItem(P<Item>), IITraitItem(DefId /* impl id */, TraitItem), diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs index 8db12fbd835..7c89245f53e 100644 --- a/src/libsyntax/ast_map/blocks.rs +++ b/src/libsyntax/ast_map/blocks.rs @@ -37,10 +37,11 @@ use visit; /// /// More specifically, it is one of either: /// - A function item, -/// - A closure expr (i.e. an ExprClosure or ExprProc), or +/// - A closure expr (i.e. an ExprClosure), or /// - The default implementation for a trait method. /// /// To construct one, use the `Code::from_node` function. +#[deriving(Copy)] pub struct FnLikeNode<'a> { node: ast_map::Node<'a> } /// MaybeFnLike wraps a method that indicates if an object @@ -71,7 +72,7 @@ impl MaybeFnLike for ast::TraitItem { impl MaybeFnLike for ast::Expr { fn is_fn_like(&self) -> bool { match self.node { - ast::ExprClosure(..) | ast::ExprProc(..) => true, + ast::ExprClosure(..) => true, _ => false, } } @@ -80,6 +81,7 @@ impl MaybeFnLike for ast::Expr { /// Carries either an FnLikeNode or a Block, as these are the two /// constructs that correspond to "code" (as in, something from which /// we can construct a control-flow graph). +#[deriving(Copy)] pub enum Code<'a> { FnLikeCode(FnLikeNode<'a>), BlockCode(&'a Block), @@ -118,7 +120,7 @@ impl<'a> Code<'a> { struct ItemFnParts<'a> { ident: ast::Ident, decl: &'a ast::FnDecl, - style: ast::FnStyle, + unsafety: ast::Unsafety, abi: abi::Abi, generics: &'a ast::Generics, body: &'a Block, @@ -177,27 +179,28 @@ impl<'a> FnLikeNode<'a> { } pub fn kind(self) -> visit::FnKind<'a> { - let item = |p: ItemFnParts<'a>| -> visit::FnKind<'a> { - visit::FkItemFn(p.ident, p.generics, p.style, p.abi) + let item = |: p: ItemFnParts<'a>| -> visit::FnKind<'a> { + visit::FkItemFn(p.ident, p.generics, p.unsafety, p.abi) }; - let closure = |_: ClosureParts| { + let closure = |: _: ClosureParts| { visit::FkFnBlock }; - let method = |m: &'a ast::Method| { + let method = |: m: &'a ast::Method| { visit::FkMethod(m.pe_ident(), m.pe_generics(), m) }; self.handle(item, method, closure) } - fn handle<A>(self, - item_fn: |ItemFnParts<'a>| -> A, - method: |&'a ast::Method| -> A, - closure: |ClosureParts<'a>| -> A) -> A { + fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where + I: FnOnce(ItemFnParts<'a>) -> A, + M: FnOnce(&'a ast::Method) -> A, + C: FnOnce(ClosureParts<'a>) -> A, + { match self.node { ast_map::NodeItem(i) => match i.node { - ast::ItemFn(ref decl, style, abi, ref generics, ref block) => + ast::ItemFn(ref decl, unsafety, abi, ref generics, ref block) => item_fn(ItemFnParts{ - ident: i.ident, decl: &**decl, style: style, body: &**block, + ident: i.ident, decl: &**decl, unsafety: unsafety, body: &**block, generics: generics, abi: abi, id: i.id, span: i.span }), _ => panic!("item FnLikeNode that is not fn-like"), @@ -217,8 +220,6 @@ impl<'a> FnLikeNode<'a> { ast_map::NodeExpr(e) => match e.node { ast::ExprClosure(_, _, ref decl, ref block) => closure(ClosureParts::new(&**decl, &**block, e.id, e.span)), - ast::ExprProc(ref decl, ref block) => - closure(ClosureParts::new(&**decl, &**block, e.id, e.span)), _ => panic!("expr FnLikeNode that is not fn-like"), }, _ => panic!("other FnLikeNode that is not fn-like"), diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index 472331bc9e1..9b42a8f7540 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -32,7 +32,7 @@ use std::slice; pub mod blocks; -#[deriving(Clone, PartialEq)] +#[deriving(Clone, Copy, PartialEq)] pub enum PathElem { PathMod(Name), PathName(Name) @@ -73,9 +73,9 @@ impl<'a> Iterator<PathElem> for LinkedPath<'a> { } } -// HACK(eddyb) move this into libstd (value wrapper for slice::Items). +// HACK(eddyb) move this into libstd (value wrapper for slice::Iter). #[deriving(Clone)] -pub struct Values<'a, T:'a>(pub slice::Items<'a, T>); +pub struct Values<'a, T:'a>(pub slice::Iter<'a, T>); impl<'a, T: Copy> Iterator<T> for Values<'a, T> { fn next(&mut self) -> Option<T> { @@ -87,7 +87,7 @@ impl<'a, T: Copy> Iterator<T> for Values<'a, T> { /// The type of the iterator used by with_path. pub type PathElems<'a, 'b> = iter::Chain<Values<'a, PathElem>, LinkedPath<'b>>; -pub fn path_to_string<PI: Iterator<PathElem>>(mut path: PI) -> String { +pub fn path_to_string<PI: Iterator<PathElem>>(path: PI) -> String { let itr = token::get_ident_interner(); path.fold(String::new(), |mut s, e| { @@ -95,12 +95,12 @@ pub fn path_to_string<PI: Iterator<PathElem>>(mut path: PI) -> String { if !s.is_empty() { s.push_str("::"); } - s.push_str(e.as_slice()); + s.push_str(e[]); s }).to_string() } -#[deriving(Show)] +#[deriving(Copy, Show)] pub enum Node<'ast> { NodeItem(&'ast Item), NodeForeignItem(&'ast ForeignItem), @@ -122,7 +122,7 @@ pub enum Node<'ast> { /// Represents an entry and its parent Node ID /// The odd layout is to bring down the total size. -#[deriving(Show)] +#[deriving(Copy, Show)] enum MapEntry<'ast> { /// Placeholder for holes in the map. NotPresent, @@ -260,7 +260,7 @@ impl<'ast> Map<'ast> { } fn find_entry(&self, id: NodeId) -> Option<MapEntry<'ast>> { - self.map.borrow().as_slice().get(id as uint).map(|e| *e) + self.map.borrow().get(id as uint).map(|e| *e) } pub fn krate(&self) -> &'ast Crate { @@ -418,7 +418,9 @@ impl<'ast> Map<'ast> { } } - pub fn with_path<T>(&self, id: NodeId, f: |PathElems| -> T) -> T { + pub fn with_path<T, F>(&self, id: NodeId, f: F) -> T where + F: FnOnce(PathElems) -> T, + { self.with_path_next(id, None, f) } @@ -432,7 +434,9 @@ impl<'ast> Map<'ast> { }) } - fn with_path_next<T>(&self, id: NodeId, next: LinkedPath, f: |PathElems| -> T) -> T { + fn with_path_next<T, F>(&self, id: NodeId, next: LinkedPath, f: F) -> T where + F: FnOnce(PathElems) -> T, + { let parent = self.get_parent(id); let parent = match self.find_entry(id) { Some(EntryForeignItem(..)) | Some(EntryVariant(..)) => { @@ -464,22 +468,24 @@ impl<'ast> Map<'ast> { /// Given a node ID and a closure, apply the closure to the array /// of attributes associated with the AST corresponding to the Node ID - pub fn with_attrs<T>(&self, id: NodeId, f: |Option<&[Attribute]>| -> T) -> T { + pub fn with_attrs<T, F>(&self, id: NodeId, f: F) -> T where + F: FnOnce(Option<&[Attribute]>) -> T, + { let attrs = match self.get(id) { - NodeItem(i) => Some(i.attrs.as_slice()), - NodeForeignItem(fi) => Some(fi.attrs.as_slice()), + NodeItem(i) => Some(i.attrs[]), + NodeForeignItem(fi) => Some(fi.attrs[]), NodeTraitItem(ref tm) => match **tm { - RequiredMethod(ref type_m) => Some(type_m.attrs.as_slice()), - ProvidedMethod(ref m) => Some(m.attrs.as_slice()), - TypeTraitItem(ref typ) => Some(typ.attrs.as_slice()), + RequiredMethod(ref type_m) => Some(type_m.attrs[]), + ProvidedMethod(ref m) => Some(m.attrs[]), + TypeTraitItem(ref typ) => Some(typ.attrs[]), }, NodeImplItem(ref ii) => { match **ii { - MethodImplItem(ref m) => Some(m.attrs.as_slice()), - TypeImplItem(ref t) => Some(t.attrs.as_slice()), + MethodImplItem(ref m) => Some(m.attrs[]), + TypeImplItem(ref t) => Some(t.attrs[]), } } - NodeVariant(ref v) => Some(v.node.attrs.as_slice()), + NodeVariant(ref v) => Some(v.node.attrs[]), // unit/tuple structs take the attributes straight from // the struct definition. // FIXME(eddyb) make this work again (requires access to the map). @@ -498,8 +504,8 @@ impl<'ast> Map<'ast> { /// the iterator will produce node id's for items with paths /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and /// any other such items it can find in the map. - pub fn nodes_matching_suffix<'a, S:Str>(&'a self, parts: &'a [S]) - -> NodesMatchingSuffix<'a, 'ast, S> { + pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String]) + -> NodesMatchingSuffix<'a, 'ast> { NodesMatchingSuffix { map: self, item_name: parts.last().unwrap(), @@ -551,18 +557,22 @@ impl<'ast> Map<'ast> { } pub fn node_to_string(&self, id: NodeId) -> String { - node_id_to_string(self, id) + node_id_to_string(self, id, true) + } + + pub fn node_to_user_string(&self, id: NodeId) -> String { + node_id_to_string(self, id, false) } } -pub struct NodesMatchingSuffix<'a, 'ast:'a, S:'a> { +pub struct NodesMatchingSuffix<'a, 'ast:'a> { map: &'a Map<'ast>, - item_name: &'a S, - in_which: &'a [S], + item_name: &'a String, + in_which: &'a [String], idx: NodeId, } -impl<'a, 'ast, S:Str> NodesMatchingSuffix<'a, 'ast, S> { +impl<'a, 'ast> NodesMatchingSuffix<'a, 'ast> { /// Returns true only if some suffix of the module path for parent /// matches `self.in_which`. /// @@ -576,7 +586,7 @@ impl<'a, 'ast, S:Str> NodesMatchingSuffix<'a, 'ast, S> { None => return false, Some((node_id, name)) => (node_id, name), }; - if part.as_slice() != mod_name.as_str() { + if part[] != mod_name.as_str() { return false; } cursor = self.map.get_parent(mod_id); @@ -614,12 +624,12 @@ impl<'a, 'ast, S:Str> NodesMatchingSuffix<'a, 'ast, S> { // We are looking at some node `n` with a given name and parent // id; do their names match what I am seeking? fn matches_names(&self, parent_of_n: NodeId, name: Name) -> bool { - name.as_str() == self.item_name.as_slice() && + name.as_str() == self.item_name[] && self.suffix_matches(parent_of_n) } } -impl<'a, 'ast, S:Str> Iterator<NodeId> for NodesMatchingSuffix<'a, 'ast, S> { +impl<'a, 'ast> Iterator<NodeId> for NodesMatchingSuffix<'a, 'ast> { fn next(&mut self) -> Option<NodeId> { loop { let idx = self.idx; @@ -739,7 +749,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { let parent = self.parent; self.parent = i.id; match i.node { - ItemImpl(_, _, _, ref impl_items) => { + ItemImpl(_, _, _, _, ref impl_items) => { for impl_item in impl_items.iter() { match *impl_item { MethodImplItem(ref m) => { @@ -770,13 +780,10 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { None => {} } } - ItemTrait(_, _, ref bounds, ref trait_items) => { + ItemTrait(_, _, _, ref bounds, ref trait_items) => { for b in bounds.iter() { - match *b { - TraitTyParamBound(ref t) => { - self.insert(t.trait_ref.ref_id, NodeItem(i)); - } - _ => {} + if let TraitTyParamBound(ref t) = *b { + self.insert(t.trait_ref.ref_id, NodeItem(i)); } } @@ -846,7 +853,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { fn visit_ty(&mut self, ty: &'ast Ty) { match ty.node { - TyClosure(ref fd) | TyProc(ref fd) => { + TyClosure(ref fd) => { self.visit_fn_decl(&*fd.decl); } TyBareFn(ref fd) => { @@ -1028,7 +1035,10 @@ impl<'a> NodePrinter for pprust::State<'a> { } } -fn node_id_to_string(map: &Map, id: NodeId) -> String { +fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { + let id_str = format!(" (id={})", id); + let id_str = if include_id { id_str[] } else { "" }; + match map.find(id) { Some(NodeItem(item)) => { let path_str = map.path_to_str_with_ident(id, item.ident); @@ -1045,30 +1055,30 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String { ItemImpl(..) => "impl", ItemMac(..) => "macro" }; - format!("{} {} (id={})", item_str, path_str, id) + format!("{} {}{}", item_str, path_str, id_str) } Some(NodeForeignItem(item)) => { let path_str = map.path_to_str_with_ident(id, item.ident); - format!("foreign item {} (id={})", path_str, id) + format!("foreign item {}{}", path_str, id_str) } Some(NodeImplItem(ref ii)) => { match **ii { MethodImplItem(ref m) => { match m.node { MethDecl(ident, _, _, _, _, _, _, _) => - format!("method {} in {} (id={})", + format!("method {} in {}{}", token::get_ident(ident), - map.path_to_string(id), id), + map.path_to_string(id), id_str), MethMac(ref mac) => - format!("method macro {} (id={})", - pprust::mac_to_string(mac), id) + format!("method macro {}{}", + pprust::mac_to_string(mac), id_str) } } TypeImplItem(ref t) => { - format!("typedef {} in {} (id={})", + format!("typedef {} in {}{}", token::get_ident(t.ident), map.path_to_string(id), - id) + id_str) } } } @@ -1076,51 +1086,51 @@ fn node_id_to_string(map: &Map, id: NodeId) -> String { match **tm { RequiredMethod(_) | ProvidedMethod(_) => { let m = ast_util::trait_item_to_ty_method(&**tm); - format!("method {} in {} (id={})", + format!("method {} in {}{}", token::get_ident(m.ident), map.path_to_string(id), - id) + id_str) } TypeTraitItem(ref t) => { - format!("type item {} in {} (id={})", + format!("type item {} in {}{}", token::get_ident(t.ty_param.ident), map.path_to_string(id), - id) + id_str) } } } Some(NodeVariant(ref variant)) => { - format!("variant {} in {} (id={})", + format!("variant {} in {}{}", token::get_ident(variant.node.name), - map.path_to_string(id), id) + map.path_to_string(id), id_str) } Some(NodeExpr(ref expr)) => { - format!("expr {} (id={})", pprust::expr_to_string(&**expr), id) + format!("expr {}{}", pprust::expr_to_string(&**expr), id_str) } Some(NodeStmt(ref stmt)) => { - format!("stmt {} (id={})", pprust::stmt_to_string(&**stmt), id) + format!("stmt {}{}", pprust::stmt_to_string(&**stmt), id_str) } Some(NodeArg(ref pat)) => { - format!("arg {} (id={})", pprust::pat_to_string(&**pat), id) + format!("arg {}{}", pprust::pat_to_string(&**pat), id_str) } Some(NodeLocal(ref pat)) => { - format!("local {} (id={})", pprust::pat_to_string(&**pat), id) + format!("local {}{}", pprust::pat_to_string(&**pat), id_str) } Some(NodePat(ref pat)) => { - format!("pat {} (id={})", pprust::pat_to_string(&**pat), id) + format!("pat {}{}", pprust::pat_to_string(&**pat), id_str) } Some(NodeBlock(ref block)) => { - format!("block {} (id={})", pprust::block_to_string(&**block), id) + format!("block {}{}", pprust::block_to_string(&**block), id_str) } Some(NodeStructCtor(_)) => { - format!("struct_ctor {} (id={})", map.path_to_string(id), id) + format!("struct_ctor {}{}", map.path_to_string(id), id_str) } Some(NodeLifetime(ref l)) => { - format!("lifetime {} (id={})", - pprust::lifetime_to_string(&**l), id) + format!("lifetime {}{}", + pprust::lifetime_to_string(&**l), id_str) } None => { - format!("unknown node (id={})", id) + format!("unknown node{}", id_str) } } } diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 043e79bffd9..9196055267f 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -85,6 +85,24 @@ pub fn is_shift_binop(b: BinOp) -> bool { } } +/// Returns `true` if the binary operator takes its arguments by value +pub fn is_by_value_binop(b: BinOp) -> bool { + match b { + BiAdd | BiSub | BiMul | BiDiv | BiRem | BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr => { + true + } + _ => false + } +} + +/// Returns `true` if the unary operator takes its argument by value +pub fn is_by_value_unop(u: UnOp) -> bool { + match u { + UnNeg | UnNot => true, + _ => false, + } +} + pub fn unop_to_string(op: UnOp) -> &'static str { match op { UnUniq => "box() ", @@ -174,12 +192,28 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path { parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: Vec::new(), types: OwnedSlice::empty(), + bindings: OwnedSlice::empty(), }) } ), } } +// If path is a single segment ident path, return that ident. Otherwise, return +// None. +pub fn path_to_ident(path: &Path) -> Option<Ident> { + if path.segments.len() != 1 { + return None; + } + + let segment = &path.segments[0]; + if !segment.parameters.is_empty() { + return None; + } + + Some(segment.identifier) +} + pub fn ident_to_pat(id: NodeId, s: Span, i: Ident) -> P<Pat> { P(Pat { id: id, @@ -204,11 +238,11 @@ pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident { match *trait_ref { Some(ref trait_ref) => { pretty.push('.'); - pretty.push_str(pprust::path_to_string(&trait_ref.path).as_slice()); + pretty.push_str(pprust::path_to_string(&trait_ref.path)[]); } None => {} } - token::gensym_ident(pretty.as_slice()) + token::gensym_ident(pretty[]) } pub fn trait_method_to_ty_method(method: &Method) -> TypeMethod { @@ -217,14 +251,14 @@ pub fn trait_method_to_ty_method(method: &Method) -> TypeMethod { ref generics, abi, ref explicit_self, - fn_style, + unsafety, ref decl, _, vis) => { TypeMethod { ident: ident, attrs: method.attrs.clone(), - fn_style: fn_style, + unsafety: unsafety, decl: (*decl).clone(), generics: generics.clone(), explicit_self: (*explicit_self).clone(), @@ -309,7 +343,7 @@ pub fn empty_generics() -> Generics { // ______________________________________________________________________ // Enumerating the IDs which appear in an AST -#[deriving(Encodable, Decodable, Show)] +#[deriving(RustcEncodable, RustcDecodable, Show, Copy)] pub struct IdRange { pub min: NodeId, pub max: NodeId, @@ -412,13 +446,10 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { } self.operation.visit_id(item.id); - match item.node { - ItemEnum(ref enum_definition, _) => { - for variant in enum_definition.variants.iter() { - self.operation.visit_id(variant.node.id) - } + if let ItemEnum(ref enum_definition, _) = item.node { + for variant in enum_definition.variants.iter() { + self.operation.visit_id(variant.node.id) } - _ => {} } visit::walk_item(self, item); @@ -453,9 +484,8 @@ 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), - _ => {} + if let TyPath(_, id) = typ.node { + self.operation.visit_id(id); } visit::walk_ty(self, typ) } @@ -500,9 +530,8 @@ impl<'a, 'v, O: IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> { span); if !self.pass_through_items { - match function_kind { - visit::FkMethod(..) => self.visited_outermost = false, - _ => {} + if let visit::FkMethod(..) = function_kind { + self.visited_outermost = false; } } } @@ -569,6 +598,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 +606,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() }; @@ -593,6 +618,7 @@ pub fn compute_id_range_for_fn_body(fk: visit::FnKind, id_visitor.operation.result } +// FIXME(#19596) unbox `it` pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool { if !it(pat) { return false; @@ -623,21 +649,21 @@ pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool { } pub trait EachViewItem { - fn each_view_item(&self, f: |&ast::ViewItem| -> bool) -> bool; + fn each_view_item<F>(&self, f: F) -> bool where F: FnMut(&ast::ViewItem) -> bool; } -struct EachViewItemData<'a> { - callback: |&ast::ViewItem|: 'a -> bool, +struct EachViewItemData<F> where F: FnMut(&ast::ViewItem) -> bool { + callback: F, } -impl<'a, 'v> Visitor<'v> for EachViewItemData<'a> { +impl<'v, F> Visitor<'v> for EachViewItemData<F> where F: FnMut(&ast::ViewItem) -> bool { fn visit_view_item(&mut self, view_item: &ast::ViewItem) { let _ = (self.callback)(view_item); } } impl EachViewItem for ast::Crate { - fn each_view_item(&self, f: |&ast::ViewItem| -> bool) -> bool { + fn each_view_item<F>(&self, f: F) -> bool where F: FnMut(&ast::ViewItem) -> bool { let mut visit = EachViewItemData { callback: f, }; @@ -674,7 +700,7 @@ pub fn pat_is_ident(pat: P<ast::Pat>) -> bool { pub fn path_name_eq(a : &ast::Path, b : &ast::Path) -> bool { (a.span == b.span) && (a.global == b.global) - && (segments_name_eq(a.segments.as_slice(), b.segments.as_slice())) + && (segments_name_eq(a.segments[], b.segments[])) } // are two arrays of segments equal when compared unhygienically? @@ -712,7 +738,7 @@ pub trait PostExpansionMethod { fn pe_generics<'a>(&'a self) -> &'a ast::Generics; fn pe_abi(&self) -> Abi; fn pe_explicit_self<'a>(&'a self) -> &'a ast::ExplicitSelf; - fn pe_fn_style(&self) -> ast::FnStyle; + fn pe_unsafety(&self) -> ast::Unsafety; fn pe_fn_decl<'a>(&'a self) -> &'a ast::FnDecl; fn pe_body<'a>(&'a self) -> &'a ast::Block; fn pe_vis(&self) -> ast::Visibility; @@ -733,16 +759,20 @@ macro_rules! mf_method{ impl PostExpansionMethod for Method { - mf_method!(pe_ident,ast::Ident,MethDecl(ident,_,_,_,_,_,_,_),ident) - mf_method!(pe_generics,&'a ast::Generics, - MethDecl(_,ref generics,_,_,_,_,_,_),generics) - mf_method!(pe_abi,Abi,MethDecl(_,_,abi,_,_,_,_,_),abi) - mf_method!(pe_explicit_self,&'a ast::ExplicitSelf, - MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self) - mf_method!(pe_fn_style,ast::FnStyle,MethDecl(_,_,_,_,fn_style,_,_,_),fn_style) - mf_method!(pe_fn_decl,&'a ast::FnDecl,MethDecl(_,_,_,_,_,ref decl,_,_),&**decl) - mf_method!(pe_body,&'a ast::Block,MethDecl(_,_,_,_,_,_,ref body,_),&**body) - mf_method!(pe_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,_,vis),vis) + mf_method! { pe_ident,ast::Ident,MethDecl(ident,_,_,_,_,_,_,_),ident } + mf_method! { + pe_generics,&'a ast::Generics, + MethDecl(_,ref generics,_,_,_,_,_,_),generics + } + mf_method! { pe_abi,Abi,MethDecl(_,_,abi,_,_,_,_,_),abi } + mf_method! { + pe_explicit_self,&'a ast::ExplicitSelf, + MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self + } + mf_method! { pe_unsafety,ast::Unsafety,MethDecl(_,_,_,_,unsafety,_,_,_),unsafety } + mf_method! { pe_fn_decl,&'a ast::FnDecl,MethDecl(_,_,_,_,_,ref decl,_,_),&**decl } + mf_method! { pe_body,&'a ast::Block,MethDecl(_,_,_,_,_,_,ref body,_),&**body } + mf_method! { pe_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,_,vis),vis } } #[cfg(test)] @@ -758,13 +788,13 @@ mod test { #[test] fn idents_name_eq_test() { assert!(segments_name_eq( [Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}] - .iter().map(ident_to_segment).collect::<Vec<PathSegment>>().as_slice(), + .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()[], [Ident{name:Name(3),ctxt:104}, Ident{name:Name(78),ctxt:182}] - .iter().map(ident_to_segment).collect::<Vec<PathSegment>>().as_slice())); + .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()[])); assert!(!segments_name_eq( [Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}] - .iter().map(ident_to_segment).collect::<Vec<PathSegment>>().as_slice(), + .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()[], [Ident{name:Name(3),ctxt:104}, Ident{name:Name(77),ctxt:182}] - .iter().map(ident_to_segment).collect::<Vec<PathSegment>>().as_slice())); + .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()[])); } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 42fdb50f87a..df820b40cb6 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -25,21 +25,20 @@ use parse::token::InternedString; use parse::token; use ptr::P; -use std::collections::HashSet; +use std::cell::{RefCell, Cell}; use std::collections::BitvSet; +use std::collections::HashSet; -local_data_key!(used_attrs: BitvSet) +thread_local! { static USED_ATTRS: RefCell<BitvSet> = RefCell::new(BitvSet::new()) } pub fn mark_used(attr: &Attribute) { - let mut used = used_attrs.replace(None).unwrap_or_else(|| BitvSet::new()); let AttrId(id) = attr.node.id; - used.insert(id); - used_attrs.replace(Some(used)); + USED_ATTRS.with(|slot| slot.borrow_mut().insert(id)); } pub fn is_used(attr: &Attribute) -> bool { let AttrId(id) = attr.node.id; - used_attrs.get().map_or(false, |used| used.contains(&id)) + USED_ATTRS.with(|slot| slot.borrow().contains(&id)) } pub trait AttrMetaMethods { @@ -98,7 +97,7 @@ impl AttrMetaMethods for MetaItem { fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> { match self.node { - MetaList(_, ref l) => Some(l.as_slice()), + MetaList(_, ref l) => Some(l[]), _ => None } } @@ -116,7 +115,8 @@ impl AttrMetaMethods for P<MetaItem> { pub trait AttributeMethods { fn meta<'a>(&'a self) -> &'a MetaItem; - fn with_desugared_doc<T>(&self, f: |&Attribute| -> T) -> T; + fn with_desugared_doc<T, F>(&self, f: F) -> T where + F: FnOnce(&Attribute) -> T; } impl AttributeMethods for Attribute { @@ -128,13 +128,15 @@ impl AttributeMethods for Attribute { /// Convert self to a normal #[doc="foo"] comment, if it is a /// comment like `///` or `/** */`. (Returns self unchanged for /// non-sugared doc attributes.) - fn with_desugared_doc<T>(&self, f: |&Attribute| -> T) -> T { + fn with_desugared_doc<T, F>(&self, f: F) -> T where + F: FnOnce(&Attribute) -> T, + { if self.node.is_sugared_doc { let comment = self.value_str().unwrap(); let meta = mk_name_value_item_str( InternedString::new("doc"), token::intern_and_get_ident(strip_doc_comment_decoration( - comment.get()).as_slice())); + comment.get())[])); if self.node.style == ast::AttrOuter { f(&mk_attr_outer(self.node.id, meta)) } else { @@ -167,11 +169,14 @@ pub fn mk_word_item(name: InternedString) -> P<MetaItem> { P(dummy_spanned(MetaWord(name))) } -local_data_key!(next_attr_id: uint) +thread_local! { static NEXT_ATTR_ID: Cell<uint> = Cell::new(0) } pub fn mk_attr_id() -> AttrId { - let id = next_attr_id.replace(None).unwrap_or(0); - next_attr_id.replace(Some(id + 1)); + let id = NEXT_ATTR_ID.with(|slot| { + let r = slot.get(); + slot.set(r + 1); + r + }); AttrId(id) } @@ -272,7 +277,7 @@ pub fn find_crate_name(attrs: &[Attribute]) -> Option<InternedString> { first_attr_value_str_by_name(attrs, "crate_name") } -#[deriving(PartialEq)] +#[deriving(Copy, PartialEq)] pub enum InlineAttr { InlineNone, InlineHint, @@ -285,15 +290,15 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr { // FIXME (#2809)---validate the usage of #[inline] and #[inline] attrs.iter().fold(InlineNone, |ia,attr| { match attr.node.value.node { - MetaWord(ref n) if n.equiv(&("inline")) => { + MetaWord(ref n) if *n == "inline" => { mark_used(attr); InlineHint } - MetaList(ref n, ref items) if n.equiv(&("inline")) => { + MetaList(ref n, ref items) if *n == "inline" => { mark_used(attr); - if contains_name(items.as_slice(), "always") { + if contains_name(items[], "always") { InlineAlways - } else if contains_name(items.as_slice(), "never") { + } else if contains_name(items[], "never") { InlineNever } else { InlineHint @@ -327,7 +332,7 @@ pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P<MetaItem>], cfg: &ast::Me !cfg_matches(diagnostic, cfgs, &*mis[0]) } ast::MetaList(ref pred, _) => { - diagnostic.span_err(cfg.span, format!("invalid predicate `{}`", pred).as_slice()); + diagnostic.span_err(cfg.span, format!("invalid predicate `{}`", pred)[]); false }, ast::MetaWord(_) | ast::MetaNameValue(..) => contains(cfgs, cfg), @@ -335,14 +340,14 @@ pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P<MetaItem>], cfg: &ast::Me } /// Represents the #[deprecated="foo"] and friends attributes. -#[deriving(Encodable,Decodable,Clone,Show)] +#[deriving(RustcEncodable,RustcDecodable,Clone,Show)] pub struct Stability { pub level: StabilityLevel, pub text: Option<InternedString> } /// The available stability levels. -#[deriving(Encodable,Decodable,PartialEq,PartialOrd,Clone,Show)] +#[deriving(RustcEncodable,RustcDecodable,PartialEq,PartialOrd,Clone,Show,Copy)] pub enum StabilityLevel { Deprecated, Experimental, @@ -391,8 +396,7 @@ pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P<MetaItem>]) { if !set.insert(name.clone()) { diagnostic.span_fatal(meta.span, - format!("duplicate meta item `{}`", - name).as_slice()); + format!("duplicate meta item `{}`", name)[]); } } } @@ -407,7 +411,7 @@ pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P<MetaItem>]) { pub fn find_repr_attrs(diagnostic: &SpanHandler, attr: &Attribute) -> Vec<ReprAttr> { let mut acc = Vec::new(); match attr.node.value.node { - ast::MetaList(ref s, ref items) if s.equiv(&("repr")) => { + ast::MetaList(ref s, ref items) if *s == "repr" => { mark_used(attr); for item in items.iter() { match item.node { @@ -459,7 +463,7 @@ fn int_type_of_word(s: &str) -> Option<IntType> { } } -#[deriving(PartialEq, Show, Encodable, Decodable)] +#[deriving(PartialEq, Show, RustcEncodable, RustcDecodable, Copy)] pub enum ReprAttr { ReprAny, ReprInt(Span, IntType), @@ -478,7 +482,7 @@ impl ReprAttr { } } -#[deriving(Eq, Hash, PartialEq, Show, Encodable, Decodable)] +#[deriving(Eq, Hash, PartialEq, Show, RustcEncodable, RustcDecodable, Copy)] pub enum IntType { SignedInt(ast::IntTy), UnsignedInt(ast::UintTy) diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 7d849ddf1c1..6b9af29c604 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::*; @@ -37,13 +31,13 @@ pub trait Pos { /// A byte offset. Keep this small (currently 32-bits), as AST contains /// a lot of them. -#[deriving(Clone, PartialEq, Eq, Hash, PartialOrd, Show)] +#[deriving(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Show)] pub struct BytePos(pub u32); /// A character offset. Because of multibyte utf8 characters, a byte offset /// is not equivalent to a character offset. The CodeMap will convert BytePos /// values to CharPos values as necessary. -#[deriving(PartialEq, Hash, PartialOrd, Show)] +#[deriving(Copy, PartialEq, Hash, PartialOrd, Show)] pub struct CharPos(pub uint); // FIXME: Lots of boilerplate in these impls, but so far my attempts to fix @@ -55,13 +49,13 @@ impl Pos for BytePos { } impl Add<BytePos, BytePos> for BytePos { - fn add(&self, rhs: &BytePos) -> BytePos { + fn add(self, rhs: BytePos) -> BytePos { BytePos((self.to_uint() + rhs.to_uint()) as u32) } } impl Sub<BytePos, BytePos> for BytePos { - fn sub(&self, rhs: &BytePos) -> BytePos { + fn sub(self, rhs: BytePos) -> BytePos { BytePos((self.to_uint() - rhs.to_uint()) as u32) } } @@ -71,25 +65,23 @@ impl Pos for CharPos { fn to_uint(&self) -> uint { let CharPos(n) = *self; n } } -impl Add<CharPos,CharPos> for CharPos { - fn add(&self, rhs: &CharPos) -> CharPos { +impl Add<CharPos, CharPos> for CharPos { + fn add(self, rhs: CharPos) -> CharPos { CharPos(self.to_uint() + rhs.to_uint()) } } -impl Sub<CharPos,CharPos> for CharPos { - fn sub(&self, rhs: &CharPos) -> CharPos { +impl Sub<CharPos, CharPos> for CharPos { + fn sub(self, rhs: CharPos) -> CharPos { CharPos(self.to_uint() - rhs.to_uint()) } } -/** -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)] +/// 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, Copy, Show, Hash)] pub struct Span { pub lo: BytePos, pub hi: BytePos, @@ -100,7 +92,7 @@ pub struct Span { pub const DUMMY_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), expn_id: NO_EXPANSION }; -#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub struct Spanned<T> { pub node: T, pub span: Span, @@ -183,7 +175,7 @@ pub struct FileMapAndLine { pub fm: Rc<FileMap>, pub line: uint } pub struct FileMapAndBytePos { pub fm: Rc<FileMap>, pub pos: BytePos } /// The syntax with which a macro was invoked. -#[deriving(Clone, Hash, Show)] +#[deriving(Clone, Copy, Hash, Show)] pub enum MacroFormat { /// e.g. #[deriving(...)] <item> MacroAttribute, @@ -226,7 +218,7 @@ pub struct ExpnInfo { pub callee: NameAndSpan } -#[deriving(PartialEq, Eq, Clone, Show, Hash, Encodable, Decodable)] +#[deriving(PartialEq, Eq, Clone, Show, Hash, RustcEncodable, RustcDecodable, Copy)] pub struct ExpnId(u32); pub const NO_EXPANSION: ExpnId = ExpnId(-1); @@ -250,6 +242,7 @@ pub struct FileLines { } /// Identifies an offset of a multi-byte character in a FileMap +#[deriving(Copy)] pub struct MultiByteChar { /// The absolute offset of the character in the CodeMap pub pos: BytePos, @@ -287,21 +280,23 @@ impl FileMap { // the new charpos must be > the last one (or it's the first one). let mut lines = self.lines.borrow_mut(); let line_len = lines.len(); - assert!(line_len == 0 || ((*lines)[line_len - 1] < pos)) + assert!(line_len == 0 || ((*lines)[line_len - 1] < pos)); lines.push(pos); } /// get a line from the list of pre-computed line-beginnings /// - pub fn get_line(&self, line: int) -> String { + pub fn get_line(&self, line_number: uint) -> Option<String> { let lines = self.lines.borrow(); - let begin: BytePos = (*lines)[line as uint] - self.start_pos; - let begin = begin.to_uint(); - let slice = self.src.as_slice().slice_from(begin); - match slice.find('\n') { - Some(e) => slice.slice_to(e).to_string(), - None => slice.to_string() - } + lines.get(line_number).map(|&line| { + let begin: BytePos = line - self.start_pos; + let begin = begin.to_uint(); + let slice = self.src[begin..]; + match slice.find('\n') { + Some(e) => slice[0..e], + None => slice + }.to_string() + }) } pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) { @@ -314,8 +309,8 @@ impl FileMap { } pub fn is_real_file(&self) -> bool { - !(self.name.as_slice().starts_with("<") && - self.name.as_slice().ends_with(">")) + !(self.name.starts_with("<") && + self.name.ends_with(">")) } } @@ -342,17 +337,17 @@ impl CodeMap { // Remove utf-8 BOM if any. // FIXME #12884: no efficient/safe way to remove from the start of a string // and reuse the allocation. - let mut src = if src.as_slice().starts_with("\ufeff") { - String::from_str(src.as_slice().slice_from(3)) + let mut src = if src.starts_with("\u{feff}") { + String::from_str(src[3..]) } else { - String::from_str(src.as_slice()) + String::from_str(src[]) }; // Append '\n' in case it's not already there. // This is a workaround to prevent CodeMap.lookup_filemap_idx from accidentally // overflowing into the next filemap in case the last byte of span is also the last // byte of filemap, which leads to incorrect results from CodeMap.span_to_*. - if src.len() > 0 && !src.as_slice().ends_with("\n") { + if src.len() > 0 && !src.ends_with("\n") { src.push('\n'); } @@ -432,14 +427,14 @@ impl CodeMap { if begin.fm.start_pos != end.fm.start_pos { None } else { - Some(begin.fm.src.as_slice().slice(begin.pos.to_uint(), - end.pos.to_uint()).to_string()) + Some(begin.fm.src[begin.pos.to_uint().. + end.pos.to_uint()].to_string()) } } pub fn get_filemap(&self, filename: &str) -> Rc<FileMap> { for fm in self.files.borrow().iter() { - if filename == fm.name.as_slice() { + if filename == fm.name { return fm.clone(); } } @@ -560,7 +555,9 @@ impl CodeMap { ExpnId(expansions.len().to_u32().expect("too many ExpnInfo's!") - 1) } - pub fn with_expn_info<T>(&self, id: ExpnId, f: |Option<&ExpnInfo>| -> T) -> T { + pub fn with_expn_info<T, F>(&self, id: ExpnId, f: F) -> T where + F: FnOnce(Option<&ExpnInfo>) -> T, + { match id { NO_EXPANSION => f(None), ExpnId(i) => f(Some(&(*self.expansions.borrow())[i as uint])) @@ -578,10 +575,10 @@ mod test { let fm = cm.new_filemap("blork.rs".to_string(), "first line.\nsecond line".to_string()); fm.next_line(BytePos(0)); - assert_eq!(&fm.get_line(0),&"first line.".to_string()); + assert_eq!(fm.get_line(0), Some("first line.".to_string())); // TESTING BROKEN BEHAVIOR: fm.next_line(BytePos(10)); - assert_eq!(&fm.get_line(1), &".".to_string()); + assert_eq!(fm.get_line(1), Some(".".to_string())); } #[test] @@ -620,11 +617,11 @@ mod test { let cm = init_code_map(); let fmabp1 = cm.lookup_byte_offset(BytePos(22)); - assert_eq!(fmabp1.fm.name, "blork.rs".to_string()); + assert_eq!(fmabp1.fm.name, "blork.rs"); assert_eq!(fmabp1.pos, BytePos(22)); let fmabp2 = cm.lookup_byte_offset(BytePos(24)); - assert_eq!(fmabp2.fm.name, "blork2.rs".to_string()); + assert_eq!(fmabp2.fm.name, "blork2.rs"); assert_eq!(fmabp2.pos, BytePos(0)); } @@ -646,12 +643,12 @@ mod test { let cm = init_code_map(); let loc1 = cm.lookup_char_pos(BytePos(22)); - assert_eq!(loc1.file.name, "blork.rs".to_string()); + assert_eq!(loc1.file.name, "blork.rs"); assert_eq!(loc1.line, 2); assert_eq!(loc1.col, CharPos(10)); let loc2 = cm.lookup_char_pos(BytePos(24)); - assert_eq!(loc2.file.name, "blork2.rs".to_string()); + assert_eq!(loc2.file.name, "blork2.rs"); assert_eq!(loc2.line, 1); assert_eq!(loc2.col, CharPos(0)); } @@ -707,7 +704,7 @@ mod test { let span = Span {lo: BytePos(12), hi: BytePos(23), expn_id: NO_EXPANSION}; let file_lines = cm.span_to_lines(span); - assert_eq!(file_lines.file.name, "blork.rs".to_string()); + assert_eq!(file_lines.file.name, "blork.rs"); assert_eq!(file_lines.lines.len(), 1); assert_eq!(file_lines.lines[0], 1u); } @@ -729,6 +726,6 @@ mod test { let span = Span {lo: BytePos(12), hi: BytePos(23), expn_id: NO_EXPANSION}; let sstr = cm.span_to_string(span); - assert_eq!(sstr, "blork.rs:2:1: 2:12".to_string()); + assert_eq!(sstr, "blork.rs:2:1: 2:12"); } } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 257bfd69f43..d2185a00876 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -19,8 +19,8 @@ use util::small_vector::SmallVector; /// A folder that strips out items that do not belong in the current /// configuration. -struct Context<'a> { - in_cfg: |attrs: &[ast::Attribute]|: 'a -> bool, +struct Context<F> where F: FnMut(&[ast::Attribute]) -> bool { + in_cfg: F, } // Support conditional compilation by transforming the AST, stripping out @@ -30,7 +30,7 @@ pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> strip_items(krate, |attrs| in_cfg(diagnostic, config.as_slice(), attrs)) } -impl<'a> fold::Folder for Context<'a> { +impl<F> fold::Folder for Context<F> where F: FnMut(&[ast::Attribute]) -> bool { fn fold_mod(&mut self, module: ast::Mod) -> ast::Mod { fold_mod(self, module) } @@ -54,16 +54,20 @@ impl<'a> fold::Folder for Context<'a> { } } -pub fn strip_items(krate: ast::Crate, - in_cfg: |attrs: &[ast::Attribute]| -> bool) - -> ast::Crate { +pub fn strip_items<F>(krate: ast::Crate, in_cfg: F) -> ast::Crate where + F: FnMut(&[ast::Attribute]) -> bool, +{ let mut ctxt = Context { in_cfg: in_cfg, }; ctxt.fold_crate(krate) } -fn filter_view_item(cx: &mut Context, view_item: ast::ViewItem) -> Option<ast::ViewItem> { +fn filter_view_item<F>(cx: &mut Context<F>, + view_item: ast::ViewItem) + -> Option<ast::ViewItem> where + F: FnMut(&[ast::Attribute]) -> bool +{ if view_item_in_cfg(cx, &view_item) { Some(view_item) } else { @@ -71,7 +75,11 @@ fn filter_view_item(cx: &mut Context, view_item: ast::ViewItem) -> Option<ast::V } } -fn fold_mod(cx: &mut Context, ast::Mod {inner, view_items, items}: ast::Mod) -> ast::Mod { +fn fold_mod<F>(cx: &mut Context<F>, + ast::Mod {inner, + view_items, items}: ast::Mod) -> ast::Mod where + F: FnMut(&[ast::Attribute]) -> bool +{ ast::Mod { inner: inner, view_items: view_items.into_iter().filter_map(|a| { @@ -83,8 +91,11 @@ fn fold_mod(cx: &mut Context, ast::Mod {inner, view_items, items}: ast::Mod) -> } } -fn filter_foreign_item(cx: &mut Context, item: P<ast::ForeignItem>) - -> Option<P<ast::ForeignItem>> { +fn filter_foreign_item<F>(cx: &mut Context<F>, + item: P<ast::ForeignItem>) + -> Option<P<ast::ForeignItem>> where + F: FnMut(&[ast::Attribute]) -> bool +{ if foreign_item_in_cfg(cx, &*item) { Some(item) } else { @@ -92,8 +103,11 @@ fn filter_foreign_item(cx: &mut Context, item: P<ast::ForeignItem>) } } -fn fold_foreign_mod(cx: &mut Context, ast::ForeignMod {abi, view_items, items}: ast::ForeignMod) - -> ast::ForeignMod { +fn fold_foreign_mod<F>(cx: &mut Context<F>, + ast::ForeignMod {abi, view_items, items}: ast::ForeignMod) + -> ast::ForeignMod where + F: FnMut(&[ast::Attribute]) -> bool +{ ast::ForeignMod { abi: abi, view_items: view_items.into_iter().filter_map(|a| { @@ -105,7 +119,9 @@ fn fold_foreign_mod(cx: &mut Context, ast::ForeignMod {abi, view_items, items}: } } -fn fold_item(cx: &mut Context, item: P<ast::Item>) -> SmallVector<P<ast::Item>> { +fn fold_item<F>(cx: &mut Context<F>, item: P<ast::Item>) -> SmallVector<P<ast::Item>> where + F: FnMut(&[ast::Attribute]) -> bool +{ if item_in_cfg(cx, &*item) { SmallVector::one(item.map(|i| cx.fold_item_simple(i))) } else { @@ -113,25 +129,27 @@ fn fold_item(cx: &mut Context, item: P<ast::Item>) -> SmallVector<P<ast::Item>> } } -fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ { +fn fold_item_underscore<F>(cx: &mut Context<F>, item: ast::Item_) -> ast::Item_ where + F: FnMut(&[ast::Attribute]) -> bool +{ let item = match item { - ast::ItemImpl(a, b, c, impl_items) => { + ast::ItemImpl(u, a, b, c, impl_items) => { let impl_items = impl_items.into_iter() .filter(|ii| impl_item_in_cfg(cx, ii)) .collect(); - ast::ItemImpl(a, b, c, impl_items) + ast::ItemImpl(u, a, b, c, impl_items) } - ast::ItemTrait(a, b, c, methods) => { + ast::ItemTrait(u, a, b, c, methods) => { let methods = methods.into_iter() .filter(|m| trait_method_in_cfg(cx, m)) .collect(); - ast::ItemTrait(a, b, c, methods) + ast::ItemTrait(u, a, b, c, methods) } ast::ItemStruct(def, generics) => { ast::ItemStruct(fold_struct(cx, def), generics) } ast::ItemEnum(def, generics) => { - let mut variants = def.variants.into_iter().filter_map(|v| { + let variants = def.variants.into_iter().filter_map(|v| { if !(cx.in_cfg)(v.node.attrs.as_slice()) { None } else { @@ -166,7 +184,9 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_ { fold::noop_fold_item_underscore(item, cx) } -fn fold_struct(cx: &mut Context, def: P<ast::StructDef>) -> P<ast::StructDef> { +fn fold_struct<F>(cx: &mut Context<F>, def: P<ast::StructDef>) -> P<ast::StructDef> where + F: FnMut(&[ast::Attribute]) -> bool +{ def.map(|ast::StructDef { fields, ctor_id }| { ast::StructDef { fields: fields.into_iter().filter(|m| { @@ -177,7 +197,9 @@ fn fold_struct(cx: &mut Context, def: P<ast::StructDef>) -> P<ast::StructDef> { }) } -fn retain_stmt(cx: &mut Context, stmt: &ast::Stmt) -> bool { +fn retain_stmt<F>(cx: &mut Context<F>, stmt: &ast::Stmt) -> bool where + F: FnMut(&[ast::Attribute]) -> bool +{ match stmt.node { ast::StmtDecl(ref decl, _) => { match decl.node { @@ -191,7 +213,9 @@ fn retain_stmt(cx: &mut Context, stmt: &ast::Stmt) -> bool { } } -fn fold_block(cx: &mut Context, b: P<ast::Block>) -> P<ast::Block> { +fn fold_block<F>(cx: &mut Context<F>, b: P<ast::Block>) -> P<ast::Block> where + F: FnMut(&[ast::Attribute]) -> bool +{ b.map(|ast::Block {id, view_items, stmts, expr, rules, span}| { let resulting_stmts: Vec<P<ast::Stmt>> = stmts.into_iter().filter(|a| retain_stmt(cx, &**a)).collect(); @@ -212,7 +236,9 @@ fn fold_block(cx: &mut Context, b: P<ast::Block>) -> P<ast::Block> { }) } -fn fold_expr(cx: &mut Context, expr: P<ast::Expr>) -> P<ast::Expr> { +fn fold_expr<F>(cx: &mut Context<F>, expr: P<ast::Expr>) -> P<ast::Expr> where + F: FnMut(&[ast::Attribute]) -> bool +{ expr.map(|ast::Expr {id, span, node}| { fold::noop_fold_expr(ast::Expr { id: id, @@ -229,19 +255,27 @@ fn fold_expr(cx: &mut Context, expr: P<ast::Expr>) -> P<ast::Expr> { }) } -fn item_in_cfg(cx: &mut Context, item: &ast::Item) -> bool { +fn item_in_cfg<F>(cx: &mut Context<F>, item: &ast::Item) -> bool where + F: FnMut(&[ast::Attribute]) -> bool +{ return (cx.in_cfg)(item.attrs.as_slice()); } -fn foreign_item_in_cfg(cx: &mut Context, item: &ast::ForeignItem) -> bool { +fn foreign_item_in_cfg<F>(cx: &mut Context<F>, item: &ast::ForeignItem) -> bool where + F: FnMut(&[ast::Attribute]) -> bool +{ return (cx.in_cfg)(item.attrs.as_slice()); } -fn view_item_in_cfg(cx: &mut Context, item: &ast::ViewItem) -> bool { +fn view_item_in_cfg<F>(cx: &mut Context<F>, item: &ast::ViewItem) -> bool where + F: FnMut(&[ast::Attribute]) -> bool +{ return (cx.in_cfg)(item.attrs.as_slice()); } -fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool { +fn trait_method_in_cfg<F>(cx: &mut Context<F>, meth: &ast::TraitItem) -> bool where + F: FnMut(&[ast::Attribute]) -> bool +{ match *meth { ast::RequiredMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()), ast::ProvidedMethod(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()), @@ -249,7 +283,9 @@ fn trait_method_in_cfg(cx: &mut Context, meth: &ast::TraitItem) -> bool { } } -fn impl_item_in_cfg(cx: &mut Context, impl_item: &ast::ImplItem) -> bool { +fn impl_item_in_cfg<F>(cx: &mut Context<F>, impl_item: &ast::ImplItem) -> bool where + F: FnMut(&[ast::Attribute]) -> bool +{ match *impl_item { ast::MethodImplItem(ref meth) => (cx.in_cfg)(meth.attrs.as_slice()), ast::TypeImplItem(ref typ) => (cx.in_cfg)(typ.attrs.as_slice()), @@ -273,4 +309,3 @@ fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attr attr::cfg_matches(diagnostic, cfg, &*mis[0]) }) } - diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index ff600fcc7c2..88dfdf6e2d8 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -28,7 +28,7 @@ use term; /// maximum number of lines we will print for each error; arbitrary. static MAX_LINES: uint = 6u; -#[deriving(Clone)] +#[deriving(Clone, Copy)] pub enum RenderSpan { /// A FullSpan renders with both with an initial line for the /// message, prefixed by file:linenum, followed by a summary of @@ -54,7 +54,7 @@ impl RenderSpan { } } -#[deriving(Clone)] +#[deriving(Clone, Copy)] pub enum ColorConfig { Auto, Always, @@ -71,10 +71,12 @@ pub trait Emitter { /// This structure is used to signify that a task has panicked with a fatal error /// from the diagnostics. You can use this with the `Any` trait to figure out /// how a rustc task died (if so desired). +#[deriving(Copy)] pub struct FatalError; /// Signifies that the compiler died with an explicit call to `.bug` /// or `.span_bug` rather than a failed assertion, etc. +#[deriving(Copy)] pub struct ExplicitBug; /// A span-handler is like a handler but also @@ -121,7 +123,7 @@ impl SpanHandler { panic!(ExplicitBug); } pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! { - self.span_bug(sp, format!("unimplemented {}", msg).as_slice()); + self.span_bug(sp, format!("unimplemented {}", msg)[]); } pub fn handler<'a>(&'a self) -> &'a Handler { &self.handler @@ -164,7 +166,7 @@ impl Handler { self.err_count.get()); } } - self.fatal(s.as_slice()); + self.fatal(s[]); } pub fn warn(&self, msg: &str) { self.emit.borrow_mut().emit(None, msg, None, Warning); @@ -180,7 +182,7 @@ impl Handler { panic!(ExplicitBug); } pub fn unimpl(&self, msg: &str) -> ! { - self.bug(format!("unimplemented {}", msg).as_slice()); + self.bug(format!("unimplemented {}", msg)[]); } pub fn emit(&self, cmsp: Option<(&codemap::CodeMap, Span)>, @@ -220,7 +222,7 @@ pub fn mk_handler(e: Box<Emitter + Send>) -> Handler { } } -#[deriving(PartialEq, Clone)] +#[deriving(Copy, PartialEq, Clone)] pub enum Level { Bug, Fatal, @@ -275,7 +277,7 @@ fn print_maybe_styled(w: &mut EmitterWriter, // to be miscolored. We assume this is rare enough that we don't // have to worry about it. if msg.ends_with("\n") { - try!(t.write_str(msg.slice_to(msg.len()-1))); + try!(t.write_str(msg[0..msg.len()-1])); try!(t.reset()); try!(t.write_str("\n")); } else { @@ -297,16 +299,16 @@ fn print_diagnostic(dst: &mut EmitterWriter, topic: &str, lvl: Level, } try!(print_maybe_styled(dst, - format!("{}: ", lvl.to_string()).as_slice(), + format!("{}: ", lvl.to_string())[], term::attr::ForegroundColor(lvl.color()))); try!(print_maybe_styled(dst, - format!("{}", msg).as_slice(), + format!("{}", msg)[], term::attr::Bold)); match code { Some(code) => { let style = term::attr::ForegroundColor(term::color::BRIGHT_MAGENTA); - try!(print_maybe_styled(dst, format!(" [{}]", code.clone()).as_slice(), style)); + try!(print_maybe_styled(dst, format!(" [{}]", code.clone())[], style)); } None => () } @@ -396,12 +398,12 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, // the span) let span_end = Span { lo: sp.hi, hi: sp.hi, expn_id: sp.expn_id}; let ses = cm.span_to_string(span_end); - try!(print_diagnostic(dst, ses.as_slice(), lvl, msg, code)); + try!(print_diagnostic(dst, ses[], lvl, msg, code)); if rsp.is_full_span() { try!(custom_highlight_lines(dst, cm, sp, lvl, lines)); } } else { - try!(print_diagnostic(dst, ss.as_slice(), lvl, msg, code)); + try!(print_diagnostic(dst, ss[], lvl, msg, code)); if rsp.is_full_span() { try!(highlight_lines(dst, cm, sp, lvl, lines)); } @@ -411,9 +413,9 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, Some(code) => match dst.registry.as_ref().and_then(|registry| registry.find_description(code)) { Some(_) => { - try!(print_diagnostic(dst, ss.as_slice(), Help, + try!(print_diagnostic(dst, ss[], Help, format!("pass `--explain {}` to see a detailed \ - explanation", code).as_slice(), None)); + explanation", code)[], None)); } None => () }, @@ -430,15 +432,17 @@ fn highlight_lines(err: &mut EmitterWriter, let fm = &*lines.file; let mut elided = false; - let mut display_lines = lines.lines.as_slice(); + let mut display_lines = lines.lines[]; if display_lines.len() > MAX_LINES { display_lines = display_lines[0u..MAX_LINES]; elided = true; } // Print the offending lines - for line in display_lines.iter() { - try!(write!(&mut err.dst, "{}:{} {}\n", fm.name, *line + 1, - fm.get_line(*line as int))); + for &line_number in display_lines.iter() { + if let Some(line) = fm.get_line(line_number) { + try!(write!(&mut err.dst, "{}:{} {}\n", fm.name, + line_number + 1, line)); + } } if elided { let last_line = display_lines[display_lines.len() - 1u]; @@ -465,30 +469,32 @@ fn highlight_lines(err: &mut EmitterWriter, for _ in range(0, skip) { s.push(' '); } - let orig = fm.get_line(lines.lines[0] as int); - for pos in range(0u, left-skip) { - let cur_char = orig.as_bytes()[pos] as char; - // Whenever a tab occurs on the previous line, we insert one on - // the error-point-squiggly-line as well (instead of a space). - // That way the squiggly line will usually appear in the correct - // position. - match cur_char { - '\t' => s.push('\t'), - _ => s.push(' '), - }; + if let Some(orig) = fm.get_line(lines.lines[0]) { + for pos in range(0u, left - skip) { + let cur_char = orig.as_bytes()[pos] as char; + // Whenever a tab occurs on the previous line, we insert one on + // the error-point-squiggly-line as well (instead of a space). + // That way the squiggly line will usually appear in the correct + // position. + match cur_char { + '\t' => s.push('\t'), + _ => s.push(' '), + }; + } } + try!(write!(&mut err.dst, "{}", s)); let mut s = String::from_str("^"); let hi = cm.lookup_char_pos(sp.hi); if hi.col != lo.col { // the ^ already takes up one space - let num_squigglies = hi.col.to_uint()-lo.col.to_uint()-1u; + let num_squigglies = hi.col.to_uint() - lo.col.to_uint() - 1u; for _ in range(0, num_squigglies) { s.push('~'); } } try!(print_maybe_styled(err, - format!("{}\n", s).as_slice(), + format!("{}\n", s)[], term::attr::ForegroundColor(lvl.color()))); } Ok(()) @@ -508,18 +514,24 @@ fn custom_highlight_lines(w: &mut EmitterWriter, -> io::IoResult<()> { let fm = &*lines.file; - let lines = lines.lines.as_slice(); + let lines = lines.lines[]; if lines.len() > MAX_LINES { - try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, - lines[0] + 1, fm.get_line(lines[0] as int))); + if let Some(line) = fm.get_line(lines[0]) { + try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, + lines[0] + 1, line)); + } try!(write!(&mut w.dst, "...\n")); - let last_line = lines[lines.len()-1]; - try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, - last_line + 1, fm.get_line(last_line as int))); - } else { - for line in lines.iter() { + let last_line_number = lines[lines.len() - 1]; + if let Some(last_line) = fm.get_line(last_line_number) { try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, - *line + 1, fm.get_line(*line as int))); + last_line_number + 1, last_line)); + } + } else { + for &line_number in lines.iter() { + if let Some(line) = fm.get_line(line_number) { + try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, + line_number + 1, line)); + } } } let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1]+1); @@ -533,7 +545,7 @@ fn custom_highlight_lines(w: &mut EmitterWriter, s.push('^'); s.push('\n'); print_maybe_styled(w, - s.as_slice(), + s[], term::attr::ForegroundColor(lvl.color())) } @@ -548,12 +560,12 @@ fn print_macro_backtrace(w: &mut EmitterWriter, codemap::MacroAttribute => ("#[", "]"), codemap::MacroBang => ("", "!") }; - try!(print_diagnostic(w, ss.as_slice(), Note, + try!(print_diagnostic(w, ss[], Note, format!("in expansion of {}{}{}", pre, ei.callee.name, - post).as_slice(), None)); + post)[], None)); let ss = cm.span_to_string(ei.call_site); - try!(print_diagnostic(w, ss.as_slice(), Note, "expansion site", None)); + try!(print_diagnostic(w, ss[], Note, "expansion site", None)); Ok(Some(ei.call_site)) } None => Ok(None) @@ -561,9 +573,11 @@ fn print_macro_backtrace(w: &mut EmitterWriter, cs.map_or(Ok(()), |call_site| print_macro_backtrace(w, cm, call_site)) } -pub fn expect<T>(diag: &SpanHandler, opt: Option<T>, msg: || -> String) -> T { +pub fn expect<T, M>(diag: &SpanHandler, opt: Option<T>, msg: M) -> T where + M: FnOnce() -> String, +{ match opt { Some(t) => t, - None => diag.handler().bug(msg().as_slice()), + None => diag.handler().bug(msg()[]), } } diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs index b4bf793d4e1..3107508a96a 100644 --- a/src/libsyntax/diagnostics/macros.rs +++ b/src/libsyntax/diagnostics/macros.rs @@ -11,44 +11,45 @@ #![macro_escape] #[macro_export] -macro_rules! register_diagnostic( - ($code:tt, $description:tt) => (__register_diagnostic!($code, $description)); - ($code:tt) => (__register_diagnostic!($code)) -) +macro_rules! register_diagnostic { + ($code:tt, $description:tt) => (__register_diagnostic! { $code, $description }); + ($code:tt) => (__register_diagnostic! { $code }) +} #[macro_export] -macro_rules! span_err( +macro_rules! span_err { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ __diagnostic_used!($code); $session.span_err_with_code($span, format!($($message)*).as_slice(), stringify!($code)) }) -) +} #[macro_export] -macro_rules! span_warn( +macro_rules! span_warn { ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({ __diagnostic_used!($code); $session.span_warn_with_code($span, format!($($message)*).as_slice(), stringify!($code)) }) -) +} #[macro_export] -macro_rules! span_note( +macro_rules! span_note { ($session:expr, $span:expr, $($message:tt)*) => ({ ($session).span_note($span, format!($($message)*).as_slice()) }) -) +} #[macro_export] -macro_rules! span_help( +macro_rules! span_help { ($session:expr, $span:expr, $($message:tt)*) => ({ ($session).span_help($span, format!($($message)*).as_slice()) }) -) +} #[macro_export] -macro_rules! register_diagnostics( +macro_rules! register_diagnostics { ($($code:tt),*) => ( - $(register_diagnostic!($code))* + $(register_diagnostic! { $code })* ) -) +} + diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 281bde3129a..90fc28014e6 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -18,33 +18,33 @@ use ext::build::AstBuilder; use parse::token; use ptr::P; -local_data_key!(registered_diagnostics: RefCell<HashMap<Name, Option<Name>>>) -local_data_key!(used_diagnostics: RefCell<HashMap<Name, Span>>) - -fn with_registered_diagnostics<T>(f: |&mut HashMap<Name, Option<Name>>| -> T) -> T { - match registered_diagnostics.get() { - Some(cell) => f(cell.borrow_mut().deref_mut()), - None => { - let mut map = HashMap::new(); - let value = f(&mut map); - registered_diagnostics.replace(Some(RefCell::new(map))); - value - } +thread_local! { + static REGISTERED_DIAGNOSTICS: RefCell<HashMap<Name, Option<Name>>> = { + RefCell::new(HashMap::new()) } } - -fn with_used_diagnostics<T>(f: |&mut HashMap<Name, Span>| -> T) -> T { - match used_diagnostics.get() { - Some(cell) => f(cell.borrow_mut().deref_mut()), - None => { - let mut map = HashMap::new(); - let value = f(&mut map); - used_diagnostics.replace(Some(RefCell::new(map))); - value - } +thread_local! { + static USED_DIAGNOSTICS: RefCell<HashMap<Name, Span>> = { + RefCell::new(HashMap::new()) } } +fn with_registered_diagnostics<T, F>(f: F) -> T where + F: FnOnce(&mut HashMap<Name, Option<Name>>) -> T, +{ + REGISTERED_DIAGNOSTICS.with(move |slot| { + f(&mut *slot.borrow_mut()) + }) +} + +fn with_used_diagnostics<T, F>(f: F) -> T where + F: FnOnce(&mut HashMap<Name, Span>) -> T, +{ + USED_DIAGNOSTICS.with(move |slot| { + f(&mut *slot.borrow_mut()) + }) +} + pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, span: Span, token_tree: &[TokenTree]) @@ -53,21 +53,12 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, [ast::TtToken(_, token::Ident(code, _))] => code, _ => unreachable!() }; - with_registered_diagnostics(|diagnostics| { - if !diagnostics.contains_key(&code.name) { - ecx.span_err(span, format!( - "unknown diagnostic code {}; add to librustc/diagnostics.rs", - token::get_ident(code).get() - ).as_slice()); - } - () - }); with_used_diagnostics(|diagnostics| { match diagnostics.insert(code.name, span) { Some(previous_span) => { ecx.span_warn(span, format!( "diagnostic code {} already used", token::get_ident(code).get() - ).as_slice()); + )[]); ecx.span_note(previous_span, "previous invocation"); }, None => () @@ -96,12 +87,12 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, if diagnostics.insert(code.name, description).is_some() { ecx.span_err(span, format!( "diagnostic code {} already registered", token::get_ident(*code).get() - ).as_slice()); + )[]); } }); let sym = Ident::new(token::gensym(( "__register_diagnostic_".to_string() + token::get_ident(*code).get() - ).as_slice())); + )[])); MacItems::new(vec![quote_item!(ecx, mod $sym {}).unwrap()].into_iter()) } @@ -114,25 +105,19 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, _ => unreachable!() }; - let (count, expr) = with_used_diagnostics(|diagnostics_in_use| { + let (count, expr) = with_registered_diagnostics(|diagnostics| { - let descriptions: Vec<P<ast::Expr>> = diagnostics - .iter().filter_map(|(code, description)| { - if !diagnostics_in_use.contains_key(code) { - ecx.span_warn(span, format!( - "diagnostic code {} never used", token::get_name(*code).get() - ).as_slice()); - } - description.map(|description| { - ecx.expr_tuple(span, vec![ - ecx.expr_str(span, token::get_name(*code)), - ecx.expr_str(span, token::get_name(description)) - ]) - }) - }).collect(); + let descriptions: Vec<P<ast::Expr>> = + diagnostics.iter().filter_map(|(code, description)| { + description.map(|description| { + ecx.expr_tuple(span, vec![ + ecx.expr_str(span, token::get_name(*code)), + ecx.expr_str(span, token::get_name(description))]) + }) + }).collect(); (descriptions.len(), ecx.expr_vec(span, descriptions)) - }) - }); + }); + MacItems::new(vec![quote_item!(ecx, pub static $name: [(&'static str, &'static str), ..$count] = $expr; ).unwrap()].into_iter()) diff --git a/src/libsyntax/ext/asm.rs b/src/libsyntax/ext/asm.rs index d04144ef26e..b77b822a6b2 100644 --- a/src/libsyntax/ext/asm.rs +++ b/src/libsyntax/ext/asm.rs @@ -53,7 +53,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let mut asm_str_style = None; let mut outputs = Vec::new(); let mut inputs = Vec::new(); - let mut cons = "".to_string(); + let mut clobs = Vec::new(); let mut volatile = false; let mut alignstack = false; let mut dialect = ast::AsmAtt; @@ -64,7 +64,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) match state { Asm => { let (s, style) = match expr_to_string(cx, p.parse_expr(), - "inline assembly must be a string literal.") { + "inline assembly must be a string literal") { Some((s, st)) => (s, st), // let compilation continue None => return DummyResult::expr(sp), @@ -100,8 +100,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) Some(('=', _)) => None, Some(('+', operand)) => { Some(token::intern_and_get_ident(format!( - "={}", - operand).as_slice())) + "={}", operand)[])) } _ => { cx.span_err(span, "output operand constraint lacks '=' or '+'"); @@ -138,7 +137,6 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) } } Clobbers => { - let mut clobs = Vec::new(); while p.token != token::Eof && p.token != token::Colon && p.token != token::ModSep { @@ -148,26 +146,23 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) } let (s, _str_style) = p.parse_str(); - let clob = format!("~{{{}}}", s); - clobs.push(clob); - if OPTIONS.iter().any(|opt| s.equiv(opt)) { + if OPTIONS.iter().any(|&opt| s == opt) { cx.span_warn(p.last_span, "expected a clobber, found an option"); } + clobs.push(s); } - - cons = clobs.connect(","); } Options => { let (option, _str_style) = p.parse_str(); - if option.equiv(&("volatile")) { + if option == "volatile" { // Indicates that the inline assembly has side effects // and must not be optimized out along with its outputs. volatile = true; - } else if option.equiv(&("alignstack")) { + } else if option == "alignstack" { alignstack = true; - } else if option.equiv(&("intel")) { + } else if option == "intel" { dialect = ast::AsmIntel; } else { cx.span_warn(p.last_span, "unrecognized option"); @@ -216,7 +211,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) asm_str_style: asm_str_style.unwrap(), outputs: outputs, inputs: inputs, - clobbers: token::intern_and_get_ident(cons.as_slice()), + clobbers: clobs, volatile: volatile, alignstack: alignstack, dialect: dialect, diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 1cbc2b98c93..d45871708dc 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -50,7 +50,9 @@ pub trait ItemDecorator { push: |P<ast::Item>|); } -impl ItemDecorator for fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, |P<ast::Item>|) { +impl<F> ItemDecorator for F + where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, &ast::Item, |P<ast::Item>|) +{ fn expand(&self, ecx: &mut ExtCtxt, sp: Span, @@ -70,7 +72,9 @@ pub trait ItemModifier { -> P<ast::Item>; } -impl ItemModifier for fn(&mut ExtCtxt, Span, &ast::MetaItem, P<ast::Item>) -> P<ast::Item> { +impl<F> ItemModifier for F + where F : Fn(&mut ExtCtxt, Span, &ast::MetaItem, P<ast::Item>) -> P<ast::Item> +{ fn expand(&self, ecx: &mut ExtCtxt, span: Span, @@ -93,7 +97,9 @@ pub trait TTMacroExpander { pub type MacroExpanderFn = for<'cx> fn(&'cx mut ExtCtxt, Span, &[ast::TokenTree]) -> Box<MacResult+'cx>; -impl TTMacroExpander for MacroExpanderFn { +impl<F> TTMacroExpander for F + where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, &[ast::TokenTree]) -> Box<MacResult+'cx> +{ fn expand<'cx>(&self, ecx: &'cx mut ExtCtxt, span: Span, @@ -115,13 +121,17 @@ pub trait IdentMacroExpander { pub type IdentMacroExpanderFn = for<'cx> fn(&'cx mut ExtCtxt, Span, ast::Ident, Vec<ast::TokenTree>) -> Box<MacResult+'cx>; -impl IdentMacroExpander for IdentMacroExpanderFn { +impl<F> IdentMacroExpander for F + where F : for<'cx> Fn(&'cx mut ExtCtxt, Span, ast::Ident, + Vec<ast::TokenTree>) -> Box<MacResult+'cx> +{ fn expand<'cx>(&self, cx: &'cx mut ExtCtxt, sp: Span, ident: ast::Ident, token_tree: Vec<ast::TokenTree> ) - -> Box<MacResult+'cx> { + -> Box<MacResult+'cx> + { (*self)(cx, sp, ident, token_tree) } } @@ -210,7 +220,7 @@ pub struct MacItems { } impl MacItems { - pub fn new<I: Iterator<P<ast::Item>>>(mut it: I) -> Box<MacResult+'static> { + pub fn new<I: Iterator<P<ast::Item>>>(it: I) -> Box<MacResult+'static> { box MacItems { items: it.collect() } as Box<MacResult+'static> } } @@ -223,6 +233,7 @@ impl MacResult for MacItems { /// Fill-in macro expansion result, to allow compilation to continue /// after hitting errors. +#[deriving(Copy)] pub struct DummyResult { expr_only: bool, span: Span @@ -466,8 +477,8 @@ pub struct ExtCtxt<'a> { } impl<'a> ExtCtxt<'a> { - pub fn new<'a>(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig, - ecfg: expand::ExpansionConfig) -> ExtCtxt<'a> { + pub fn new(parse_sess: &'a parse::ParseSess, cfg: ast::CrateConfig, + ecfg: expand::ExpansionConfig) -> ExtCtxt<'a> { let env = initial_syntax_expander_table(&ecfg); ExtCtxt { parse_sess: parse_sess, @@ -489,7 +500,7 @@ impl<'a> ExtCtxt<'a> { /// Returns a `Folder` for deeply expanding all macros in a AST node. pub fn expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> { - expand::MacroExpander { cx: self } + expand::MacroExpander::new(self) } pub fn new_parser_from_tts(&self, tts: &[ast::TokenTree]) @@ -527,7 +538,7 @@ impl<'a> ExtCtxt<'a> { let mut call_site = None; loop { let expn_info = self.codemap().with_expn_info(expn_id, |ei| { - ei.map(|ei| (ei.call_site, ei.callee.name.as_slice() == "include")) + ei.map(|ei| (ei.call_site, ei.callee.name == "include")) }); match expn_info { None => break, @@ -548,7 +559,7 @@ impl<'a> ExtCtxt<'a> { pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); } pub fn mod_path(&self) -> Vec<ast::Ident> { let mut v = Vec::new(); - v.push(token::str_to_ident(self.ecfg.crate_name.as_slice())); + v.push(token::str_to_ident(self.ecfg.crate_name[])); v.extend(self.mod_path.iter().map(|a| *a)); return v; } @@ -557,7 +568,7 @@ impl<'a> ExtCtxt<'a> { if self.recursion_count > self.ecfg.recursion_limit { self.span_fatal(ei.call_site, format!("recursion limit reached while expanding the macro `{}`", - ei.callee.name).as_slice()); + ei.callee.name)[]); } let mut call_site = ei.call_site; @@ -668,7 +679,7 @@ pub fn check_zero_tts(cx: &ExtCtxt, tts: &[ast::TokenTree], name: &str) { if tts.len() != 0 { - cx.span_err(sp, format!("{} takes no arguments", name).as_slice()); + cx.span_err(sp, format!("{} takes no arguments", name)[]); } } @@ -681,12 +692,12 @@ pub fn get_single_str_from_tts(cx: &mut ExtCtxt, -> Option<String> { let mut p = cx.new_parser_from_tts(tts); if p.token == token::Eof { - cx.span_err(sp, format!("{} takes 1 argument", name).as_slice()); + cx.span_err(sp, format!("{} takes 1 argument", name)[]); return None } let ret = cx.expander().fold_expr(p.parse_expr()); if p.token != token::Eof { - cx.span_err(sp, format!("{} takes 1 argument", name).as_slice()); + cx.span_err(sp, format!("{} takes 1 argument", name)[]); } expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| { s.get().to_string() diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index b18a0c8411c..77165168746 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -37,14 +37,16 @@ pub trait AstBuilder { global: bool, idents: Vec<ast::Ident> , lifetimes: Vec<ast::Lifetime>, - types: Vec<P<ast::Ty>> ) + types: Vec<P<ast::Ty>>, + bindings: Vec<P<ast::TypeBinding>> ) -> ast::Path; // types 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, @@ -292,20 +294,21 @@ 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()) + self.path_all(span, false, strs, Vec::new(), Vec::new(), Vec::new()) } 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()) + self.path_all(span, true, strs, Vec::new(), Vec::new(), Vec::new()) } fn path_all(&self, sp: Span, global: bool, mut idents: Vec<ast::Ident> , lifetimes: Vec<ast::Lifetime>, - types: Vec<P<ast::Ty>> ) + types: Vec<P<ast::Ty>>, + bindings: Vec<P<ast::TypeBinding>> ) -> ast::Path { let last_identifier = idents.pop().unwrap(); let mut segments: Vec<ast::PathSegment> = idents.into_iter() @@ -320,6 +323,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: OwnedSlice::from_vec(types), + bindings: OwnedSlice::from_vec(bindings), }) }); ast::Path { @@ -344,17 +348,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 +394,8 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.ident_of("Option") ), Vec::new(), - vec!( ty )), None) + vec!( ty ), + Vec::new())) } fn ty_field_imm(&self, span: Span, name: Ident, ty: P<ast::Ty>) -> ast::TypeField { @@ -425,8 +434,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 { @@ -577,7 +588,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { }; let id = Spanned { node: ident, span: field_span }; - self.expr(sp, ast::ExprField(expr, id, Vec::new())) + self.expr(sp, ast::ExprField(expr, id)) } fn expr_tup_field_access(&self, sp: Span, expr: P<ast::Expr>, idx: uint) -> P<ast::Expr> { let field_span = Span { @@ -587,7 +598,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { }; let id = Spanned { node: idx, span: field_span }; - self.expr(sp, ast::ExprTupField(expr, id, Vec::new())) + self.expr(sp, ast::ExprTupField(expr, id)) } fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> { self.expr(sp, ast::ExprAddrOf(ast::MutImmutable, e)) @@ -673,6 +684,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let some = vec!( self.ident_of("std"), self.ident_of("option"), + self.ident_of("Option"), self.ident_of("Some")); self.expr_call_global(sp, some, vec!(expr)) } @@ -681,6 +693,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let none = self.path_global(sp, vec!( self.ident_of("std"), self.ident_of("option"), + self.ident_of("Option"), self.ident_of("None"))); self.expr_path(none) } @@ -699,8 +712,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let loc = self.codemap().lookup_char_pos(span.lo); let expr_file = self.expr_str(span, token::intern_and_get_ident(loc.file - .name - .as_slice())); + .name[])); let expr_line = self.expr_uint(span, loc.line); let expr_file_line_tuple = self.expr_tuple(span, vec!(expr_file, expr_line)); let expr_file_line_ptr = self.expr_addr_of(span, expr_file_line_tuple); @@ -725,6 +737,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let ok = vec!( self.ident_of("std"), self.ident_of("result"), + self.ident_of("Result"), self.ident_of("Ok")); self.expr_call_global(sp, ok, vec!(expr)) } @@ -733,6 +746,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let err = vec!( self.ident_of("std"), self.ident_of("result"), + self.ident_of("Result"), self.ident_of("Err")); self.expr_call_global(sp, err, vec!(expr)) } @@ -803,6 +817,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let some = vec!( self.ident_of("std"), self.ident_of("option"), + self.ident_of("Option"), self.ident_of("Some")); let path = self.path_global(span, some); self.pat_enum(span, path, vec!(pat)) @@ -812,6 +827,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let some = vec!( self.ident_of("std"), self.ident_of("option"), + self.ident_of("Option"), self.ident_of("None")); let path = self.path_global(span, some); self.pat_enum(span, path, vec!()) @@ -821,6 +837,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let some = vec!( self.ident_of("std"), self.ident_of("result"), + self.ident_of("Result"), self.ident_of("Ok")); let path = self.path_global(span, some); self.pat_enum(span, path, vec!(pat)) @@ -830,6 +847,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let some = vec!( self.ident_of("std"), self.ident_of("result"), + self.ident_of("Result"), self.ident_of("Err")); let path = self.path_global(span, some); self.pat_enum(span, path, vec!(pat)) @@ -849,7 +867,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: Vec<ast::Arm>) -> P<Expr> { - self.expr(span, ast::ExprMatch(arg, arms, ast::MatchNormal)) + self.expr(span, ast::ExprMatch(arg, arms, ast::MatchSource::Normal)) } fn expr_if(&self, span: Span, cond: P<ast::Expr>, @@ -950,7 +968,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { name, Vec::new(), ast::ItemFn(self.fn_decl(inputs, output), - ast::NormalFn, + ast::Unsafety::Normal, abi::Rust, generics, body)) diff --git a/src/libsyntax/ext/concat.rs b/src/libsyntax/ext/concat.rs index e2867c2fbab..03dd08fdf7f 100644 --- a/src/libsyntax/ext/concat.rs +++ b/src/libsyntax/ext/concat.rs @@ -40,14 +40,14 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, ast::LitInt(i, ast::UnsignedIntLit(_)) | ast::LitInt(i, ast::SignedIntLit(_, ast::Plus)) | ast::LitInt(i, ast::UnsuffixedIntLit(ast::Plus)) => { - accumulator.push_str(format!("{}", i).as_slice()); + accumulator.push_str(format!("{}", i)[]); } ast::LitInt(i, ast::SignedIntLit(_, ast::Minus)) | ast::LitInt(i, ast::UnsuffixedIntLit(ast::Minus)) => { - accumulator.push_str(format!("-{}", i).as_slice()); + accumulator.push_str(format!("-{}", i)[]); } ast::LitBool(b) => { - accumulator.push_str(format!("{}", b).as_slice()); + accumulator.push_str(format!("{}", b)[]); } ast::LitByte(..) | ast::LitBinary(..) => { @@ -62,5 +62,5 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, } base::MacExpr::new(cx.expr_str( sp, - token::intern_and_get_ident(accumulator.as_slice()))) + token::intern_and_get_ident(accumulator[]))) } diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index aa18b1be31a..2cf60d30a1b 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -40,7 +40,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree] } } } - let res = str_to_ident(res_str.as_slice()); + let res = str_to_ident(res_str[]); let e = P(ast::Expr { id: ast::DUMMY_NODE_ID, diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs index 0595b0bc7f4..c27a27fce6a 100644 --- a/src/libsyntax/ext/deriving/bounds.rs +++ b/src/libsyntax/ext/deriving/bounds.rs @@ -15,12 +15,13 @@ use ext::deriving::generic::*; use ext::deriving::generic::ty::*; use ptr::P; -pub fn expand_deriving_bound(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { - +pub fn expand_deriving_bound<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ let name = match mitem.node { MetaWord(ref tname) => { match tname.get() { @@ -30,8 +31,7 @@ pub fn expand_deriving_bound(cx: &mut ExtCtxt, ref tname => { cx.span_bug(span, format!("expected built-in trait name but \ - found {}", - *tname).as_slice()) + found {}", *tname)[]) } } }, diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index fccc67bf220..eedec6f37c8 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_clone(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_clone<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { @@ -60,7 +62,7 @@ fn cs_clone( cx.ident_of("Clone"), cx.ident_of("clone"), ]; - let subcall = |field: &FieldInfo| { + let subcall = |&: field: &FieldInfo| { let args = vec![cx.expr_addr_of(field.span, field.self_.clone())]; cx.expr_call_global(field.span, fn_path.clone(), args) @@ -78,13 +80,11 @@ fn cs_clone( EnumNonMatchingCollapsed (..) => { cx.span_bug(trait_span, format!("non-matching enum variants in \ - `deriving({})`", - name).as_slice()) + `deriving({})`", name)[]) } StaticEnum(..) | StaticStruct(..) => { cx.span_bug(trait_span, - format!("static method in `deriving({})`", - name).as_slice()) + format!("static method in `deriving({})`", name)[]) } } @@ -101,8 +101,7 @@ fn cs_clone( None => { cx.span_bug(trait_span, format!("unnamed field in normal struct in \ - `deriving({})`", - name).as_slice()) + `deriving({})`", name)[]) } }; cx.field_imm(field.span, ident, subcall(field)) diff --git a/src/libsyntax/ext/deriving/cmp/eq.rs b/src/libsyntax/ext/deriving/cmp/eq.rs index 7727bb824db..c8bf5ec326c 100644 --- a/src/libsyntax/ext/deriving/cmp/eq.rs +++ b/src/libsyntax/ext/deriving/cmp/eq.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_eq(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_eq<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ // structures are equal if all fields are equal, and non equal, if // any fields are not equal or if the enum variants are different fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { diff --git a/src/libsyntax/ext/deriving/cmp/ord.rs b/src/libsyntax/ext/deriving/cmp/ord.rs index 98345e1dd67..10e14e0c975 100644 --- a/src/libsyntax/ext/deriving/cmp/ord.rs +++ b/src/libsyntax/ext/deriving/cmp/ord.rs @@ -20,11 +20,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_ord(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_ord<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ macro_rules! md ( ($name:expr, $op:expr, $equal:expr) => { { let inline = cx.meta_word(span, InternedString::new("inline")); @@ -81,6 +83,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, trait_def.expand(cx, mitem, item, push) } +#[deriving(Copy)] pub enum OrderingOp { PartialCmpOp, LtOp, LeOp, GtOp, GeOp, } @@ -105,6 +108,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, let ordering = cx.path_global(span, vec!(cx.ident_of("std"), cx.ident_of("cmp"), + cx.ident_of("Ordering"), cx.ident_of("Equal"))); let ordering = cx.expr_path(ordering); let equals_expr = cx.expr_some(span, ordering); @@ -120,9 +124,9 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, Builds: let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1); - if __test == ::std::option::Some(::std::cmp::Equal) { + if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) { let __test = ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2); - if __test == ::std::option::Some(::std::cmp::Equal) { + if __test == ::std::option::Option::Some(::std::cmp::Ordering::Equal) { ... } else { __test @@ -139,7 +143,7 @@ pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, false, |cx, span, old, self_f, other_fs| { // let __test = new; - // if __test == Some(::std::cmp::Equal) { + // if __test == Some(::std::cmp::Ordering::Equal) { // old // } else { // __test diff --git a/src/libsyntax/ext/deriving/cmp/totaleq.rs b/src/libsyntax/ext/deriving/cmp/totaleq.rs index ecee2008254..2b986bea122 100644 --- a/src/libsyntax/ext/deriving/cmp/totaleq.rs +++ b/src/libsyntax/ext/deriving/cmp/totaleq.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_totaleq(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_totaleq<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> { cs_same_method(|cx, span, exprs| { // create `a.<method>(); b.<method>(); c.<method>(); ...` diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index d84ad677e5d..65a4c569b44 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -18,11 +18,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_totalord(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_totalord<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { @@ -64,15 +66,23 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, let equals_path = cx.path_global(span, vec!(cx.ident_of("std"), cx.ident_of("cmp"), + cx.ident_of("Ordering"), cx.ident_of("Equal"))); + let cmp_path = vec![ + cx.ident_of("std"), + cx.ident_of("cmp"), + cx.ident_of("Ord"), + cx.ident_of("cmp"), + ]; + /* Builds: - let __test = self_field1.cmp(&other_field2); - if other == ::std::cmp::Equal { - let __test = self_field2.cmp(&other_field2); - if __test == ::std::cmp::Equal { + let __test = ::std::cmp::Ord::cmp(&self_field1, &other_field1); + if other == ::std::cmp::Ordering::Equal { + let __test = ::std::cmp::Ord::cmp(&self_field2, &other_field2); + if __test == ::std::cmp::Ordering::Equal { ... } else { __test @@ -83,18 +93,32 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, FIXME #6449: These `if`s could/should be `match`es. */ - cs_same_method_fold( + cs_fold( // foldr nests the if-elses correctly, leaving the first field // as the outermost one, and the last as the innermost. false, - |cx, span, old, new| { + |cx, span, old, self_f, other_fs| { // let __test = new; - // if __test == ::std::cmp::Equal { + // if __test == ::std::cmp::Ordering::Equal { // old // } else { // __test // } + let new = { + let other_f = match other_fs { + [ref o_f] => o_f, + _ => cx.span_bug(span, "not exactly 2 arguments in `deriving(PartialOrd)`"), + }; + + let args = vec![ + cx.expr_addr_of(span, self_f), + cx.expr_addr_of(span, other_f.clone()), + ]; + + cx.expr_call_global(span, cmp_path.clone(), args) + }; + let assign = cx.stmt_let(span, false, test_id, new); let cond = cx.expr_binary(span, ast::BiEq, diff --git a/src/libsyntax/ext/deriving/decodable.rs b/src/libsyntax/ext/deriving/decodable.rs index d0a03658386..57dfbc0c6e8 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}; @@ -24,22 +21,45 @@ use parse::token::InternedString; use parse::token; use ptr::P; -pub fn expand_deriving_decodable(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_rustc_decodable<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ + expand_deriving_decodable_imp(cx, span, mitem, item, push, "rustc_serialize") +} + +pub fn expand_deriving_decodable<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ + expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize") +} + +fn expand_deriving_decodable_imp<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F, + krate: &'static str) where + F: FnOnce(P<Item>), +{ let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new_(vec!("serialize", "Decodable"), None, + path: Path::new_(vec!(krate, "Decodable"), None, vec!(box Literal(Path::new_local("__D")), box Literal(Path::new_local("__E"))), true), additional_bounds: Vec::new(), generics: LifetimeBounds { lifetimes: Vec::new(), bounds: vec!(("__D", None, vec!(Path::new_( - vec!("serialize", "Decoder"), None, + vec!(krate, "Decoder"), None, vec!(box Literal(Path::new_local("__E"))), true))), ("__E", None, vec!())) }, @@ -55,7 +75,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt, box Literal(Path::new_local("__E"))), true)), attributes: Vec::new(), combine_substructure: combine_substructure(|a, b, c| { - decodable_substructure(a, b, c) + decodable_substructure(a, b, c, krate) }), }) }; @@ -64,9 +84,10 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt, } fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span, - substr: &Substructure) -> P<Expr> { + substr: &Substructure, + krate: &str) -> P<Expr> { let decoder = substr.nonself_args[0].clone(); - let recurse = vec!(cx.ident_of("serialize"), + let recurse = vec!(cx.ident_of(krate), cx.ident_of("Decodable"), cx.ident_of("decode")); // throw an underscore in front to suppress unused variable warnings @@ -158,12 +179,14 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span, /// Create a decoder for a single enum variant/struct: /// - `outer_pat_path` is the path to this enum variant/struct /// - `getarg` should retrieve the `uint`-th field with name `@str`. -fn decode_static_fields(cx: &mut ExtCtxt, - trait_span: Span, - outer_pat_path: ast::Path, - fields: &StaticFields, - getarg: |&mut ExtCtxt, Span, InternedString, uint| -> P<Expr>) - -> P<Expr> { +fn decode_static_fields<F>(cx: &mut ExtCtxt, + trait_span: Span, + outer_pat_path: ast::Path, + fields: &StaticFields, + mut getarg: F) + -> P<Expr> where + F: FnMut(&mut ExtCtxt, Span, InternedString, uint) -> P<Expr>, +{ match *fields { Unnamed(ref fields) => { let path_expr = cx.expr_path(outer_pat_path); @@ -173,7 +196,7 @@ fn decode_static_fields(cx: &mut ExtCtxt, let fields = fields.iter().enumerate().map(|(i, &span)| { getarg(cx, span, token::intern_and_get_ident(format!("_field{}", - i).as_slice()), + i)[]), i) }).collect(); diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index f4a66414d89..b3621490ce3 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_default(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_default<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { diff --git a/src/libsyntax/ext/deriving/encodable.rs b/src/libsyntax/ext/deriving/encodable.rs index 62f3b5d01b4..8bd3df6232c 100644 --- a/src/libsyntax/ext/deriving/encodable.rs +++ b/src/libsyntax/ext/deriving/encodable.rs @@ -97,22 +97,45 @@ use ext::deriving::generic::ty::*; use parse::token; use ptr::P; -pub fn expand_deriving_encodable(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_rustc_encodable<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ + expand_deriving_encodable_imp(cx, span, mitem, item, push, "rustc_serialize") +} + +pub fn expand_deriving_encodable<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ + expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize") +} + +fn expand_deriving_encodable_imp<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F, + krate: &'static str) where + F: FnOnce(P<Item>), +{ let trait_def = TraitDef { span: span, attributes: Vec::new(), - path: Path::new_(vec!("serialize", "Encodable"), None, + path: Path::new_(vec!(krate, "Encodable"), None, vec!(box Literal(Path::new_local("__S")), box Literal(Path::new_local("__E"))), true), additional_bounds: Vec::new(), generics: LifetimeBounds { lifetimes: Vec::new(), bounds: vec!(("__S", None, vec!(Path::new_( - vec!("serialize", "Encoder"), None, + vec!(krate, "Encoder"), None, vec!(box Literal(Path::new_local("__E"))), true))), ("__E", None, vec!())) }, @@ -160,8 +183,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span, let name = match name { Some(id) => token::get_ident(id), None => { - token::intern_and_get_ident(format!("_field{}", - i).as_slice()) + token::intern_and_get_ident(format!("_field{}", i)[]) } }; let enc = cx.expr_method_call(span, self_.clone(), diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index fcd4966683d..cf0201294ae 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -333,11 +333,13 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>) impl<'a> TraitDef<'a> { - pub fn expand(&self, - cx: &mut ExtCtxt, - mitem: &ast::MetaItem, - item: &ast::Item, - push: |P<ast::Item>|) { + pub fn expand<F>(&self, + cx: &mut ExtCtxt, + mitem: &ast::MetaItem, + item: &ast::Item, + push: F) where + F: FnOnce(P<ast::Item>), + { let newitem = match item.node { ast::ItemStruct(ref struct_def, ref generics) => { self.expand_struct_def(cx, @@ -386,7 +388,7 @@ impl<'a> TraitDef<'a> { methods: Vec<P<ast::Method>>) -> P<ast::Item> { let trait_path = self.path.to_path(cx, self.span, type_ident, generics); - let Generics { mut lifetimes, ty_params, where_clause: _ } = + let Generics { mut lifetimes, ty_params, mut where_clause } = self.generics.to_generics(cx, self.span, type_ident, generics); let mut ty_params = ty_params.into_vec(); @@ -418,13 +420,39 @@ impl<'a> TraitDef<'a> { ty_param.unbound.clone(), None) })); + + // and similarly for where clauses + where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| { + match *clause { + ast::WherePredicate::BoundPredicate(ref wb) => { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + span: self.span, + bounded_ty: wb.bounded_ty.clone(), + bounds: OwnedSlice::from_vec(wb.bounds.iter().map(|b| b.clone()).collect()) + }) + } + ast::WherePredicate::RegionPredicate(ref rb) => { + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + span: self.span, + lifetime: rb.lifetime, + bounds: rb.bounds.iter().map(|b| b.clone()).collect() + }) + } + ast::WherePredicate::EqPredicate(ref we) => { + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { + id: ast::DUMMY_NODE_ID, + span: self.span, + path: we.path.clone(), + ty: we.ty.clone() + }) + } + } + })); + let trait_generics = Generics { lifetimes: lifetimes, ty_params: OwnedSlice::from_vec(ty_params), - where_clause: ast::WhereClause { - id: ast::DUMMY_NODE_ID, - predicates: Vec::new(), - }, + where_clause: where_clause }; // Create the reference to the trait. @@ -444,7 +472,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(), Vec::new())); let attr = cx.attribute( self.span, @@ -460,7 +488,8 @@ impl<'a> TraitDef<'a> { self.span, ident, a, - ast::ItemImpl(trait_generics, + ast::ItemImpl(ast::Unsafety::Normal, + trait_generics, opt_trait_ref, self_type, methods.into_iter() @@ -485,15 +514,15 @@ impl<'a> TraitDef<'a> { self, struct_def, type_ident, - self_args.as_slice(), - nonself_args.as_slice()) + self_args[], + nonself_args[]) } else { method_def.expand_struct_method_body(cx, self, struct_def, type_ident, - self_args.as_slice(), - nonself_args.as_slice()) + self_args[], + nonself_args[]) }; method_def.create_method(cx, @@ -525,15 +554,15 @@ impl<'a> TraitDef<'a> { self, enum_def, type_ident, - self_args.as_slice(), - nonself_args.as_slice()) + self_args[], + nonself_args[]) } else { method_def.expand_enum_method_body(cx, self, enum_def, type_ident, self_args, - nonself_args.as_slice()) + nonself_args[]) }; method_def.create_method(cx, @@ -620,7 +649,7 @@ impl<'a> MethodDef<'a> { for (i, ty) in self.args.iter().enumerate() { let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics); - let ident = cx.ident_of(format!("__arg_{}", i).as_slice()); + let ident = cx.ident_of(format!("__arg_{}", i)[]); arg_tys.push((ident, ast_ty)); let arg_expr = cx.expr_ident(trait_.span, ident); @@ -682,7 +711,7 @@ impl<'a> MethodDef<'a> { fn_generics, abi, explicit_self, - ast::NormalFn, + ast::Unsafety::Normal, fn_decl, body_block, ast::Inherited) @@ -727,7 +756,7 @@ impl<'a> MethodDef<'a> { struct_path, struct_def, format!("__self_{}", - i).as_slice(), + i)[], ast::MutImmutable); patterns.push(pat); raw_fields.push(ident_expr); @@ -737,7 +766,7 @@ impl<'a> MethodDef<'a> { let fields = if raw_fields.len() > 0 { let mut raw_fields = raw_fields.into_iter().map(|v| v.into_iter()); let first_field = raw_fields.next().unwrap(); - let mut other_fields: Vec<vec::MoveItems<(Span, Option<Ident>, P<Expr>)>> + let mut other_fields: Vec<vec::IntoIter<(Span, Option<Ident>, P<Expr>)>> = raw_fields.collect(); first_field.map(|(span, opt_id, field)| { FieldInfo { @@ -883,22 +912,22 @@ impl<'a> MethodDef<'a> { .collect::<Vec<String>>(); let self_arg_idents = self_arg_names.iter() - .map(|name|cx.ident_of(name.as_slice())) + .map(|name|cx.ident_of(name[])) .collect::<Vec<ast::Ident>>(); // The `vi_idents` will be bound, solely in the catch-all, to // a series of let statements mapping each self_arg to a uint // corresponding to its variant index. let vi_idents: Vec<ast::Ident> = self_arg_names.iter() - .map(|name| { let vi_suffix = format!("{}_vi", name.as_slice()); - cx.ident_of(vi_suffix.as_slice()) }) + .map(|name| { let vi_suffix = format!("{}_vi", name[]); + cx.ident_of(vi_suffix[]) }) .collect::<Vec<ast::Ident>>(); // Builds, via callback to call_substructure_method, the // delegated expression that handles the catch-all case, // using `__variants_tuple` to drive logic if necessary. let catch_all_substructure = EnumNonMatchingCollapsed( - self_arg_idents, variants.as_slice(), vi_idents.as_slice()); + self_arg_idents, variants[], vi_idents[]); // These arms are of the form: // (Variant1, Variant1, ...) => Body1 @@ -920,12 +949,12 @@ impl<'a> MethodDef<'a> { let mut subpats = Vec::with_capacity(self_arg_names.len()); let mut self_pats_idents = Vec::with_capacity(self_arg_names.len() - 1); let first_self_pat_idents = { - let (p, idents) = mk_self_pat(cx, self_arg_names[0].as_slice()); + let (p, idents) = mk_self_pat(cx, self_arg_names[0][]); subpats.push(p); idents }; for self_arg_name in self_arg_names.tail().iter() { - let (p, idents) = mk_self_pat(cx, self_arg_name.as_slice()); + let (p, idents) = mk_self_pat(cx, self_arg_name[]); subpats.push(p); self_pats_idents.push(idents); } @@ -981,7 +1010,7 @@ impl<'a> MethodDef<'a> { &**variant, field_tuples); let arm_expr = self.call_substructure_method( - cx, trait_, type_ident, self_args.as_slice(), nonself_args, + cx, trait_, type_ident, self_args[], nonself_args, &substructure); cx.arm(sp, vec![single_pat], arm_expr) @@ -1034,7 +1063,7 @@ impl<'a> MethodDef<'a> { } let arm_expr = self.call_substructure_method( - cx, trait_, type_ident, self_args.as_slice(), nonself_args, + cx, trait_, type_ident, self_args[], nonself_args, &catch_all_substructure); // Builds the expression: @@ -1238,7 +1267,7 @@ impl<'a> TraitDef<'a> { cx.span_bug(sp, "a struct with named and unnamed fields in `deriving`"); } }; - let ident = cx.ident_of(format!("{}_{}", prefix, i).as_slice()); + let ident = cx.ident_of(format!("{}_{}", prefix, i)[]); paths.push(codemap::Spanned{span: sp, node: ident}); let val = cx.expr( sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident))))); @@ -1284,7 +1313,7 @@ impl<'a> TraitDef<'a> { let mut ident_expr = Vec::new(); for (i, va) in variant_args.iter().enumerate() { let sp = self.set_expn_info(cx, va.ty.span); - let ident = cx.ident_of(format!("{}_{}", prefix, i).as_slice()); + let ident = cx.ident_of(format!("{}_{}", prefix, i)[]); let path1 = codemap::Spanned{span: sp, node: ident}; paths.push(path1); let expr_path = cx.expr_path(cx.path_ident(sp, ident)); @@ -1309,14 +1338,16 @@ impl<'a> TraitDef<'a> { /// Fold the fields. `use_foldl` controls whether this is done /// left-to-right (`true`) or right-to-left (`false`). -pub fn cs_fold(use_foldl: bool, - f: |&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]| -> P<Expr>, - base: P<Expr>, - enum_nonmatch_f: EnumNonMatchCollapsedFunc, - cx: &mut ExtCtxt, - trait_span: Span, - substructure: &Substructure) - -> P<Expr> { +pub fn cs_fold<F>(use_foldl: bool, + mut f: F, + base: P<Expr>, + enum_nonmatch_f: EnumNonMatchCollapsedFunc, + cx: &mut ExtCtxt, + trait_span: Span, + substructure: &Substructure) + -> P<Expr> where + F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>, +{ match *substructure.fields { EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => { if use_foldl { @@ -1325,7 +1356,7 @@ pub fn cs_fold(use_foldl: bool, field.span, old, field.self_.clone(), - field.other.as_slice()) + field.other[]) }) } else { all_fields.iter().rev().fold(base, |old, field| { @@ -1333,12 +1364,12 @@ pub fn cs_fold(use_foldl: bool, field.span, old, field.self_.clone(), - field.other.as_slice()) + field.other[]) }) } }, EnumNonMatchingCollapsed(ref all_args, _, tuple) => - enum_nonmatch_f(cx, trait_span, (all_args.as_slice(), tuple), + enum_nonmatch_f(cx, trait_span, (all_args[], tuple), substructure.nonself_args), StaticEnum(..) | StaticStruct(..) => { cx.span_bug(trait_span, "static function in `deriving`") @@ -1355,12 +1386,14 @@ pub fn cs_fold(use_foldl: bool, /// self_2.method(__arg_1_2, __arg_2_2)]) /// ``` #[inline] -pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec<P<Expr>>| -> P<Expr>, - enum_nonmatch_f: EnumNonMatchCollapsedFunc, - cx: &mut ExtCtxt, - trait_span: Span, - substructure: &Substructure) - -> P<Expr> { +pub fn cs_same_method<F>(f: F, + enum_nonmatch_f: EnumNonMatchCollapsedFunc, + cx: &mut ExtCtxt, + trait_span: Span, + substructure: &Substructure) + -> P<Expr> where + F: FnOnce(&mut ExtCtxt, Span, Vec<P<Expr>>) -> P<Expr>, +{ match *substructure.fields { EnumMatching(_, _, ref all_fields) | Struct(ref all_fields) => { // call self_n.method(other_1_n, other_2_n, ...) @@ -1376,7 +1409,7 @@ pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec<P<Expr>>| -> P<Expr>, f(cx, trait_span, called) }, EnumNonMatchingCollapsed(ref all_self_args, _, tuple) => - enum_nonmatch_f(cx, trait_span, (all_self_args.as_slice(), tuple), + enum_nonmatch_f(cx, trait_span, (all_self_args[], tuple), substructure.nonself_args), StaticEnum(..) | StaticStruct(..) => { cx.span_bug(trait_span, "static function in `deriving`") @@ -1388,14 +1421,16 @@ pub fn cs_same_method(f: |&mut ExtCtxt, Span, Vec<P<Expr>>| -> P<Expr>, /// fields. `use_foldl` controls whether this is done left-to-right /// (`true`) or right-to-left (`false`). #[inline] -pub fn cs_same_method_fold(use_foldl: bool, - f: |&mut ExtCtxt, Span, P<Expr>, P<Expr>| -> P<Expr>, - base: P<Expr>, - enum_nonmatch_f: EnumNonMatchCollapsedFunc, - cx: &mut ExtCtxt, - trait_span: Span, - substructure: &Substructure) - -> P<Expr> { +pub fn cs_same_method_fold<F>(use_foldl: bool, + mut f: F, + base: P<Expr>, + enum_nonmatch_f: EnumNonMatchCollapsedFunc, + cx: &mut ExtCtxt, + trait_span: Span, + substructure: &Substructure) + -> P<Expr> where + F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>) -> P<Expr>, +{ cs_same_method( |cx, span, vals| { if use_foldl { diff --git a/src/libsyntax/ext/deriving/generic/ty.rs b/src/libsyntax/ext/deriving/generic/ty.rs index 700ada8b4ad..56d11c2377f 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, @@ -82,7 +80,7 @@ impl<'a> Path<'a> { let lt = mk_lifetimes(cx, span, &self.lifetime); let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect(); - cx.path_all(span, self.global, idents, lt, tys) + cx.path_all(span, self.global, idents, lt, tys, Vec::new()) } } @@ -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() @@ -179,7 +177,7 @@ impl<'a> Ty<'a> { .collect(); cx.path_all(span, false, vec!(self_ty), lifetimes, - self_params.into_vec()) + self_params.into_vec(), Vec::new()) } Literal(ref p) => { p.to_path(cx, span, self_ty, self_generics) diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index b7f11c25825..4e59124a129 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_hash(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ let (path, generics, args) = if cx.ecfg.deriving_hash_type_parameter { (Path::new_(vec!("std", "hash", "Hash"), None, diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index b8cebd8ea20..edf29e670eb 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; @@ -75,8 +70,26 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt, "Hash" => expand!(hash::expand_deriving_hash), - "Encodable" => expand!(encodable::expand_deriving_encodable), - "Decodable" => expand!(decodable::expand_deriving_decodable), + "RustcEncodable" => { + expand!(encodable::expand_deriving_rustc_encodable) + } + "RustcDecodable" => { + expand!(decodable::expand_deriving_rustc_decodable) + } + "Encodable" => { + cx.span_warn(titem.span, + "deriving(Encodable) is deprecated \ + in favor of deriving(RustcEncodable)"); + + expand!(encodable::expand_deriving_encodable) + } + "Decodable" => { + cx.span_warn(titem.span, + "deriving(Decodable) is deprecated \ + in favor of deriving(RustcDecodable)"); + + expand!(decodable::expand_deriving_decodable) + } "PartialEq" => expand!(eq::expand_deriving_eq), "Eq" => expand!(totaleq::expand_deriving_totaleq), @@ -100,7 +113,7 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt, cx.span_err(titem.span, format!("unknown `deriving` \ trait: `{}`", - *tname).as_slice()); + *tname)[]); } }; } diff --git a/src/libsyntax/ext/deriving/primitive.rs b/src/libsyntax/ext/deriving/primitive.rs index cd2d98b70f1..8abd846373a 100644 --- a/src/libsyntax/ext/deriving/primitive.rs +++ b/src/libsyntax/ext/deriving/primitive.rs @@ -18,11 +18,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_from_primitive(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 8ad8436906b..4f6e4d1fb3c 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::*; use ext::deriving::generic::ty::*; use ptr::P; -pub fn expand_deriving_rand(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_rand<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ let trait_def = TraitDef { span: span, attributes: Vec::new(), @@ -64,7 +66,7 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) cx.ident_of("Rand"), cx.ident_of("rand") ); - let rand_call = |cx: &mut ExtCtxt, span| { + let mut rand_call = |&mut: cx: &mut ExtCtxt, span| { cx.expr_call_global(span, rand_ident.clone(), vec!(rng.clone())) @@ -88,6 +90,7 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) true, rand_ident.clone(), Vec::new(), + Vec::new(), Vec::new()); let rand_name = cx.expr_path(rand_name); @@ -132,12 +135,14 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) _ => cx.bug("Non-static method in `deriving(Rand)`") }; - fn rand_thing(cx: &mut ExtCtxt, - trait_span: Span, - ctor_path: ast::Path, - summary: &StaticFields, - rand_call: |&mut ExtCtxt, Span| -> P<Expr>) - -> P<Expr> { + fn rand_thing<F>(cx: &mut ExtCtxt, + trait_span: Span, + ctor_path: ast::Path, + summary: &StaticFields, + mut rand_call: F) + -> P<Expr> where + F: FnMut(&mut ExtCtxt, Span) -> P<Expr>, + { let path = cx.expr_path(ctor_path.clone()); match *summary { Unnamed(ref fields) => { diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index 322a84eaa2b..19b45a1e610 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -21,11 +21,13 @@ use ptr::P; use std::collections::HashMap; -pub fn expand_deriving_show(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_show<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ // &mut ::std::fmt::Formatter let fmtr = Ptr(box Literal(Path::new(vec!("std", "fmt", "Formatter"))), Borrowed(None, ast::MutMutable)); @@ -125,7 +127,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, let formatter = substr.nonself_args[0].clone(); let meth = cx.ident_of("write_fmt"); - let s = token::intern_and_get_ident(format_string.as_slice()); + let s = token::intern_and_get_ident(format_string[]); let format_string = cx.expr_str(span, s); // phew, not our responsibility any more! diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs index 7f265b529ff..ea32549cad2 100644 --- a/src/libsyntax/ext/deriving/zero.rs +++ b/src/libsyntax/ext/deriving/zero.rs @@ -17,11 +17,13 @@ use ext::deriving::generic::ty::*; use parse::token::InternedString; use ptr::P; -pub fn expand_deriving_zero(cx: &mut ExtCtxt, - span: Span, - mitem: &MetaItem, - item: &Item, - push: |P<Item>|) { +pub fn expand_deriving_zero<F>(cx: &mut ExtCtxt, + span: Span, + mitem: &MetaItem, + item: &Item, + push: F) where + F: FnOnce(P<Item>), +{ let inline = cx.meta_word(span, InternedString::new("inline")); let attrs = vec!(cx.attribute(span, inline)); let trait_def = TraitDef { diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index 87e257c52cd..9fedc4a158e 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -30,12 +30,13 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT Some(v) => v }; - let e = match os::getenv(var.as_slice()) { + let e = match os::getenv(var[]) { None => { cx.expr_path(cx.path_all(sp, true, vec!(cx.ident_of("std"), cx.ident_of("option"), + cx.ident_of("Option"), cx.ident_of("None")), Vec::new(), vec!(cx.ty_rptr(sp, @@ -44,16 +45,18 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT Some(cx.lifetime(sp, cx.ident_of( "'static").name)), - ast::MutImmutable)))) + ast::MutImmutable)), + Vec::new())) } Some(s) => { cx.expr_call_global(sp, vec!(cx.ident_of("std"), cx.ident_of("option"), + cx.ident_of("Option"), cx.ident_of("Some")), vec!(cx.expr_str(sp, token::intern_and_get_ident( - s.as_slice())))) + s[])))) } }; MacExpr::new(e) @@ -80,7 +83,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) None => { token::intern_and_get_ident(format!("environment variable `{}` \ not defined", - var).as_slice()) + var)[]) } Some(second) => { match expr_to_string(cx, second, "expected string literal") { @@ -103,7 +106,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) cx.span_err(sp, msg.get()); cx.expr_uint(sp, 0) } - Some(s) => cx.expr_str(sp, token::intern_and_get_ident(s.as_slice())) + Some(s) => cx.expr_str(sp, token::intern_and_get_ident(s[])) }; MacExpr::new(e) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 04132679a03..f2b6f6bfe16 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -11,9 +11,11 @@ use self::Either::*; use ast::{Block, Crate, DeclLocal, ExprMac, PatMac}; use ast::{Local, Ident, MacInvocTT}; -use ast::{ItemMac, Mrk, Stmt, StmtDecl, StmtMac, StmtExpr, StmtSemi}; +use ast::{ItemMac, MacStmtWithSemicolon, Mrk, Stmt, StmtDecl, StmtMac}; +use ast::{StmtExpr, StmtSemi}; use ast::TokenTree; use ast; +use ast_util::path_to_ident; use ext::mtwt; use ext::build::AstBuilder; use attr; @@ -36,6 +38,30 @@ enum Either<L,R> { Right(R) } +pub fn expand_type(t: P<ast::Ty>, + fld: &mut MacroExpander, + impl_ty: Option<P<ast::Ty>>) + -> P<ast::Ty> { + debug!("expanding type {} with impl_ty {}", t, impl_ty); + let t = match (t.node.clone(), impl_ty) { + // Expand uses of `Self` in impls to the concrete type. + (ast::Ty_::TyPath(ref path, _), Some(ref impl_ty)) => { + let path_as_ident = path_to_ident(path); + // Note unhygenic comparison here. I think this is correct, since + // even though `Self` is almost just a type parameter, the treatment + // for this expansion is as if it were a keyword. + if path_as_ident.is_some() && + path_as_ident.unwrap().name == token::special_idents::type_self.name { + impl_ty.clone() + } else { + t + } + } + _ => t + }; + fold::noop_fold_ty(t, fld) +} + pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { e.and_then(|ast::Expr {id, node, span}| match node { // expr_mac should really be expr_ext or something; it's the @@ -96,7 +122,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { // `match <expr> { ... }` let arms = vec![pat_arm, break_arm]; let match_expr = fld.cx.expr(span, - ast::ExprMatch(expr, arms, ast::MatchWhileLetDesugar)); + ast::ExprMatch(expr, arms, ast::MatchSource::WhileLetDesugar)); // `[opt_ident]: loop { ... }` let loop_block = fld.cx.block_expr(match_expr); @@ -157,6 +183,8 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { arms }; + let contains_else_clause = elseopt.is_some(); + // `_ => [<elseopt> | ()]` let else_arm = { let pat_under = fld.cx.pat_wild(span); @@ -169,7 +197,11 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { arms.extend(else_if_arms.into_iter()); arms.push(else_arm); - let match_expr = fld.cx.expr(span, ast::ExprMatch(expr, arms, ast::MatchIfLetDesugar)); + let match_expr = fld.cx.expr(span, + ast::ExprMatch(expr, arms, + ast::MatchSource::IfLetDesugar { + contains_else_clause: contains_else_clause, + })); fld.fold_expr(match_expr) } @@ -217,13 +249,6 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { P(ast::Expr{id:id, node: new_node, span: fld.new_span(span)}) } - ast::ExprProc(fn_decl, block) => { - let (rewritten_fn_decl, rewritten_block) - = expand_and_rename_fn_decl_and_block(fn_decl, block, fld); - let new_node = ast::ExprProc(rewritten_fn_decl, rewritten_block); - P(ast::Expr{id:id, node: new_node, span: fld.new_span(span)}) - } - _ => { P(noop_fold_expr(ast::Expr { id: id, @@ -238,11 +263,13 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> { /// of expansion and the mark which must be applied to the result. /// Our current interface doesn't allow us to apply the mark to the /// result until after calling make_expr, make_items, etc. -fn expand_mac_invoc<T>(mac: ast::Mac, span: codemap::Span, - parse_thunk: |Box<MacResult>|->Option<T>, - mark_thunk: |T,Mrk|->T, - fld: &mut MacroExpander) - -> Option<T> +fn expand_mac_invoc<T, F, G>(mac: ast::Mac, span: codemap::Span, + parse_thunk: F, + mark_thunk: G, + fld: &mut MacroExpander) + -> Option<T> where + F: FnOnce(Box<MacResult>) -> Option<T>, + G: FnOnce(T, Mrk) -> T, { match mac.node { // it would almost certainly be cleaner to pass the whole @@ -266,7 +293,7 @@ fn expand_mac_invoc<T>(mac: ast::Mac, span: codemap::Span, fld.cx.span_err( pth.span, format!("macro undefined: '{}!'", - extnamestr.get()).as_slice()); + extnamestr.get())[]); // let compilation continue None @@ -282,7 +309,7 @@ fn expand_mac_invoc<T>(mac: ast::Mac, span: codemap::Span, }, }); let fm = fresh_mark(); - let marked_before = mark_tts(tts.as_slice(), fm); + let marked_before = mark_tts(tts[], fm); // The span that we pass to the expanders we want to // be the root of the call stack. That's the most @@ -293,7 +320,7 @@ fn expand_mac_invoc<T>(mac: ast::Mac, span: codemap::Span, let opt_parsed = { let expanded = expandfun.expand(fld.cx, mac_span, - marked_before.as_slice()); + marked_before[]); parse_thunk(expanded) }; let parsed = match opt_parsed { @@ -302,8 +329,8 @@ fn expand_mac_invoc<T>(mac: ast::Mac, span: codemap::Span, fld.cx.span_err( pth.span, format!("non-expression macro in expression position: {}", - extnamestr.get().as_slice() - ).as_slice()); + extnamestr.get()[] + )[]); return None; } }; @@ -313,7 +340,7 @@ fn expand_mac_invoc<T>(mac: ast::Mac, span: codemap::Span, fld.cx.span_err( pth.span, format!("'{}' is not a tt-style macro", - extnamestr.get()).as_slice()); + extnamestr.get())[]); None } } @@ -359,7 +386,7 @@ fn expand_loop_block(loop_block: P<Block>, // eval $e with a new exts frame. // must be a macro so that $e isn't evaluated too early. -macro_rules! with_exts_frame ( +macro_rules! with_exts_frame { ($extsboxexpr:expr,$macros_escape:expr,$e:expr) => ({$extsboxexpr.push_frame(); $extsboxexpr.info().macros_escape = $macros_escape; @@ -367,7 +394,7 @@ macro_rules! with_exts_frame ( $extsboxexpr.pop_frame(); result }) -) +} // When we enter a module, record it, for the sake of `module!` pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander) @@ -412,12 +439,19 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander) let mut new_items = match it.node { ast::ItemMac(..) => expand_item_mac(it, fld), ast::ItemMod(_) | ast::ItemForeignMod(_) => { - fld.cx.mod_push(it.ident); - let macro_escape = contains_macro_escape(new_attrs.as_slice()); + let valid_ident = + it.ident.name != parse::token::special_idents::invalid.name; + + if valid_ident { + fld.cx.mod_push(it.ident); + } + let macro_escape = contains_macro_escape(new_attrs[]); let result = with_exts_frame!(fld.cx.syntax_env, macro_escape, noop_fold_item(it, fld)); - fld.cx.mod_pop(); + if valid_ident { + fld.cx.mod_pop(); + } result }, _ => { @@ -519,7 +553,7 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) None => { fld.cx.span_err(path_span, format!("macro undefined: '{}!'", - extnamestr).as_slice()); + extnamestr)[]); // let compilation continue return SmallVector::zero(); } @@ -532,7 +566,7 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) format!("macro {}! expects no ident argument, \ given '{}'", extnamestr, - token::get_ident(it.ident)).as_slice()); + token::get_ident(it.ident))[]); return SmallVector::zero(); } fld.cx.bt_push(ExpnInfo { @@ -544,14 +578,14 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) } }); // mark before expansion: - let marked_before = mark_tts(tts.as_slice(), fm); - expander.expand(fld.cx, it.span, marked_before.as_slice()) + let marked_before = mark_tts(tts[], fm); + expander.expand(fld.cx, it.span, marked_before[]) } IdentTT(ref expander, span) => { if it.ident.name == parse::token::special_idents::invalid.name { fld.cx.span_err(path_span, format!("macro {}! expects an ident argument", - extnamestr.get()).as_slice()); + extnamestr.get())[]); return SmallVector::zero(); } fld.cx.bt_push(ExpnInfo { @@ -563,14 +597,14 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) } }); // mark before expansion: - let marked_tts = mark_tts(tts.as_slice(), fm); + let marked_tts = mark_tts(tts[], fm); expander.expand(fld.cx, it.span, it.ident, marked_tts) } LetSyntaxTT(ref expander, span) => { if it.ident.name == parse::token::special_idents::invalid.name { fld.cx.span_err(path_span, format!("macro {}! expects an ident argument", - extnamestr.get()).as_slice()); + extnamestr.get())[]); return SmallVector::zero(); } fld.cx.bt_push(ExpnInfo { @@ -587,7 +621,7 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) _ => { fld.cx.span_err(it.span, format!("{}! is not legal in item position", - extnamestr.get()).as_slice()); + extnamestr.get())[]); return SmallVector::zero(); } } @@ -605,8 +639,8 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) // result of expanding a LetSyntaxTT, and thus doesn't // need to be marked. Not that it could be marked anyway. // create issue to recommend refactoring here? - fld.cx.syntax_env.insert(intern(name.as_slice()), ext); - if attr::contains_name(it.attrs.as_slice(), "macro_export") { + fld.cx.syntax_env.insert(intern(name[]), ext); + if attr::contains_name(it.attrs[], "macro_export") { fld.cx.exported_macros.push(it); } SmallVector::zero() @@ -620,7 +654,7 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) Right(None) => { fld.cx.span_err(path_span, format!("non-item macro in item position: {}", - extnamestr.get()).as_slice()); + extnamestr.get())[]); return SmallVector::zero(); } }; @@ -634,8 +668,8 @@ pub fn expand_item_mac(it: P<ast::Item>, fld: &mut MacroExpander) // I don't understand why this returns a vector... it looks like we're // half done adding machinery to allow macros to expand into multiple statements. fn expand_stmt(s: Stmt, fld: &mut MacroExpander) -> SmallVector<P<Stmt>> { - let (mac, semi) = match s.node { - StmtMac(mac, semi) => (mac, semi), + let (mac, style) = match s.node { + StmtMac(mac, style) => (mac, style), _ => return expand_non_macro_stmt(s, fld) }; let expanded_stmt = match expand_mac_invoc(mac, s.span, @@ -651,7 +685,7 @@ fn expand_stmt(s: Stmt, fld: &mut MacroExpander) -> SmallVector<P<Stmt>> { let fully_expanded = fld.fold_stmt(expanded_stmt); fld.cx.bt_pop(); - if semi { + if style == MacStmtWithSemicolon { fully_expanded.into_iter().map(|s| s.map(|Spanned {node, span}| { Spanned { node: match node { @@ -869,7 +903,7 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> { None => { fld.cx.span_err(pth.span, format!("macro undefined: '{}!'", - extnamestr).as_slice()); + extnamestr)[]); // let compilation continue return DummyResult::raw_pat(span); } @@ -886,11 +920,11 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> { }); let fm = fresh_mark(); - let marked_before = mark_tts(tts.as_slice(), fm); + let marked_before = mark_tts(tts[], fm); let mac_span = fld.cx.original_span(); let expanded = match expander.expand(fld.cx, mac_span, - marked_before.as_slice()).make_pat() { + marked_before[]).make_pat() { Some(e) => e, None => { fld.cx.span_err( @@ -898,7 +932,7 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> { format!( "non-pattern macro in pattern position: {}", extnamestr.get() - ).as_slice() + )[] ); return DummyResult::raw_pat(span); } @@ -910,7 +944,7 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> { _ => { fld.cx.span_err(span, format!("{}! is not legal in pattern position", - extnamestr.get()).as_slice()); + extnamestr.get())[]); return DummyResult::raw_pat(span); } } @@ -1019,16 +1053,17 @@ fn expand_method(m: P<ast::Method>, fld: &mut MacroExpander) -> SmallVector<P<as |meths, mark| meths.move_map(|m| mark_method(m, mark)), fld); - let new_methods = match maybe_new_methods { - Some(methods) => methods, + match maybe_new_methods { + Some(methods) => { + // expand again if necessary + let new_methods = methods.into_iter() + .flat_map(|m| fld.fold_method(m).into_iter()) + .collect(); + fld.cx.bt_pop(); + new_methods + } None => SmallVector::zero() - }; - - // expand again if necessary - let new_methods = new_methods.into_iter() - .flat_map(|m| fld.fold_method(m).into_iter()).collect(); - fld.cx.bt_pop(); - new_methods + } } }) } @@ -1055,6 +1090,14 @@ fn expand_and_rename_fn_decl_and_block(fn_decl: P<ast::FnDecl>, block: P<ast::Bl /// A tree-folder that performs macro expansion pub struct MacroExpander<'a, 'b:'a> { pub cx: &'a mut ExtCtxt<'b>, + // The type of the impl currently being expanded. + current_impl_type: Option<P<ast::Ty>>, +} + +impl<'a, 'b> MacroExpander<'a, 'b> { + pub fn new(cx: &'a mut ExtCtxt<'b>) -> MacroExpander<'a, 'b> { + MacroExpander { cx: cx, current_impl_type: None } + } } impl<'a, 'b> Folder for MacroExpander<'a, 'b> { @@ -1067,7 +1110,14 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { } fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> { - expand_item(item, self) + let prev_type = self.current_impl_type.clone(); + if let ast::Item_::ItemImpl(_, _, _, ref ty, _) = item.node { + self.current_impl_type = Some(ty.clone()); + } + + let result = expand_item(item, self); + self.current_impl_type = prev_type; + result } fn fold_item_underscore(&mut self, item: ast::Item_) -> ast::Item_ { @@ -1090,6 +1140,11 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { expand_method(method, self) } + fn fold_ty(&mut self, t: P<ast::Ty>) -> P<ast::Ty> { + let impl_type = self.current_impl_type.clone(); + expand_type(t, self, impl_type) + } + fn new_span(&mut self, span: Span) -> Span { new_span(self.cx, span) } @@ -1134,13 +1189,10 @@ pub fn expand_crate(parse_sess: &parse::ParseSess, user_exts: Vec<NamedSyntaxExtension>, c: Crate) -> Crate { let mut cx = ExtCtxt::new(parse_sess, c.config.clone(), cfg); - let mut expander = MacroExpander { - cx: &mut cx, - }; + let mut expander = MacroExpander::new(&mut cx); for ExportedMacros { crate_name, macros } in imported_macros.into_iter() { - let name = format!("<{} macros>", token::get_ident(crate_name)) - .into_string(); + let name = format!("<{} macros>", token::get_ident(crate_name)); for source in macros.into_iter() { let item = parse::parse_item_from_source_str(name.clone(), @@ -1185,7 +1237,7 @@ impl Folder for Marker { node: match node { MacInvocTT(path, tts, ctxt) => { MacInvocTT(self.fold_path(path), - self.fold_tts(tts.as_slice()), + self.fold_tts(tts[]), mtwt::apply_mark(self.mark, ctxt)) } }, @@ -1321,7 +1373,7 @@ mod test { // make sure that macros can't escape fns #[should_fail] #[test] fn macros_cant_escape_fns_test () { - let src = "fn bogus() {macro_rules! z (() => (3+4))}\ + let src = "fn bogus() {macro_rules! z (() => (3+4));}\ fn inty() -> int { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( @@ -1335,7 +1387,7 @@ mod test { // make sure that macros can't escape modules #[should_fail] #[test] fn macros_cant_escape_mods_test () { - let src = "mod foo {macro_rules! z (() => (3+4))}\ + let src = "mod foo {macro_rules! z (() => (3+4));}\ fn inty() -> int { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( @@ -1347,7 +1399,7 @@ mod test { // macro_escape modules should allow macros to escape #[test] fn macros_can_escape_flattened_mods_test () { - let src = "#[macro_escape] mod foo {macro_rules! z (() => (3+4))}\ + let src = "#[macro_escape] mod foo {macro_rules! z (() => (3+4));}\ fn inty() -> int { z!() }".to_string(); let sess = parse::new_parse_sess(); let crate_ast = parse::parse_crate_from_source_str( @@ -1362,9 +1414,9 @@ mod test { let attr2 = make_dummy_attr ("bar"); let escape_attr = make_dummy_attr ("macro_escape"); let attrs1 = vec!(attr1.clone(), escape_attr, attr2.clone()); - assert_eq!(contains_macro_escape(attrs1.as_slice()),true); + assert_eq!(contains_macro_escape(attrs1[]),true); let attrs2 = vec!(attr1,attr2); - assert_eq!(contains_macro_escape(attrs2.as_slice()),false); + assert_eq!(contains_macro_escape(attrs2[]),false); } // make a MetaWord outer attribute with the given name @@ -1399,13 +1451,13 @@ mod test { #[test] fn macro_tokens_should_match(){ expand_crate_str( - "macro_rules! m((a)=>(13)) fn main(){m!(a);}".to_string()); + "macro_rules! m((a)=>(13)) ;fn main(){m!(a);}".to_string()); } // should be able to use a bound identifier as a literal in a macro definition: #[test] fn self_macro_parsing(){ expand_crate_str( - "macro_rules! foo ((zz) => (287u;)) + "macro_rules! foo ((zz) => (287u;)); fn f(zz : int) {foo!(zz);}".to_string() ); } @@ -1448,16 +1500,16 @@ mod test { ("fn main () {let x: int = 13;x;}", vec!(vec!(0)), false), // the use of b after the + should be renamed, the other one not: - ("macro_rules! f (($x:ident) => (b + $x)) fn a() -> int { let b = 13; f!(b)}", + ("macro_rules! f (($x:ident) => (b + $x)); fn a() -> int { let b = 13; f!(b)}", vec!(vec!(1)), false), // the b before the plus should not be renamed (requires marks) - ("macro_rules! f (($x:ident) => ({let b=9; ($x + b)})) fn a() -> int { f!(b)}", + ("macro_rules! f (($x:ident) => ({let b=9; ($x + b)})); fn a() -> int { f!(b)}", vec!(vec!(1)), false), // the marks going in and out of letty should cancel, allowing that $x to // capture the one following the semicolon. // this was an awesome test case, and caught a *lot* of bugs. - ("macro_rules! letty(($x:ident) => (let $x = 15;)) - macro_rules! user(($x:ident) => ({letty!($x); $x})) + ("macro_rules! letty(($x:ident) => (let $x = 15;)); + macro_rules! user(($x:ident) => ({letty!($x); $x})); fn main() -> int {user!(z)}", vec!(vec!(0)), false) ); @@ -1485,7 +1537,7 @@ mod test { #[test] fn issue_6994(){ run_renaming_test( &("macro_rules! g (($x:ident) => - ({macro_rules! f(($y:ident)=>({let $y=3;$x}));f!($x)})) + ({macro_rules! f(($y:ident)=>({let $y=3;$x}));f!($x)})); fn a(){g!(z)}", vec!(vec!(0)),false), 0) @@ -1495,7 +1547,7 @@ mod test { // fn z() {match 8 {x_1 => {match 9 {x_2 | x_2 if x_2 == x_1 => x_2 + x_1}}}} #[test] fn issue_9384(){ run_renaming_test( - &("macro_rules! bad_macro (($ex:expr) => ({match 9 {x | x if x == $ex => x + $ex}})) + &("macro_rules! bad_macro (($ex:expr) => ({match 9 {x | x if x == $ex => x + $ex}})); fn z() {match 8 {x => bad_macro!(x)}}", // NB: the third "binding" is the repeat of the second one. vec!(vec!(1,3),vec!(0,2),vec!(0,2)), @@ -1508,8 +1560,8 @@ mod test { // fn main(){let g1_1 = 13; g1_1}} #[test] fn pat_expand_issue_15221(){ run_renaming_test( - &("macro_rules! inner ( ($e:pat ) => ($e)) - macro_rules! outer ( ($e:pat ) => (inner!($e))) + &("macro_rules! inner ( ($e:pat ) => ($e)); + macro_rules! outer ( ($e:pat ) => (inner!($e))); fn main() { let outer!(g) = 13; g;}", vec!(vec!(0)), true), @@ -1524,8 +1576,8 @@ mod test { // method expands to fn get_x(&self_0, x_1:int) {self_0 + self_2 + x_3 + x_1} #[test] fn method_arg_hygiene(){ run_renaming_test( - &("macro_rules! inject_x (()=>(x)) - macro_rules! inject_self (()=>(self)) + &("macro_rules! inject_x (()=>(x)); + macro_rules! inject_self (()=>(self)); struct A; impl A{fn get_x(&self, x: int) {self + inject_self!() + inject_x!() + x;} }", vec!(vec!(0),vec!(3)), @@ -1539,8 +1591,8 @@ mod test { run_renaming_test( &("struct A; macro_rules! add_method (($T:ty) => - (impl $T { fn thingy(&self) {self;} })) - add_method!(A)", + (impl $T { fn thingy(&self) {self;} })); + add_method!(A);", vec!(vec!(0)), true), 0) @@ -1550,7 +1602,7 @@ mod test { // expands to fn q(x_1:int){fn g(x_2:int){x_2 + x_1};} #[test] fn issue_9383(){ run_renaming_test( - &("macro_rules! bad_macro (($ex:expr) => (fn g(x:int){ x + $ex })) + &("macro_rules! bad_macro (($ex:expr) => (fn g(x:int){ x + $ex })); fn q(x:int) { bad_macro!(x); }", vec!(vec!(1),vec!(0)),true), 0) @@ -1560,30 +1612,19 @@ mod test { // expands to fn f(){(|x_1 : int| {(x_2 + x_1)})(3);} #[test] fn closure_arg_hygiene(){ run_renaming_test( - &("macro_rules! inject_x (()=>(x)) + &("macro_rules! inject_x (()=>(x)); fn f(){(|x : int| {(inject_x!() + x)})(3);}", vec!(vec!(1)), true), 0) } - // closure arg hygiene (ExprProc) - // expands to fn f(){(proc(x_1 : int) {(x_2 + x_1)})(3);} - #[test] fn closure_arg_hygiene_2(){ - run_renaming_test( - &("macro_rules! inject_x (()=>(x)) - fn f(){ (proc(x : int){(inject_x!() + x)})(3); }", - vec!(vec!(1)), - true), - 0) - } - // macro_rules in method position. Sadly, unimplemented. #[test] fn macro_in_method_posn(){ expand_crate_str( - "macro_rules! my_method (() => (fn thirteen(&self) -> int {13})) + "macro_rules! my_method (() => (fn thirteen(&self) -> int {13})); struct A; - impl A{ my_method!()} + impl A{ my_method!(); } fn f(){A.thirteen;}".to_string()); } @@ -1594,7 +1635,7 @@ mod test { &("macro_rules! item { ($i:item) => {$i}} struct Entries; macro_rules! iterator_impl { - () => { item!( impl Entries { fn size_hint(&self) { self;}})}} + () => { item!( impl Entries { fn size_hint(&self) { self;}});}} iterator_impl! { }", vec!(vec!(0)), true), 0) @@ -1674,9 +1715,9 @@ mod test { } #[test] fn fmt_in_macro_used_inside_module_macro() { - let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_string())) -macro_rules! foo_module (() => (mod generated { fn a() { let xx = 147; fmt_wrap!(xx);}})) -foo_module!() + let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_string())); +macro_rules! foo_module (() => (mod generated { fn a() { let xx = 147; fmt_wrap!(xx);}})); +foo_module!(); ".to_string(); let cr = expand_crate_str(crate_str); // find the xx binding @@ -1687,7 +1728,7 @@ foo_module!() let string = ident.get(); "xx" == string }).collect(); - let cxbinds: &[&ast::Ident] = cxbinds.as_slice(); + let cxbinds: &[&ast::Ident] = cxbinds[]; let cxbind = match cxbinds { [b] => b, _ => panic!("expected just one binding for ext_cx") diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index b04a800a32d..aad4045f00a 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -136,7 +136,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool, _ => { ecx.span_err(p.span, format!("expected ident for named argument, found `{}`", - p.this_token_to_string()).as_slice()); + p.this_token_to_string())[]); return (invocation, None); } }; @@ -149,7 +149,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool, Some(prev) => { ecx.span_err(e.span, format!("duplicate argument named `{}`", - name).as_slice()); + name)[]); ecx.parse_sess.span_diagnostic.span_note(prev.span, "previously here"); continue } @@ -240,7 +240,7 @@ impl<'a, 'b> Context<'a, 'b> { let msg = format!("invalid reference to argument `{}` ({})", arg, self.describe_num_args()); - self.ecx.span_err(self.fmtsp, msg.as_slice()); + self.ecx.span_err(self.fmtsp, msg[]); return; } { @@ -260,7 +260,7 @@ impl<'a, 'b> Context<'a, 'b> { Some(e) => e.span, None => { let msg = format!("there is no argument named `{}`", name); - self.ecx.span_err(self.fmtsp, msg.as_slice()); + self.ecx.span_err(self.fmtsp, msg[]); return; } }; @@ -303,19 +303,19 @@ impl<'a, 'b> Context<'a, 'b> { format!("argument redeclared with type `{}` when \ it was previously `{}`", *ty, - *cur).as_slice()); + *cur)[]); } (&Known(ref cur), _) => { self.ecx.span_err(sp, format!("argument used to format with `{}` was \ attempted to not be used for formatting", - *cur).as_slice()); + *cur)[]); } (_, &Known(ref ty)) => { self.ecx.span_err(sp, format!("argument previously used as a format \ argument attempted to be used as `{}`", - *ty).as_slice()); + *ty)[]); } (_, _) => { self.ecx.span_err(sp, "argument declared with multiple formats"); @@ -380,7 +380,7 @@ impl<'a, 'b> Context<'a, 'b> { /// Translate the accumulated string literals to a literal expression fn trans_literal_string(&mut self) -> P<ast::Expr> { let sp = self.fmtsp; - let s = token::intern_and_get_ident(self.literal.as_slice()); + let s = token::intern_and_get_ident(self.literal[]); self.literal.clear(); self.ecx.expr_str(sp, s) } @@ -530,8 +530,9 @@ impl<'a, 'b> Context<'a, 'b> { self.fmtsp, true, Context::rtpath(self.ecx, "Argument"), vec![static_lifetime], + vec![], vec![] - ), None); + )); lets.push(Context::item_static_array(self.ecx, static_args_name, piece_ty, @@ -551,7 +552,7 @@ impl<'a, 'b> Context<'a, 'b> { None => continue // error already generated }; - let name = self.ecx.ident_of(format!("__arg{}", i).as_slice()); + let name = self.ecx.ident_of(format!("__arg{}", i)[]); pats.push(self.ecx.pat_ident(e.span, name)); locals.push(Context::format_arg(self.ecx, e.span, arg_ty, self.ecx.expr_ident(e.span, name))); @@ -568,7 +569,7 @@ impl<'a, 'b> Context<'a, 'b> { }; let lname = self.ecx.ident_of(format!("__arg{}", - *name).as_slice()); + *name)[]); pats.push(self.ecx.pat_ident(e.span, lname)); names[self.name_positions[*name]] = Some(Context::format_arg(self.ecx, e.span, arg_ty, @@ -577,17 +578,11 @@ impl<'a, 'b> Context<'a, 'b> { } // Now create a vector containing all the arguments - let slicename = self.ecx.ident_of("__args_vec"); - { - let args = names.into_iter().map(|a| a.unwrap()); - let mut args = locals.into_iter().chain(args); - let args = self.ecx.expr_vec_slice(self.fmtsp, args.collect()); - lets.push(self.ecx.stmt_let(self.fmtsp, false, slicename, args)); - } + let args = locals.into_iter().chain(names.into_iter().map(|a| a.unwrap())); // Now create the fmt::Arguments struct with all our locals we created. let pieces = self.ecx.expr_ident(self.fmtsp, static_str_name); - let args_slice = self.ecx.expr_ident(self.fmtsp, slicename); + let args_slice = self.ecx.expr_vec_slice(self.fmtsp, args.collect()); let (fn_name, fn_args) = if self.all_pieces_simple { ("new", vec![pieces, args_slice]) @@ -602,29 +597,18 @@ impl<'a, 'b> Context<'a, 'b> { self.ecx.ident_of("Arguments"), self.ecx.ident_of(fn_name)), fn_args); - // We did all the work of making sure that the arguments - // structure is safe, so we can safely have an unsafe block. - let result = self.ecx.expr_block(P(ast::Block { - view_items: Vec::new(), - stmts: Vec::new(), - expr: Some(result), - id: ast::DUMMY_NODE_ID, - rules: ast::UnsafeBlock(ast::CompilerGenerated), - span: self.fmtsp, - })); - let resname = self.ecx.ident_of("__args"); - lets.push(self.ecx.stmt_let(self.fmtsp, false, resname, result)); - let res = self.ecx.expr_ident(self.fmtsp, resname); let result = match invocation { Call(e) => { let span = e.span; - self.ecx.expr_call(span, e, - vec!(self.ecx.expr_addr_of(span, res))) + self.ecx.expr_call(span, e, vec![ + self.ecx.expr_addr_of(span, result) + ]) } MethodCall(e, m) => { let span = e.span; - self.ecx.expr_method_call(span, e, m, - vec!(self.ecx.expr_addr_of(span, res))) + self.ecx.expr_method_call(span, e, m, vec![ + self.ecx.expr_addr_of(span, result) + ]) } }; let body = self.ecx.expr_block(self.ecx.block(self.fmtsp, lets, @@ -668,8 +652,9 @@ impl<'a, 'b> Context<'a, 'b> { -> P<ast::Expr> { let trait_ = match *ty { Known(ref tyname) => { - match tyname.as_slice() { + match tyname[] { "" => "Show", + "?" => "Show", "e" => "LowerExp", "E" => "UpperExp", "o" => "Octal", @@ -680,7 +665,7 @@ impl<'a, 'b> Context<'a, 'b> { _ => { ecx.span_err(sp, format!("unknown format trait `{}`", - *tyname).as_slice()); + *tyname)[]); "Dummy" } } @@ -775,8 +760,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span, match parser.errors.remove(0) { Some(error) => { cx.ecx.span_err(cx.fmtsp, - format!("invalid format string: {}", - error).as_slice()); + format!("invalid format string: {}", error)[]); return DummyResult::raw_expr(sp); } None => {} diff --git a/src/libsyntax/ext/mtwt.rs b/src/libsyntax/ext/mtwt.rs index 2ddcab10cda..6a296333fdb 100644 --- a/src/libsyntax/ext/mtwt.rs +++ b/src/libsyntax/ext/mtwt.rs @@ -20,9 +20,8 @@ pub use self::SyntaxContext_::*; use ast::{Ident, Mrk, Name, SyntaxContext}; use std::cell::RefCell; -use std::rc::Rc; use std::collections::HashMap; -use std::collections::hash_map::{Occupied, Vacant}; +use std::collections::hash_map::Entry::{Occupied, Vacant}; /// The SCTable contains a table of SyntaxContext_'s. It /// represents a flattened tree structure, to avoid having @@ -40,7 +39,7 @@ pub struct SCTable { rename_memo: RefCell<HashMap<(SyntaxContext,Ident,Name),SyntaxContext>>, } -#[deriving(PartialEq, Encodable, Decodable, Hash, Show)] +#[deriving(PartialEq, RustcEncodable, RustcDecodable, Hash, Show, Copy)] pub enum SyntaxContext_ { EmptyCtxt, Mark (Mrk,SyntaxContext), @@ -104,17 +103,11 @@ pub fn apply_renames(renames: &RenameList, ctxt: SyntaxContext) -> SyntaxContext } /// Fetch the SCTable from TLS, create one if it doesn't yet exist. -pub fn with_sctable<T>(op: |&SCTable| -> T) -> T { - local_data_key!(sctable_key: Rc<SCTable>) - - match sctable_key.get() { - Some(ts) => op(&**ts), - None => { - let ts = Rc::new(new_sctable_internal()); - sctable_key.replace(Some(ts.clone())); - op(&*ts) - } - } +pub fn with_sctable<T, F>(op: F) -> T where + F: FnOnce(&SCTable) -> T, +{ + thread_local!(static SCTABLE_KEY: SCTable = new_sctable_internal()); + SCTABLE_KEY.with(move |slot| op(slot)) } // Make a fresh syntax context table with EmptyCtxt in slot zero @@ -145,6 +138,16 @@ pub fn clear_tables() { with_resolve_table_mut(|table| *table = HashMap::new()); } +/// Reset the tables to their initial state +pub fn reset_tables() { + with_sctable(|table| { + *table.table.borrow_mut() = vec!(EmptyCtxt, IllegalCtxt); + *table.mark_memo.borrow_mut() = HashMap::new(); + *table.rename_memo.borrow_mut() = HashMap::new(); + }); + with_resolve_table_mut(|table| *table = HashMap::new()); +} + /// Add a value to the end of a vec, return its index fn idx_push<T>(vec: &mut Vec<T>, val: T) -> u32 { vec.push(val); @@ -164,17 +167,14 @@ type ResolveTable = HashMap<(Name,SyntaxContext),Name>; // okay, I admit, putting this in TLS is not so nice: // fetch the SCTable from TLS, create one if it doesn't yet exist. -fn with_resolve_table_mut<T>(op: |&mut ResolveTable| -> T) -> T { - local_data_key!(resolve_table_key: Rc<RefCell<ResolveTable>>) - - match resolve_table_key.get() { - Some(ts) => op(&mut *ts.borrow_mut()), - None => { - let ts = Rc::new(RefCell::new(HashMap::new())); - resolve_table_key.replace(Some(ts.clone())); - op(&mut *ts.borrow_mut()) - } - } +fn with_resolve_table_mut<T, F>(op: F) -> T where + F: FnOnce(&mut ResolveTable) -> T, +{ + thread_local!(static RESOLVE_TABLE_KEY: RefCell<ResolveTable> = { + RefCell::new(HashMap::new()) + }); + + RESOLVE_TABLE_KEY.with(move |slot| op(&mut *slot.borrow_mut())) } /// Resolve a syntax object to a name, per MTWT. diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index eaa3632cf49..368d4fa8447 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; @@ -104,7 +100,7 @@ pub mod rt { fn to_source_with_hygiene(&self) -> String; } - macro_rules! impl_to_source( + macro_rules! impl_to_source { (P<$t:ty>, $pp:ident) => ( impl ToSource for P<$t> { fn to_source(&self) -> String { @@ -129,7 +125,7 @@ pub mod rt { } } ); - ) + } fn slice_to_source<'a, T: ToSource>(sep: &'static str, xs: &'a [T]) -> String { xs.iter() @@ -148,7 +144,7 @@ pub mod rt { .to_string() } - macro_rules! impl_to_source_slice( + macro_rules! impl_to_source_slice { ($t:ty, $sep:expr) => ( impl ToSource for [$t] { fn to_source(&self) -> String { @@ -162,7 +158,7 @@ pub mod rt { } } ) - ) + } impl ToSource for ast::Ident { fn to_source(&self) -> String { @@ -176,18 +172,18 @@ pub mod rt { } } - impl_to_source!(ast::Ty, ty_to_string) - impl_to_source!(ast::Block, block_to_string) - impl_to_source!(ast::Arg, arg_to_string) - impl_to_source!(Generics, generics_to_string) - impl_to_source!(P<ast::Item>, item_to_string) - impl_to_source!(P<ast::Method>, method_to_string) - impl_to_source!(P<ast::Stmt>, stmt_to_string) - impl_to_source!(P<ast::Expr>, expr_to_string) - impl_to_source!(P<ast::Pat>, pat_to_string) - impl_to_source!(ast::Arm, arm_to_string) - impl_to_source_slice!(ast::Ty, ", ") - impl_to_source_slice!(P<ast::Item>, "\n\n") + impl_to_source! { ast::Ty, ty_to_string } + impl_to_source! { ast::Block, block_to_string } + impl_to_source! { ast::Arg, arg_to_string } + impl_to_source! { Generics, generics_to_string } + impl_to_source! { P<ast::Item>, item_to_string } + impl_to_source! { P<ast::Method>, method_to_string } + impl_to_source! { P<ast::Stmt>, stmt_to_string } + impl_to_source! { P<ast::Expr>, expr_to_string } + impl_to_source! { P<ast::Pat>, pat_to_string } + impl_to_source! { ast::Arm, arm_to_string } + impl_to_source_slice! { ast::Ty, ", " } + impl_to_source_slice! { P<ast::Item>, "\n\n" } impl ToSource for ast::Attribute_ { fn to_source(&self) -> String { @@ -248,7 +244,7 @@ pub mod rt { } } - macro_rules! impl_to_source_int( + macro_rules! impl_to_source_int { (signed, $t:ty, $tag:ident) => ( impl ToSource for $t { fn to_source(&self) -> String { @@ -276,23 +272,23 @@ pub mod rt { } } ); - ) + } - impl_to_source_int!(signed, int, TyI) - impl_to_source_int!(signed, i8, TyI8) - impl_to_source_int!(signed, i16, TyI16) - impl_to_source_int!(signed, i32, TyI32) - impl_to_source_int!(signed, i64, TyI64) + impl_to_source_int! { signed, int, TyI } + impl_to_source_int! { signed, i8, TyI8 } + impl_to_source_int! { signed, i16, TyI16 } + impl_to_source_int! { signed, i32, TyI32 } + impl_to_source_int! { signed, i64, TyI64 } - impl_to_source_int!(unsigned, uint, TyU) - impl_to_source_int!(unsigned, u8, TyU8) - impl_to_source_int!(unsigned, u16, TyU16) - impl_to_source_int!(unsigned, u32, TyU32) - impl_to_source_int!(unsigned, u64, TyU64) + impl_to_source_int! { unsigned, uint, TyU } + impl_to_source_int! { unsigned, u8, TyU8 } + impl_to_source_int! { unsigned, u16, TyU16 } + impl_to_source_int! { unsigned, u32, TyU32 } + impl_to_source_int! { unsigned, u64, TyU64 } // Alas ... we write these out instead. All redundant. - macro_rules! impl_to_tokens( + macro_rules! impl_to_tokens { ($t:ty) => ( impl ToTokens for $t { fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> { @@ -300,9 +296,9 @@ pub mod rt { } } ) - ) + } - macro_rules! impl_to_tokens_lifetime( + macro_rules! impl_to_tokens_lifetime { ($t:ty) => ( impl<'a> ToTokens for $t { fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> { @@ -310,36 +306,36 @@ pub mod rt { } } ) - ) - - impl_to_tokens!(ast::Ident) - impl_to_tokens!(P<ast::Item>) - impl_to_tokens!(P<ast::Pat>) - impl_to_tokens!(ast::Arm) - impl_to_tokens!(P<ast::Method>) - impl_to_tokens_lifetime!(&'a [P<ast::Item>]) - impl_to_tokens!(ast::Ty) - impl_to_tokens_lifetime!(&'a [ast::Ty]) - impl_to_tokens!(Generics) - impl_to_tokens!(P<ast::Stmt>) - impl_to_tokens!(P<ast::Expr>) - impl_to_tokens!(ast::Block) - impl_to_tokens!(ast::Arg) - impl_to_tokens!(ast::Attribute_) - impl_to_tokens_lifetime!(&'a str) - impl_to_tokens!(()) - impl_to_tokens!(char) - impl_to_tokens!(bool) - impl_to_tokens!(int) - impl_to_tokens!(i8) - impl_to_tokens!(i16) - impl_to_tokens!(i32) - impl_to_tokens!(i64) - impl_to_tokens!(uint) - impl_to_tokens!(u8) - impl_to_tokens!(u16) - impl_to_tokens!(u32) - impl_to_tokens!(u64) + } + + impl_to_tokens! { ast::Ident } + impl_to_tokens! { P<ast::Item> } + impl_to_tokens! { P<ast::Pat> } + impl_to_tokens! { ast::Arm } + impl_to_tokens! { P<ast::Method> } + impl_to_tokens_lifetime! { &'a [P<ast::Item>] } + impl_to_tokens! { ast::Ty } + impl_to_tokens_lifetime! { &'a [ast::Ty] } + impl_to_tokens! { Generics } + impl_to_tokens! { P<ast::Stmt> } + impl_to_tokens! { P<ast::Expr> } + impl_to_tokens! { ast::Block } + impl_to_tokens! { ast::Arg } + impl_to_tokens! { ast::Attribute_ } + impl_to_tokens_lifetime! { &'a str } + impl_to_tokens! { () } + impl_to_tokens! { char } + impl_to_tokens! { bool } + impl_to_tokens! { int } + impl_to_tokens! { i8 } + impl_to_tokens! { i16 } + impl_to_tokens! { i32 } + impl_to_tokens! { i64 } + impl_to_tokens! { uint } + impl_to_tokens! { u8 } + impl_to_tokens! { u16 } + impl_to_tokens! { u32 } + impl_to_tokens! { u64 } pub trait ExtParseUtils { fn parse_item(&self, s: String) -> P<ast::Item>; @@ -454,9 +450,7 @@ pub fn expand_quote_ty(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box<base::MacResult+'static> { - let e_param_colons = cx.expr_lit(sp, ast::LitBool(false)); - let expanded = expand_parse_call(cx, sp, "parse_ty", - vec!(e_param_colons), tts); + let expanded = expand_parse_call(cx, sp, "parse_ty", vec!(), tts); base::MacExpr::new(expanded) } @@ -480,7 +474,7 @@ pub fn expand_quote_stmt(cx: &mut ExtCtxt, } fn ids_ext(strs: Vec<String> ) -> Vec<ast::Ident> { - strs.iter().map(|str| str_to_ident((*str).as_slice())).collect() + strs.iter().map(|str| str_to_ident((*str)[])).collect() } fn id_ext(str: &str) -> ast::Ident { @@ -682,7 +676,7 @@ fn mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree) -> Vec<P<ast::Stmt>> { for i in range(0, tt.len()) { seq.push(tt.get_tt(i)); } - mk_tts(cx, seq.as_slice()) + mk_tts(cx, seq[]) } ast::TtToken(sp, ref tok) => { let e_sp = cx.expr_ident(sp, id_ext("_sp")); @@ -771,7 +765,7 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let stmt_let_tt = cx.stmt_let(sp, true, id_ext("tt"), cx.expr_vec_ng(sp)); let mut vector = vec!(stmt_let_sp, stmt_let_tt); - vector.extend(mk_tts(cx, tts.as_slice()).into_iter()); + vector.extend(mk_tts(cx, tts[]).into_iter()); let block = cx.expr_block( cx.block_all(sp, Vec::new(), diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 570231940aa..7c2c5c1530c 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -57,7 +57,7 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) let topmost = cx.original_span_in_file(); let loc = cx.codemap().lookup_char_pos(topmost.lo); - let filename = token::intern_and_get_ident(loc.file.name.as_slice()); + let filename = token::intern_and_get_ident(loc.file.name[]); base::MacExpr::new(cx.expr_str(topmost, filename)) } @@ -65,7 +65,7 @@ pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box<base::MacResult+'static> { let s = pprust::tts_to_string(tts); base::MacExpr::new(cx.expr_str(sp, - token::intern_and_get_ident(s.as_slice()))) + token::intern_and_get_ident(s[]))) } pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) @@ -78,7 +78,7 @@ pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) .connect("::"); base::MacExpr::new(cx.expr_str( sp, - token::intern_and_get_ident(string.as_slice()))) + token::intern_and_get_ident(string[]))) } /// include! : parse the given file as an expr @@ -137,7 +137,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) cx.span_err(sp, format!("couldn't read {}: {}", file.display(), - e).as_slice()); + e)[]); return DummyResult::expr(sp); } Ok(bytes) => bytes, @@ -147,7 +147,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) // Add this input file to the code map to make it available as // dependency information let filename = file.display().to_string(); - let interned = token::intern_and_get_ident(src.as_slice()); + let interned = token::intern_and_get_ident(src[]); cx.codemap().new_filemap(filename, src); base::MacExpr::new(cx.expr_str(sp, interned)) @@ -155,7 +155,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) Err(_) => { cx.span_err(sp, format!("{} wasn't a utf-8 file", - file.display()).as_slice()); + file.display())[]); return DummyResult::expr(sp); } } @@ -171,9 +171,7 @@ pub fn expand_include_bin(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) match File::open(&file).read_to_end() { Err(e) => { cx.span_err(sp, - format!("couldn't read {}: {}", - file.display(), - e).as_slice()); + format!("couldn't read {}: {}", file.display(), e)[]); return DummyResult::expr(sp); } Ok(bytes) => { diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index b4cd9779ae2..73ef18b8449 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -98,7 +98,7 @@ use ptr::P; use std::mem; use std::rc::Rc; use std::collections::HashMap; -use std::collections::hash_map::{Vacant, Occupied}; +use std::collections::hash_map::Entry::{Vacant, Occupied}; // To avoid costly uniqueness checks, we require that `MatchSeq` always has // a nonempty body. @@ -153,7 +153,7 @@ pub fn count_names(ms: &[TokenTree]) -> uint { seq.num_captures } &TtDelimited(_, ref delim) => { - count_names(delim.tts.as_slice()) + count_names(delim.tts[]) } &TtToken(_, MatchNt(..)) => { 1 @@ -165,7 +165,7 @@ pub fn count_names(ms: &[TokenTree]) -> uint { pub fn initial_matcher_pos(ms: Rc<Vec<TokenTree>>, sep: Option<Token>, lo: BytePos) -> Box<MatcherPos> { - let match_idx_hi = count_names(ms.as_slice()); + let match_idx_hi = count_names(ms[]); let matches = Vec::from_fn(match_idx_hi, |_i| Vec::new()); box MatcherPos { stack: vec![], @@ -229,7 +229,7 @@ pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc<NamedMatch>]) p_s.span_diagnostic .span_fatal(sp, format!("duplicated bind name: {}", - string.get()).as_slice()) + string.get())[]) } } } @@ -254,13 +254,13 @@ pub fn parse_or_else(sess: &ParseSess, rdr: TtReader, ms: Vec<TokenTree> ) -> HashMap<Ident, Rc<NamedMatch>> { - match parse(sess, cfg, rdr, ms.as_slice()) { + match parse(sess, cfg, rdr, ms[]) { Success(m) => m, Failure(sp, str) => { - sess.span_diagnostic.span_fatal(sp, str.as_slice()) + sess.span_diagnostic.span_fatal(sp, str[]) } Error(sp, str) => { - sess.span_diagnostic.span_fatal(sp, str.as_slice()) + sess.span_diagnostic.span_fatal(sp, str[]) } } } @@ -416,7 +416,7 @@ pub fn parse(sess: &ParseSess, } } TtToken(sp, SubstNt(..)) => { - return Error(sp, "Cannot transcribe in macro LHS".into_string()) + return Error(sp, "Cannot transcribe in macro LHS".to_string()) } seq @ TtDelimited(..) | seq @ TtToken(_, DocComment(..)) => { let lower_elts = mem::replace(&mut ei.top_elts, Tt(seq)); @@ -446,7 +446,7 @@ pub fn parse(sess: &ParseSess, for dv in eof_eis[0].matches.iter_mut() { v.push(dv.pop().unwrap()); } - return Success(nameize(sess, ms, v.as_slice())); + return Success(nameize(sess, ms, v[])); } else if eof_eis.len() > 1u { return Error(sp, "ambiguity: multiple successful parses".to_string()); } else { @@ -514,18 +514,18 @@ 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) } _ => { let token_str = pprust::token_to_string(&p.token); p.fatal((format!("expected ident, found {}", - token_str.as_slice())).as_slice()) + token_str[]))[]) } }, "path" => { - token::NtPath(box p.parse_path(LifetimeAndTypesWithoutColons).path) + token::NtPath(box p.parse_path(LifetimeAndTypesWithoutColons)) } "meta" => token::NtMeta(p.parse_meta_item()), "tt" => { @@ -535,8 +535,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal { res } _ => { - p.fatal(format!("unsupported builtin nonterminal parser: {}", - name).as_slice()) + p.fatal(format!("unsupported builtin nonterminal parser: {}", name)[]) } } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 92c68b7a9c7..08014dc1338 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -52,7 +52,7 @@ impl<'a> ParserAnyMacro<'a> { following", token_str); let span = parser.span; - parser.span_err(span, msg.as_slice()); + parser.span_err(span, msg[]); } } } @@ -124,8 +124,8 @@ impl TTMacroExpander for MacroRulesMacroExpander { sp, self.name, arg, - self.lhses.as_slice(), - self.rhses.as_slice()) + self.lhses[], + self.rhses[]) } } @@ -160,7 +160,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, match **lhs { MatchedNonterminal(NtTT(ref lhs_tt)) => { let lhs_tt = match **lhs_tt { - TtDelimited(_, ref delim) => delim.tts.as_slice(), + TtDelimited(_, ref delim) => delim.tts[], _ => cx.span_fatal(sp, "malformed macro lhs") }; // `None` is because we're not interpolating @@ -198,13 +198,13 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, best_fail_spot = sp; best_fail_msg = (*msg).clone(); }, - Error(sp, ref msg) => cx.span_fatal(sp, msg.as_slice()) + Error(sp, ref msg) => cx.span_fatal(sp, msg[]) } } _ => cx.bug("non-matcher found in parsed lhses") } } - cx.span_fatal(best_fail_spot, best_fail_msg.as_slice()); + cx.span_fatal(best_fail_spot, best_fail_msg[]); } // Note that macro-by-example's input is also matched against a token tree: diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 99799fecb78..deed0b78e87 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -107,16 +107,16 @@ enum LockstepIterSize { } impl Add<LockstepIterSize, LockstepIterSize> for LockstepIterSize { - fn add(&self, other: &LockstepIterSize) -> LockstepIterSize { - match *self { - LisUnconstrained => other.clone(), - LisContradiction(_) => self.clone(), - LisConstraint(l_len, l_id) => match *other { + fn add(self, other: LockstepIterSize) -> LockstepIterSize { + match self { + LisUnconstrained => other, + LisContradiction(_) => self, + LisConstraint(l_len, ref l_id) => match other { LisUnconstrained => self.clone(), - LisContradiction(_) => other.clone(), + LisContradiction(_) => other, LisConstraint(r_len, _) if l_len == r_len => self.clone(), LisConstraint(r_len, r_id) => { - let l_n = token::get_ident(l_id); + let l_n = token::get_ident(l_id.clone()); let r_n = token::get_ident(r_id); LisContradiction(format!("inconsistent lockstep iteration: \ '{}' has {} items, but '{}' has {}", @@ -223,7 +223,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } LisContradiction(ref msg) => { // FIXME #2887 blame macro invoker instead - r.sp_diag.span_fatal(sp.clone(), msg.as_slice()); + r.sp_diag.span_fatal(sp.clone(), msg[]); } LisConstraint(len, _) => { if len == 0 { @@ -280,7 +280,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { r.sp_diag.span_fatal( r.cur_span, /* blame the macro writer */ format!("variable '{}' is still repeating at this depth", - token::get_ident(ident)).as_slice()); + token::get_ident(ident))[]); } } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9635f0175f0..d53a4b0e8d1 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -32,9 +32,7 @@ use parse::token; use std::slice; -/// This is a list of all known features since the beginning of time. This list -/// can never shrink, it may only be expanded (in order to prevent old programs -/// from failing to compile). The status of each feature may change, however. +// if you change this list without updating src/doc/reference.md, @cmr will be sad static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("globs", Active), ("macro_rules", Active), @@ -65,20 +63,21 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[ ("unboxed_closures", Active), ("import_shadowing", Active), ("advanced_slice_patterns", Active), - ("tuple_indexing", Active), + ("tuple_indexing", Accepted), ("associated_types", Active), ("visible_private_types", Active), ("slicing_syntax", Active), - ("if_let", Active), - ("while_let", Active), - - // if you change this list without updating src/doc/reference.md, cmr will be sad + ("if_let", Accepted), + ("while_let", Accepted), // A temporary feature gate used to enable parser extensions needed // to bootstrap fix for #5723. ("issue_5723_bootstrap", Accepted), + // A way to temporary opt out of opt in copy. This will *never* be accepted. + ("opt_out_copy", Active), + // These are used to test this portion of the compiler, they don't actually // mean anything ("test_accepted_feature", Accepted), @@ -98,6 +97,7 @@ enum Status { } /// A set of features to be used by later passes. +#[deriving(Copy)] pub struct Features { pub default_type_params: bool, pub unboxed_closures: bool, @@ -105,6 +105,7 @@ pub struct Features { pub import_shadowing: bool, pub visible_private_types: bool, pub quote: bool, + pub opt_out_copy: bool, } impl Features { @@ -116,6 +117,7 @@ impl Features { import_shadowing: false, visible_private_types: false, quote: false, + opt_out_copy: false, } } } @@ -131,12 +133,12 @@ impl<'a> Context<'a> { self.span_handler.span_err(span, explain); self.span_handler.span_help(span, format!("add #![feature({})] to the \ crate attributes to enable", - feature).as_slice()); + feature)[]); } } fn has_feature(&self, feature: &str) -> bool { - self.features.iter().any(|n| n.as_slice() == feature) + self.features.iter().any(|&n| n == feature) } } @@ -151,13 +153,10 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { fn visit_view_item(&mut self, i: &ast::ViewItem) { match i.node { ast::ViewItemUse(ref path) => { - match path.node { - ast::ViewPathGlob(..) => { - self.gate_feature("globs", path.span, - "glob import statements are \ - experimental and possibly buggy"); - } - _ => {} + if let ast::ViewPathGlob(..) = path.node { + self.gate_feature("globs", path.span, + "glob import statements are \ + experimental and possibly buggy"); } } ast::ViewItemExternCrate(..) => { @@ -175,12 +174,12 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { fn visit_item(&mut self, i: &ast::Item) { for attr in i.attrs.iter() { - if attr.name().equiv(&("thread_local")) { + if attr.name() == "thread_local" { self.gate_feature("thread_local", i.span, "`#[thread_local]` is an experimental feature, and does not \ currently handle destructors. There is no corresponding \ `#[task_local]` mapping to the task model"); - } else if attr.name().equiv(&("linkage")) { + } else if attr.name() == "linkage" { self.gate_feature("linkage", i.span, "the `linkage` attribute is experimental \ and not portable across platforms") @@ -188,7 +187,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } match i.node { ast::ItemForeignMod(ref foreign_module) => { - if attr::contains_name(i.attrs.as_slice(), "link_args") { + if attr::contains_name(i.attrs[], "link_args") { self.gate_feature("link_args", i.span, "the `link_args` attribute is not portable \ across platforms, it is recommended to \ @@ -202,20 +201,20 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } ast::ItemFn(..) => { - if attr::contains_name(i.attrs.as_slice(), "plugin_registrar") { + if attr::contains_name(i.attrs[], "plugin_registrar") { self.gate_feature("plugin_registrar", i.span, "compiler plugins are experimental and possibly buggy"); } } ast::ItemStruct(..) => { - if attr::contains_name(i.attrs.as_slice(), "simd") { + if attr::contains_name(i.attrs[], "simd") { self.gate_feature("simd", i.span, "SIMD types are experimental and possibly buggy"); } } - ast::ItemImpl(_, _, _, ref items) => { + ast::ItemImpl(_, _, _, _, ref items) => { if attr::contains_name(i.attrs.as_slice(), "unsafe_destructor") { self.gate_feature("unsafe_destructor", @@ -286,7 +285,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } fn visit_foreign_item(&mut self, i: &ast::ForeignItem) { - if attr::contains_name(i.attrs.as_slice(), "linkage") { + if attr::contains_name(i.attrs[], "linkage") { self.gate_feature("linkage", i.span, "the `linkage` attribute is experimental \ and not portable across platforms") @@ -295,13 +294,10 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } fn visit_ty(&mut self, t: &ast::Ty) { - match t.node { - ast::TyClosure(ref closure) => { - // this used to be blocked by a feature gate, but it should just - // be plain impossible right now - assert!(closure.onceness != ast::Once); - }, - _ => {} + if let ast::TyClosure(ref closure) = t.node { + // this used to be blocked by a feature gate, but it should just + // be plain impossible right now + assert!(closure.onceness != ast::Once); } visit::walk_ty(self, t); @@ -309,30 +305,11 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { fn visit_expr(&mut self, e: &ast::Expr) { match e.node { - ast::ExprClosure(_, Some(_), _, _) => { - self.gate_feature("unboxed_closures", - e.span, - "unboxed closures are a work-in-progress \ - feature with known bugs"); - } - ast::ExprTupField(..) => { - self.gate_feature("tuple_indexing", - e.span, - "tuple indexing is experimental"); - } - ast::ExprIfLet(..) => { - self.gate_feature("if_let", e.span, - "`if let` syntax is experimental"); - } ast::ExprSlice(..) => { self.gate_feature("slicing_syntax", e.span, "slicing syntax is experimental"); } - ast::ExprWhileLet(..) => { - self.gate_feature("while_let", e.span, - "`while let` syntax is experimental"); - } _ => {} } visit::walk_expr(self, e); @@ -390,19 +367,6 @@ impl<'a, 'v> Visitor<'v> for Context<'a> { } visit::walk_fn(self, fn_kind, fn_decl, block, span); } - - fn visit_path_parameters(&mut self, path_span: Span, parameters: &'v ast::PathParameters) { - match *parameters { - ast::ParenthesizedParameters(..) => { - self.gate_feature("unboxed_closures", - path_span, - "parenthetical parameter notation is subject to change"); - } - ast::AngleBracketedParameters(..) => { } - } - - visit::walk_path_parameters(self, path_span, parameters) - } } pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features, Vec<Span>) { @@ -435,7 +399,7 @@ pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features, } }; match KNOWN_FEATURES.iter() - .find(|& &(n, _)| name.equiv(&n)) { + .find(|& &(n, _)| name == n) { Some(&(name, Active)) => { cx.features.push(name); } Some(&(_, Removed)) => { span_handler.span_err(mi.span, "feature has been removed"); @@ -462,7 +426,7 @@ pub fn check_crate(span_handler: &SpanHandler, krate: &ast::Crate) -> (Features, import_shadowing: cx.has_feature("import_shadowing"), visible_private_types: cx.has_feature("visible_private_types"), quote: cx.has_feature("quote"), + opt_out_copy: cx.has_feature("opt_out_copy"), }, unknown_features) } - diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 1bdf9ea73df..0803de1bb53 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -32,11 +32,11 @@ use std::rc::Rc; // This could have a better place to live. pub trait MoveMap<T> { - fn move_map(self, f: |T| -> T) -> Self; + fn move_map<F>(self, f: F) -> Self where F: FnMut(T) -> T; } impl<T> MoveMap<T> for Vec<T> { - fn move_map(mut self, f: |T| -> T) -> Vec<T> { + fn move_map<F>(mut self, mut f: F) -> Vec<T> where F: FnMut(T) -> T { for p in self.iter_mut() { unsafe { // FIXME(#5016) this shouldn't need to zero to be safe. @@ -48,7 +48,7 @@ impl<T> MoveMap<T> for Vec<T> { } impl<T> MoveMap<T> for OwnedSlice<T> { - fn move_map(self, f: |T| -> T) -> OwnedSlice<T> { + fn move_map<F>(self, f: F) -> OwnedSlice<T> where F: FnMut(T) -> T { OwnedSlice::from_vec(self.into_vec().move_map(f)) } } @@ -146,6 +146,10 @@ pub trait Folder { noop_fold_qpath(t, self) } + fn fold_ty_binding(&mut self, t: P<TypeBinding>) -> P<TypeBinding> { + noop_fold_ty_binding(t, self) + } + fn fold_mod(&mut self, m: Mod) -> Mod { noop_fold_mod(m, self) } @@ -391,6 +395,15 @@ pub fn noop_fold_decl<T: Folder>(d: P<Decl>, fld: &mut T) -> SmallVector<P<Decl> }) } +pub fn noop_fold_ty_binding<T: Folder>(b: P<TypeBinding>, fld: &mut T) -> P<TypeBinding> { + b.map(|TypeBinding { id, ident, ty, span }| TypeBinding { + id: fld.new_id(id), + ident: ident, + ty: fld.fold_ty(ty), + span: fld.new_span(span), + }) +} + pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { t.map(|Ty {id, node, span}| Ty { id: fld.new_id(id), @@ -402,20 +415,9 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt)) } TyClosure(f) => { - TyClosure(f.map(|ClosureTy {fn_style, onceness, bounds, decl, lifetimes}| { - ClosureTy { - fn_style: fn_style, - onceness: onceness, - bounds: fld.fold_bounds(bounds), - decl: fld.fold_fn_decl(decl), - lifetimes: fld.fold_lifetime_defs(lifetimes) - } - })) - } - TyProc(f) => { - TyProc(f.map(|ClosureTy {fn_style, onceness, bounds, decl, lifetimes}| { + TyClosure(f.map(|ClosureTy {unsafety, onceness, bounds, decl, lifetimes}| { ClosureTy { - fn_style: fn_style, + unsafety: unsafety, onceness: onceness, bounds: fld.fold_bounds(bounds), decl: fld.fold_fn_decl(decl), @@ -424,20 +426,22 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { })) } TyBareFn(f) => { - TyBareFn(f.map(|BareFnTy {lifetimes, fn_style, abi, decl}| BareFnTy { + TyBareFn(f.map(|BareFnTy {lifetimes, unsafety, abi, decl}| BareFnTy { lifetimes: fld.fold_lifetime_defs(lifetimes), - fn_style: fn_style, + unsafety: unsafety, abi: abi, decl: fld.fold_fn_decl(decl) })) } 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)) @@ -531,9 +535,10 @@ pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedP fld: &mut T) -> AngleBracketedParameterData { - let AngleBracketedParameterData { lifetimes, types } = data; + let AngleBracketedParameterData { lifetimes, types, bindings } = data; AngleBracketedParameterData { lifetimes: fld.fold_lifetimes(lifetimes), - types: types.move_map(|ty| fld.fold_ty(ty)) } + types: types.move_map(|ty| fld.fold_ty(ty)), + bindings: bindings.move_map(|b| fld.fold_ty_binding(b)) } } pub fn noop_fold_parenthesized_parameter_data<T: Folder>(data: ParenthesizedParameterData, @@ -805,14 +810,39 @@ pub fn noop_fold_where_clause<T: Folder>( } pub fn noop_fold_where_predicate<T: Folder>( - WherePredicate {id, ident, bounds, span}: WherePredicate, + pred: WherePredicate, fld: &mut T) -> WherePredicate { - WherePredicate { - id: fld.new_id(id), - ident: fld.fold_ident(ident), - bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)), - span: fld.new_span(span) + match pred { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{bounded_ty, + bounds, + span}) => { + ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate { + bounded_ty: fld.fold_ty(bounded_ty), + bounds: bounds.move_map(|x| fld.fold_ty_param_bound(x)), + span: fld.new_span(span) + }) + } + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{lifetime, + bounds, + span}) => { + ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { + span: fld.new_span(span), + lifetime: fld.fold_lifetime(lifetime), + bounds: bounds.move_map(|bound| fld.fold_lifetime(bound)) + }) + } + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, + path, + ty, + span}) => { + ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ + id: fld.new_id(id), + path: fld.fold_path(path), + ty:fld.fold_ty(ty), + span: fld.new_span(span) + }) + } } } @@ -960,10 +990,10 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ { ItemConst(t, e) => { ItemConst(folder.fold_ty(t), folder.fold_expr(e)) } - ItemFn(decl, fn_style, abi, generics, body) => { + ItemFn(decl, unsafety, abi, generics, body) => { ItemFn( folder.fold_fn_decl(decl), - fn_style, + unsafety, abi, folder.fold_generics(generics), folder.fold_block(body) @@ -985,7 +1015,7 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ { let struct_def = folder.fold_struct_def(struct_def); ItemStruct(struct_def, folder.fold_generics(generics)) } - ItemImpl(generics, ifce, ty, impl_items) => { + ItemImpl(unsafety, generics, ifce, ty, impl_items) => { let mut new_impl_items = Vec::new(); for impl_item in impl_items.iter() { match *impl_item { @@ -1007,12 +1037,13 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ { Some(folder.fold_trait_ref((*trait_ref).clone())) } }; - ItemImpl(folder.fold_generics(generics), + ItemImpl(unsafety, + folder.fold_generics(generics), ifce, folder.fold_ty(ty), new_impl_items) } - ItemTrait(generics, unbound, bounds, methods) => { + ItemTrait(unsafety, generics, unbound, bounds, methods) => { let bounds = folder.fold_bounds(bounds); let methods = methods.into_iter().flat_map(|method| { let r = match method { @@ -1040,7 +1071,8 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ { }; r }).collect(); - ItemTrait(folder.fold_generics(generics), + ItemTrait(unsafety, + folder.fold_generics(generics), unbound, bounds, methods) @@ -1054,7 +1086,7 @@ pub fn noop_fold_type_method<T: Folder>(m: TypeMethod, fld: &mut T) -> TypeMetho id, ident, attrs, - fn_style, + unsafety, abi, decl, generics, @@ -1066,7 +1098,7 @@ pub fn noop_fold_type_method<T: Folder>(m: TypeMethod, fld: &mut T) -> TypeMetho id: fld.new_id(id), ident: fld.fold_ident(ident), attrs: attrs.move_map(|a| fld.fold_attribute(a)), - fn_style: fn_style, + unsafety: unsafety, abi: abi, decl: fld.fold_fn_decl(decl), generics: fld.fold_generics(generics), @@ -1136,7 +1168,7 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span} let node = folder.fold_item_underscore(node); let ident = match node { // The node may have changed, recompute the "pretty" impl name. - ItemImpl(_, ref maybe_trait, ref ty, _) => { + ItemImpl(_, _, ref maybe_trait, ref ty, _) => { ast_util::impl_pretty_name(maybe_trait, &**ty) } _ => ident @@ -1188,7 +1220,7 @@ pub fn noop_fold_method<T: Folder>(m: P<Method>, folder: &mut T) -> SmallVector< generics, abi, explicit_self, - fn_style, + unsafety, decl, body, vis) => { @@ -1196,7 +1228,7 @@ pub fn noop_fold_method<T: Folder>(m: P<Method>, folder: &mut T) -> SmallVector< folder.fold_generics(generics), abi, folder.fold_explicit_self(explicit_self), - fn_style, + unsafety, folder.fold_fn_decl(decl), folder.fold_block(body), vis) @@ -1257,7 +1289,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> id: folder.new_id(id), node: match node { ExprBox(p, e) => { - ExprBox(folder.fold_expr(p), folder.fold_expr(e)) + ExprBox(p.map(|e|folder.fold_expr(e)), folder.fold_expr(e)) } ExprVec(exprs) => { ExprVec(exprs.move_map(|x| folder.fold_expr(x))) @@ -1326,10 +1358,6 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> arms.move_map(|x| folder.fold_arm(x)), source) } - ExprProc(decl, body) => { - ExprProc(folder.fold_fn_decl(decl), - folder.fold_block(body)) - } ExprClosure(capture_clause, opt_kind, decl, body) => { ExprClosure(capture_clause, opt_kind, @@ -1345,15 +1373,13 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> folder.fold_expr(el), folder.fold_expr(er)) } - ExprField(el, ident, tys) => { + ExprField(el, ident) => { ExprField(folder.fold_expr(el), - respan(ident.span, folder.fold_ident(ident.node)), - tys.move_map(|x| folder.fold_ty(x))) + respan(ident.span, folder.fold_ident(ident.node))) } - ExprTupField(el, ident, tys) => { + ExprTupField(el, ident) => { ExprTupField(folder.fold_expr(el), - respan(ident.span, folder.fold_uint(ident.node)), - tys.move_map(|x| folder.fold_ty(x))) + respan(ident.span, folder.fold_uint(ident.node))) } ExprIndex(el, er) => { ExprIndex(folder.fold_expr(el), folder.fold_expr(er)) @@ -1364,6 +1390,10 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) -> e2.map(|x| folder.fold_expr(x)), m) } + ExprRange(e1, e2) => { + ExprRange(folder.fold_expr(e1), + e2.map(|x| folder.fold_expr(x))) + } ExprPath(pth) => ExprPath(folder.fold_path(pth)), ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))), ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))), @@ -1466,7 +1496,7 @@ mod test { } // maybe add to expand.rs... - macro_rules! assert_pred ( + macro_rules! assert_pred { ($pred:expr, $predname:expr, $a:expr , $b:expr) => ( { let pred_val = $pred; @@ -1478,7 +1508,7 @@ mod test { } } ) - ) + } // make sure idents get transformed everywhere #[test] fn ident_transformation () { @@ -1504,6 +1534,6 @@ mod test { matches_codepattern, "matches_codepattern", pprust::to_string(|s| fake_print_crate(s, &folded_crate)), - "zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)))".to_string()); + "zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string()); } } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index c9d72603b89..d5093c5055c 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -16,7 +16,6 @@ #![crate_name = "syntax"] #![experimental] -#![license = "MIT/ASL2"] #![crate_type = "dylib"] #![crate_type = "rlib"] #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", @@ -24,8 +23,9 @@ html_root_url = "http://doc.rust-lang.org/nightly/")] #![allow(unknown_features)] -#![feature(if_let, macro_rules, globs, default_type_params, phase, slicing_syntax)] -#![feature(quote, unsafe_destructor, import_shadowing)] +#![feature(macro_rules, globs, default_type_params, phase, slicing_syntax)] +#![feature(quote, unsafe_destructor)] +#![feature(unboxed_closures)] extern crate arena; extern crate fmt_macros; @@ -34,6 +34,8 @@ extern crate serialize; extern crate term; extern crate libc; +extern crate "serialize" as rustc_serialize; // used by deriving + pub mod util { pub mod interner; #[cfg(test)] diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index f622e2d6112..3023c547fb0 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -10,112 +10,54 @@ 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 + &*self.data } - 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() - } - - pub fn move_iter(self) -> vec::MoveItems<T> { + pub fn move_iter(self) -> vec::IntoIter<T> { self.into_vec().into_iter() } - pub fn map<U>(&self, f: |&T| -> U) -> OwnedSlice<U> { + pub fn map<U, F: FnMut(&T) -> U>(&self, f: F) -> 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,22 +72,8 @@ 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>>(mut iter: I) -> OwnedSlice<T> { + fn from_iter<I: Iterator<T>>(iter: I) -> OwnedSlice<T> { OwnedSlice::from_vec(iter.collect()) } } diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 0c919daa8ed..41693d9d47a 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -92,14 +92,13 @@ impl<'a> ParserAttr for Parser<'a> { } _ => { let token_str = self.this_token_to_string(); - self.fatal(format!("expected `#`, found `{}`", - token_str).as_slice()); + self.fatal(format!("expected `#`, found `{}`", token_str)[]); } }; if permit_inner && self.eat(&token::Semi) { self.span_warn(span, "this inner attribute syntax is deprecated. \ - The new syntax is `#![foo]`, with a bang and no semicolon."); + The new syntax is `#![foo]`, with a bang and no semicolon"); style = ast::AttrInner; } @@ -212,7 +211,7 @@ impl<'a> ParserAttr for Parser<'a> { fn parse_meta_seq(&mut self) -> Vec<P<ast::MetaItem>> { self.parse_seq(&token::OpenDelim(token::Paren), &token::CloseDelim(token::Paren), - seq_sep_trailing_disallowed(token::Comma), + seq_sep_trailing_allowed(token::Comma), |p| p.parse_meta_item()).node } diff --git a/src/libsyntax/parse/common.rs b/src/libsyntax/parse/common.rs index 3842170d677..a96bf1ce10b 100644 --- a/src/libsyntax/parse/common.rs +++ b/src/libsyntax/parse/common.rs @@ -19,18 +19,13 @@ pub struct SeqSep { pub trailing_sep_allowed: bool } -pub fn seq_sep_trailing_disallowed(t: token::Token) -> SeqSep { - SeqSep { - sep: Some(t), - trailing_sep_allowed: false, - } -} pub fn seq_sep_trailing_allowed(t: token::Token) -> SeqSep { SeqSep { sep: Some(t), trailing_sep_allowed: true, } } + pub fn seq_sep_none() -> SeqSep { SeqSep { sep: None, diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index b62d2d744c9..b8da8365f7e 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -24,7 +24,7 @@ use std::str; use std::string::String; use std::uint; -#[deriving(Clone, PartialEq)] +#[deriving(Clone, Copy, PartialEq)] pub enum CommentStyle { /// No code on either side of each line of the comment Isolated, @@ -66,24 +66,23 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { let mut j = lines.len(); // first line of all-stars should be omitted if lines.len() > 0 && - lines[0].as_slice().chars().all(|c| c == '*') { + lines[0].chars().all(|c| c == '*') { i += 1; } - while i < j && lines[i].as_slice().trim().is_empty() { + while i < j && lines[i].trim().is_empty() { i += 1; } // like the first, a last line of all stars should be omitted if j > i && lines[j - 1] - .as_slice() .chars() .skip(1) .all(|c| c == '*') { j -= 1; } - while j > i && lines[j - 1].as_slice().trim().is_empty() { + while j > i && lines[j - 1].trim().is_empty() { j -= 1; } - return lines.slice(i, j).iter().map(|x| (*x).clone()).collect(); + return lines[i..j].iter().map(|x| (*x).clone()).collect(); } /// remove a "[ \t]*\*" block from each line, if possible @@ -92,7 +91,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { let mut can_trim = true; let mut first = true; for line in lines.iter() { - for (j, c) in line.as_slice().chars().enumerate() { + for (j, c) in line.chars().enumerate() { if j > i || !"* \t".contains_char(c) { can_trim = false; break; @@ -117,7 +116,7 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { if can_trim { lines.iter().map(|line| { - line.as_slice().slice(i + 1, line.len()).to_string() + line[i + 1..line.len()].to_string() }).collect() } else { lines @@ -128,12 +127,12 @@ pub fn strip_doc_comment_decoration(comment: &str) -> String { static ONLINERS: &'static [&'static str] = &["///!", "///", "//!", "//"]; for prefix in ONLINERS.iter() { if comment.starts_with(*prefix) { - return comment.slice_from(prefix.len()).to_string(); + return comment[prefix.len()..].to_string(); } } if comment.starts_with("/*") { - let lines = comment.slice(3u, comment.len() - 2u) + let lines = comment[3u..comment.len() - 2u] .lines_any() .map(|s| s.to_string()) .collect::<Vec<String> >(); @@ -188,7 +187,7 @@ fn read_line_comments(rdr: &mut StringReader, code_to_the_left: bool, let line = rdr.read_one_line_comment(); debug!("{}", line); // Doc comments are not put in comments. - if is_doc_comment(line.as_slice()) { + if is_doc_comment(line[]) { break; } lines.push(line); @@ -225,10 +224,10 @@ fn all_whitespace(s: &str, col: CharPos) -> Option<uint> { fn trim_whitespace_prefix_and_push_line(lines: &mut Vec<String> , s: String, col: CharPos) { let len = s.len(); - let s1 = match all_whitespace(s.as_slice(), col) { + let s1 = match all_whitespace(s[], col) { Some(col) => { if col < len { - s.as_slice().slice(col, len).to_string() + s[col..len].to_string() } else { "".to_string() } @@ -262,10 +261,10 @@ fn read_block_comment(rdr: &mut StringReader, rdr.bump(); rdr.bump(); } - if is_block_doc_comment(curr_line.as_slice()) { + if is_block_doc_comment(curr_line[]) { return } - assert!(!curr_line.as_slice().contains_char('\n')); + assert!(!curr_line.contains_char('\n')); lines.push(curr_line); } else { let mut level: int = 1; @@ -390,41 +389,41 @@ mod test { #[test] fn test_block_doc_comment_1() { let comment = "/**\n * Test \n ** Test\n * Test\n*/"; let stripped = strip_doc_comment_decoration(comment); - assert_eq!(stripped, " Test \n* Test\n Test".to_string()); + assert_eq!(stripped, " Test \n* Test\n Test"); } #[test] fn test_block_doc_comment_2() { let comment = "/**\n * Test\n * Test\n*/"; let stripped = strip_doc_comment_decoration(comment); - assert_eq!(stripped, " Test\n Test".to_string()); + assert_eq!(stripped, " Test\n Test"); } #[test] fn test_block_doc_comment_3() { let comment = "/**\n let a: *int;\n *a = 5;\n*/"; let stripped = strip_doc_comment_decoration(comment); - assert_eq!(stripped, " let a: *int;\n *a = 5;".to_string()); + assert_eq!(stripped, " let a: *int;\n *a = 5;"); } #[test] fn test_block_doc_comment_4() { let comment = "/*******************\n test\n *********************/"; let stripped = strip_doc_comment_decoration(comment); - assert_eq!(stripped, " test".to_string()); + assert_eq!(stripped, " test"); } #[test] fn test_line_doc_comment() { let stripped = strip_doc_comment_decoration("/// test"); - assert_eq!(stripped, " test".to_string()); + assert_eq!(stripped, " test"); let stripped = strip_doc_comment_decoration("///! test"); - assert_eq!(stripped, " test".to_string()); + assert_eq!(stripped, " test"); let stripped = strip_doc_comment_decoration("// test"); - assert_eq!(stripped, " test".to_string()); + assert_eq!(stripped, " test"); let stripped = strip_doc_comment_decoration("// test"); - assert_eq!(stripped, " test".to_string()); + assert_eq!(stripped, " test"); let stripped = strip_doc_comment_decoration("///test"); - assert_eq!(stripped, "test".to_string()); + assert_eq!(stripped, "test"); let stripped = strip_doc_comment_decoration("///!test"); - assert_eq!(stripped, "test".to_string()); + assert_eq!(stripped, "test"); let stripped = strip_doc_comment_decoration("//test"); - assert_eq!(stripped, "test".to_string()); + assert_eq!(stripped, "test"); } } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index a88029e087b..13d020f6ae3 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -194,7 +194,7 @@ impl<'a> StringReader<'a> { let mut m = m.to_string(); m.push_str(": "); for c in c.escape_default() { m.push(c) } - self.fatal_span_(from_pos, to_pos, m.as_slice()); + self.fatal_span_(from_pos, to_pos, m[]); } /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an @@ -203,7 +203,7 @@ impl<'a> StringReader<'a> { let mut m = m.to_string(); m.push_str(": "); for c in c.escape_default() { m.push(c) } - self.err_span_(from_pos, to_pos, m.as_slice()); + self.err_span_(from_pos, to_pos, m[]); } /// Report a lexical error spanning [`from_pos`, `to_pos`), appending the @@ -212,8 +212,8 @@ impl<'a> StringReader<'a> { m.push_str(": "); let from = self.byte_offset(from_pos).to_uint(); let to = self.byte_offset(to_pos).to_uint(); - m.push_str(self.filemap.src.as_slice().slice(from, to)); - self.fatal_span_(from_pos, to_pos, m.as_slice()); + m.push_str(self.filemap.src[from..to]); + self.fatal_span_(from_pos, to_pos, m[]); } /// Advance peek_tok and peek_span to refer to the next token, and @@ -244,7 +244,9 @@ impl<'a> StringReader<'a> { /// Calls `f` with a string slice of the source text spanning from `start` /// up to but excluding `self.last_pos`, meaning the slice does not include /// the character `self.curr`. - pub fn with_str_from<T>(&self, start: BytePos, f: |s: &str| -> T) -> T { + pub fn with_str_from<T, F>(&self, start: BytePos, f: F) -> T where + F: FnOnce(&str) -> T, + { self.with_str_from_to(start, self.last_pos, f) } @@ -264,21 +266,23 @@ impl<'a> StringReader<'a> { /// Calls `f` with a string slice of the source text spanning from `start` /// up to but excluding `end`. - fn with_str_from_to<T>(&self, start: BytePos, end: BytePos, f: |s: &str| -> T) -> T { - f(self.filemap.src.as_slice().slice( + fn with_str_from_to<T, F>(&self, start: BytePos, end: BytePos, f: F) -> T where + F: FnOnce(&str) -> T, + { + f(self.filemap.src.slice( self.byte_offset(start).to_uint(), self.byte_offset(end).to_uint())) } /// Converts CRLF to LF in the given string, raising an error on bare CR. - fn translate_crlf<'a>(&self, start: BytePos, - s: &'a str, errmsg: &'a str) -> str::MaybeOwned<'a> { + fn translate_crlf<'b>(&self, start: BytePos, + s: &'b str, errmsg: &'b str) -> str::CowString<'b> { let mut i = 0u; while i < s.len() { let str::CharRange { ch, next } = s.char_range_at(i); if ch == '\r' { if next < s.len() && s.char_at(next) == '\n' { - return translate_crlf_(self, start, s, errmsg, i).into_maybe_owned(); + return translate_crlf_(self, start, s, errmsg, i).into_cow(); } let pos = start + BytePos(i as u32); let end_pos = start + BytePos(next as u32); @@ -286,7 +290,7 @@ impl<'a> StringReader<'a> { } i = next; } - return s.into_maybe_owned(); + return s.into_cow(); fn translate_crlf_(rdr: &StringReader, start: BytePos, s: &str, errmsg: &str, mut i: uint) -> String { @@ -295,7 +299,7 @@ impl<'a> StringReader<'a> { while i < s.len() { let str::CharRange { ch, next } = s.char_range_at(i); if ch == '\r' { - if j < i { buf.push_str(s.slice(j, i)); } + if j < i { buf.push_str(s[j..i]); } j = next; if next >= s.len() || s.char_at(next) != '\n' { let pos = start + BytePos(i as u32); @@ -305,7 +309,7 @@ impl<'a> StringReader<'a> { } i = next; } - if j < s.len() { buf.push_str(s.slice_from(j)); } + if j < s.len() { buf.push_str(s[j..]); } buf } } @@ -321,7 +325,6 @@ impl<'a> StringReader<'a> { let last_char = self.curr.unwrap(); let next = self.filemap .src - .as_slice() .char_range_at(current_byte_offset); let byte_offset_diff = next.next - current_byte_offset; self.pos = self.pos + Pos::from_uint(byte_offset_diff); @@ -343,7 +346,7 @@ impl<'a> StringReader<'a> { pub fn nextch(&self) -> Option<char> { let offset = self.byte_offset(self.pos).to_uint(); if offset < self.filemap.src.len() { - Some(self.filemap.src.as_slice().char_at(offset)) + Some(self.filemap.src.char_at(offset)) } else { None } @@ -355,7 +358,7 @@ impl<'a> StringReader<'a> { pub fn nextnextch(&self) -> Option<char> { let offset = self.byte_offset(self.pos).to_uint(); - let s = self.filemap.deref().src.as_slice(); + let s = self.filemap.deref().src[]; if offset >= s.len() { return None } let str::CharRange { next, .. } = s.char_range_at(offset); if next < s.len() { @@ -550,8 +553,8 @@ impl<'a> StringReader<'a> { let string = if has_cr { self.translate_crlf(start_bpos, string, "bare CR not allowed in block doc-comment") - } else { string.into_maybe_owned() }; - token::DocComment(token::intern(string.as_slice())) + } else { string.into_cow() }; + token::DocComment(token::intern(string[])) } else { token::Comment }; @@ -764,6 +767,13 @@ impl<'a> StringReader<'a> { } } + fn old_escape_warning(&mut self, sp: Span) { + self.span_diagnostic + .span_warn(sp, "\\U00ABCD12 and \\uABCD escapes are deprecated"); + self.span_diagnostic + .span_help(sp, "use \\u{ABCD12} escapes instead"); + } + /// Scan for a single (possibly escaped) byte or char /// in a byte, (non-raw) byte string, char, or (non-raw) string literal. /// `start` is the position of `first_source_char`, which is already consumed. @@ -782,12 +792,22 @@ impl<'a> StringReader<'a> { Some(e) => { return match e { 'n' | 'r' | 't' | '\\' | '\'' | '"' | '0' => true, - 'x' => self.scan_hex_digits(2u, delim, !ascii_only), + 'x' => self.scan_byte_escape(delim, !ascii_only), 'u' if !ascii_only => { - self.scan_hex_digits(4u, delim, false) + if self.curr == Some('{') { + self.scan_unicode_escape(delim) + } else { + let res = self.scan_hex_digits(4u, delim, false); + let sp = codemap::mk_sp(escaped_pos, self.last_pos); + self.old_escape_warning(sp); + res + } } 'U' if !ascii_only => { - self.scan_hex_digits(8u, delim, false) + let res = self.scan_hex_digits(8u, delim, false); + let sp = codemap::mk_sp(escaped_pos, self.last_pos); + self.old_escape_warning(sp); + res } '\n' if delim == '"' => { self.consume_whitespace(); @@ -809,7 +829,7 @@ impl<'a> StringReader<'a> { self.span_diagnostic.span_help( sp, "this is an isolated carriage return; consider checking \ - your editor and version control settings.") + your editor and version control settings") } false } @@ -848,6 +868,56 @@ impl<'a> StringReader<'a> { true } + /// Scan over a \u{...} escape + /// + /// At this point, we have already seen the \ and the u, the { is the current character. We + /// will read at least one digit, and up to 6, and pass over the }. + fn scan_unicode_escape(&mut self, delim: char) -> bool { + self.bump(); // past the { + let start_bpos = self.last_pos; + let mut count: uint = 0; + let mut accum_int = 0; + + while !self.curr_is('}') && count <= 6 { + let c = match self.curr { + Some(c) => c, + None => { + self.fatal_span_(start_bpos, self.last_pos, + "unterminated unicode escape (found EOF)"); + } + }; + accum_int *= 16; + accum_int += c.to_digit(16).unwrap_or_else(|| { + if c == delim { + self.fatal_span_(self.last_pos, self.pos, + "unterminated unicode escape (needed a `}`)"); + } else { + self.fatal_span_char(self.last_pos, self.pos, + "illegal character in unicode escape", c); + } + }) as u32; + self.bump(); + count += 1; + } + + if count > 6 { + self.fatal_span_(start_bpos, self.last_pos, + "overlong unicode escape (can have at most 6 hex digits)"); + } + + self.bump(); // past the ending } + + let mut valid = count >= 1 && count <= 6; + if char::from_u32(accum_int).is_none() { + valid = false; + } + + if !valid { + self.fatal_span_(start_bpos, self.last_pos, "illegal unicode character escape"); + } + valid + } + /// Scan over a float exponent. fn scan_float_exponent(&mut self) { if self.curr_is('e') || self.curr_is('E') { @@ -1038,7 +1108,7 @@ impl<'a> StringReader<'a> { // expansion purposes. See #12512 for the gory details of why // this is necessary. let ident = self.with_str_from(start, |lifetime_name| { - str_to_ident(format!("'{}", lifetime_name).as_slice()) + str_to_ident(format!("'{}", lifetime_name)[]) }); // Conjure up a "keyword checking ident" to make sure that @@ -1273,6 +1343,10 @@ impl<'a> StringReader<'a> { return token::Byte(id); } + fn scan_byte_escape(&mut self, delim: char, below_0x7f_only: bool) -> bool { + self.scan_hex_digits(2, delim, below_0x7f_only) + } + fn scan_byte_string(&mut self) -> token::Lit { self.bump(); let start = self.last_pos; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 96659031e6a..8cefb111fd1 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -251,17 +251,17 @@ pub fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>) Err(e) => { err(format!("couldn't read {}: {}", path.display(), - e).as_slice()); + e)[]); unreachable!() } }; - match str::from_utf8(bytes.as_slice()) { + match str::from_utf8(bytes[]).ok() { Some(s) => { return string_to_filemap(sess, s.to_string(), path.as_str().unwrap().to_string()) } None => { - err(format!("{} is not UTF-8 encoded", path.display()).as_slice()) + err(format!("{} is not UTF-8 encoded", path.display())[]) } } unreachable!() @@ -391,18 +391,30 @@ pub fn char_lit(lit: &str) -> (char, int) { } let msg = format!("lexer should have rejected a bad character escape {}", lit); - let msg2 = msg.as_slice(); + let msg2 = msg[]; - let esc: |uint| -> Option<(char, int)> = |len| - num::from_str_radix(lit.slice(2, len), 16) + fn esc(len: uint, lit: &str) -> Option<(char, int)> { + num::from_str_radix(lit[2..len], 16) .and_then(char::from_u32) - .map(|x| (x, len as int)); + .map(|x| (x, len as int)) + } + + let unicode_escape: || -> Option<(char, int)> = || + if lit.as_bytes()[2] == b'{' { + let idx = lit.find('}').expect(msg2); + let subslice = lit[3..idx]; + num::from_str_radix(subslice, 16) + .and_then(char::from_u32) + .map(|x| (x, subslice.chars().count() as int + 4)) + } else { + esc(6, lit) + }; // Unicode escapes return match lit.as_bytes()[1] as char { - 'x' | 'X' => esc(4), - 'u' => esc(6), - 'U' => esc(10), + 'x' | 'X' => esc(4, lit), + 'u' => unicode_escape(), + 'U' => esc(10, lit), _ => None, }.expect(msg2); } @@ -417,9 +429,9 @@ pub fn str_lit(lit: &str) -> String { let error = |i| format!("lexer should have rejected {} at {}", lit, i); /// Eat everything up to a non-whitespace - fn eat<'a>(it: &mut iter::Peekable<(uint, char), str::CharOffsets<'a>>) { + fn eat<'a>(it: &mut iter::Peekable<(uint, char), str::CharIndices<'a>>) { loop { - match it.peek().map(|x| x.val1()) { + match it.peek().map(|x| x.1) { Some(' ') | Some('\n') | Some('\r') | Some('\t') => { it.next(); }, @@ -436,7 +448,7 @@ pub fn str_lit(lit: &str) -> String { '\\' => { let ch = chars.peek().unwrap_or_else(|| { panic!("{}", error(i).as_slice()) - }).val1(); + }).1; if ch == '\n' { eat(&mut chars); @@ -444,7 +456,7 @@ pub fn str_lit(lit: &str) -> String { chars.next(); let ch = chars.peek().unwrap_or_else(|| { panic!("{}", error(i).as_slice()) - }).val1(); + }).1; if ch != '\n' { panic!("lexer accepted bare CR"); @@ -452,7 +464,7 @@ pub fn str_lit(lit: &str) -> String { eat(&mut chars); } else { // otherwise, a normal escape - let (c, n) = char_lit(lit.slice_from(i)); + let (c, n) = char_lit(lit[i..]); for _ in range(0, n - 1) { // we don't need to move past the first \ chars.next(); } @@ -462,7 +474,7 @@ pub fn str_lit(lit: &str) -> String { '\r' => { let ch = chars.peek().unwrap_or_else(|| { panic!("{}", error(i).as_slice()) - }).val1(); + }).1; if ch != '\n' { panic!("lexer accepted bare CR"); @@ -515,7 +527,7 @@ pub fn raw_str_lit(lit: &str) -> String { fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { s.len() > 1 && first_chars.contains(&s.char_at(0)) && - s.slice_from(1).chars().all(|c| '0' <= c && c <= '9') + s[1..].chars().all(|c| '0' <= c && c <= '9') } fn filtered_float_lit(data: token::InternedString, suffix: Option<&str>, @@ -528,7 +540,7 @@ fn filtered_float_lit(data: token::InternedString, suffix: Option<&str>, if suf.len() >= 2 && looks_like_width_suffix(&['f'], suf) { // if it looks like a width, lets try to be helpful. sd.span_err(sp, &*format!("illegal width `{}` for float literal, \ - valid widths are 32 and 64", suf.slice_from(1))); + valid widths are 32 and 64", suf[1..])); } else { sd.span_err(sp, &*format!("illegal suffix `{}` for float literal, \ valid suffixes are `f32` and `f64`", suf)); @@ -564,7 +576,7 @@ pub fn byte_lit(lit: &str) -> (u8, uint) { b'\'' => b'\'', b'0' => b'\0', _ => { - match ::std::num::from_str_radix::<u64>(lit.slice(2, 4), 16) { + match ::std::num::from_str_radix::<u64>(lit[2..4], 16) { Some(c) => if c > 0xFF { panic!(err(2)) @@ -588,7 +600,7 @@ pub fn binary_lit(lit: &str) -> Rc<Vec<u8>> { /// Eat everything up to a non-whitespace fn eat<'a, I: Iterator<(uint, u8)>>(it: &mut iter::Peekable<(uint, u8), I>) { loop { - match it.peek().map(|x| x.val1()) { + match it.peek().map(|x| x.1) { Some(b' ') | Some(b'\n') | Some(b'\r') | Some(b'\t') => { it.next(); }, @@ -603,18 +615,18 @@ pub fn binary_lit(lit: &str) -> Rc<Vec<u8>> { match chars.next() { Some((i, b'\\')) => { let em = error(i); - match chars.peek().expect(em.as_slice()).val1() { + match chars.peek().expect(em.as_slice()).1 { b'\n' => eat(&mut chars), b'\r' => { chars.next(); - if chars.peek().expect(em.as_slice()).val1() != b'\n' { + if chars.peek().expect(em.as_slice()).1 != b'\n' { panic!("lexer accepted bare CR"); } eat(&mut chars); } _ => { // otherwise, a normal escape - let (c, n) = byte_lit(lit.slice_from(i)); + let (c, n) = byte_lit(lit[i..]); // we don't need to move past the first \ for _ in range(0, n - 1) { chars.next(); @@ -625,7 +637,7 @@ pub fn binary_lit(lit: &str) -> Rc<Vec<u8>> { }, Some((i, b'\r')) => { let em = error(i); - if chars.peek().expect(em.as_slice()).val1() != b'\n' { + if chars.peek().expect(em.as_slice()).1 != b'\n' { panic!("lexer accepted bare CR"); } chars.next(); @@ -643,7 +655,7 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> // s can only be ascii, byte indexing is fine let s2 = s.chars().filter(|&c| c != '_').collect::<String>(); - let mut s = s2.as_slice(); + let mut s = s2[]; debug!("integer_lit: {}, {}", s, suffix); @@ -676,7 +688,7 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> } if base != 10 { - s = s.slice_from(2); + s = s[2..]; } if let Some(suf) = suffix { @@ -698,7 +710,7 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> if looks_like_width_suffix(&['i', 'u'], suf) { sd.span_err(sp, &*format!("illegal width `{}` for integer literal; \ valid widths are 8, 16, 32 and 64", - suf.slice_from(1))); + suf[1..])); } else { sd.span_err(sp, &*format!("illegal suffix `{}` for numeric literal", suf)); } @@ -733,8 +745,7 @@ mod test { use owned_slice::OwnedSlice; use ast; use abi; - use attr; - use attr::AttrMetaMethods; + use attr::{first_attr_value_str_by_name, AttrMetaMethods}; use parse::parser::Parser; use parse::token::{str_to_ident}; use print::pprust::view_item_to_string; @@ -797,7 +808,7 @@ mod test { #[test] fn string_to_tts_macro () { let tts = string_to_tts("macro_rules! zip (($a)=>($a))".to_string()); - let tts: &[ast::TokenTree] = tts.as_slice(); + let tts: &[ast::TokenTree] = tts[]; match tts { [ast::TtToken(_, token::Ident(name_macro_rules, token::Plain)), ast::TtToken(_, token::Not), @@ -805,19 +816,19 @@ mod test { ast::TtDelimited(_, ref macro_delimed)] if name_macro_rules.as_str() == "macro_rules" && name_zip.as_str() == "zip" => { - match macro_delimed.tts.as_slice() { + match macro_delimed.tts[] { [ast::TtDelimited(_, ref first_delimed), ast::TtToken(_, token::FatArrow), ast::TtDelimited(_, ref second_delimed)] if macro_delimed.delim == token::Paren => { - match first_delimed.tts.as_slice() { + match first_delimed.tts[] { [ast::TtToken(_, token::Dollar), ast::TtToken(_, token::Ident(name, token::Plain))] if first_delimed.delim == token::Paren && name.as_str() == "a" => {}, _ => panic!("value 3: {}", **first_delimed), } - match second_delimed.tts.as_slice() { + match second_delimed.tts[] { [ast::TtToken(_, token::Dollar), ast::TtToken(_, token::Ident(name, token::Plain))] if second_delimed.delim == token::Paren @@ -942,7 +953,7 @@ mod test { }\ ]\ }\ -]".to_string() +]" ); } @@ -1029,7 +1040,7 @@ mod test { parameters: ast::PathParameters::none(), } ), - }, None, ast::DUMMY_NODE_ID), + }, ast::DUMMY_NODE_ID), span:sp(10,13) }), pat: P(ast::Pat { @@ -1050,7 +1061,7 @@ mod test { span:sp(15,15)})), // not sure variadic: false }), - ast::NormalFn, + ast::Unsafety::Normal, abi::Rust, ast::Generics{ // no idea on either of these: lifetimes: Vec::new(), @@ -1095,24 +1106,24 @@ mod test { let use_s = "use foo::bar::baz;"; let vitem = string_to_view_item(use_s.to_string()); let vitem_s = view_item_to_string(&vitem); - assert_eq!(vitem_s.as_slice(), use_s); + assert_eq!(vitem_s[], use_s); let use_s = "use foo::bar as baz;"; let vitem = string_to_view_item(use_s.to_string()); let vitem_s = view_item_to_string(&vitem); - assert_eq!(vitem_s.as_slice(), use_s); + assert_eq!(vitem_s[], use_s); } #[test] fn parse_extern_crate() { let ex_s = "extern crate foo;"; let vitem = string_to_view_item(ex_s.to_string()); let vitem_s = view_item_to_string(&vitem); - assert_eq!(vitem_s.as_slice(), ex_s); + assert_eq!(vitem_s[], ex_s); let ex_s = "extern crate \"foo\" as bar;"; let vitem = string_to_view_item(ex_s.to_string()); let vitem_s = view_item_to_string(&vitem); - assert_eq!(vitem_s.as_slice(), ex_s); + assert_eq!(vitem_s[], ex_s); } fn get_spans_of_pat_idents(src: &str) -> Vec<Span> { @@ -1150,9 +1161,9 @@ mod test { for &src in srcs.iter() { let spans = get_spans_of_pat_idents(src); let Span{lo:lo,hi:hi,..} = spans[0]; - assert!("self" == src.slice(lo.to_uint(), hi.to_uint()), + assert!("self" == src[lo.to_uint()..hi.to_uint()], "\"{}\" != \"self\". src=\"{}\"", - src.slice(lo.to_uint(), hi.to_uint()), src) + src[lo.to_uint()..hi.to_uint()], src) } } @@ -1183,7 +1194,7 @@ mod test { let name = "<source>".to_string(); let source = "/// doc comment\r\nfn foo() {}".to_string(); let item = parse_item_from_source_str(name.clone(), source, Vec::new(), &sess).unwrap(); - let doc = attr::first_attr_value_str_by_name(item.attrs.as_slice(), "doc").unwrap(); + let doc = first_attr_value_str_by_name(item.attrs.as_slice(), "doc").unwrap(); assert_eq!(doc.get(), "/// doc comment"); let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string(); @@ -1191,11 +1202,11 @@ mod test { let docs = item.attrs.iter().filter(|a| a.name().get() == "doc") .map(|a| a.value_str().unwrap().get().to_string()).collect::<Vec<_>>(); let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()]; - assert_eq!(docs.as_slice(), b); + assert_eq!(docs[], b); let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string(); let item = parse_item_from_source_str(name, source, Vec::new(), &sess).unwrap(); - let doc = attr::first_attr_value_str_by_name(item.attrs.as_slice(), "doc").unwrap(); + let doc = first_attr_value_str_by_name(item.attrs.as_slice(), "doc").unwrap(); assert_eq!(doc.get(), "/** doc comment\n * with CRLF */"); } } diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index e2dee607c69..e3c831c09ba 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::*; @@ -26,7 +22,7 @@ use parse::token; use ptr::P; /// The specific types of unsupported syntax -#[deriving(PartialEq, Eq, Hash)] +#[deriving(Copy, PartialEq, Eq, Hash)] pub enum ObsoleteSyntax { ObsoleteOwnedType, ObsoleteOwnedExpr, @@ -36,6 +32,8 @@ pub enum ObsoleteSyntax { ObsoleteImportRenaming, ObsoleteSubsliceMatch, ObsoleteExternCrateRenaming, + ObsoleteProcType, + ObsoleteProcExpr, } pub trait ParserObsoleteMethods { @@ -57,6 +55,14 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { /// Reports an obsolete syntax non-fatal error. fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) { let (kind_str, desc) = match kind { + ObsoleteProcType => ( + "the `proc` type", + "use unboxed closures instead", + ), + ObsoleteProcExpr => ( + "`proc` expression", + "use a `move ||` expression instead", + ), ObsoleteOwnedType => ( "`~` notation for owned pointers", "use `Box<T>` in `std::owned` instead" @@ -107,13 +113,13 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { kind_str: &str, desc: &str) { self.span_err(sp, - format!("obsolete syntax: {}", kind_str).as_slice()); + format!("obsolete syntax: {}", kind_str)[]); if !self.obsolete_set.contains(&kind) { self.sess .span_diagnostic .handler() - .note(format!("{}", desc).as_slice()); + .note(format!("{}", desc)[]); self.obsolete_set.insert(kind); } } @@ -121,7 +127,7 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> { fn is_obsolete_ident(&mut self, ident: &str) -> bool { match self.token { token::Ident(sid, _) => { - token::get_ident(sid).equiv(&ident) + token::get_ident(sid) == ident } _ => false } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index ab0543d64b7..94b61ba56d2 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -16,7 +16,7 @@ use self::ItemOrViewItem::*; use abi; use ast::{AssociatedType, BareFnTy, ClosureTy}; use ast::{RegionTyParamBound, TraitTyParamBound}; -use ast::{ProvidedMethod, Public, FnStyle}; +use ast::{ProvidedMethod, Public, Unsafety}; use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue}; use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, Block}; use ast::{BlockCheckMode, CaptureByRef, CaptureByValue, CaptureClause}; @@ -26,62 +26,57 @@ use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain}; use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox}; use ast::{ExprBreak, ExprCall, ExprCast}; use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex, ExprSlice}; -use ast::{ExprLit, ExprLoop, ExprMac}; -use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc}; +use ast::{ExprLit, ExprLoop, ExprMac, ExprRange}; +use ast::{ExprMethodCall, ExprParen, ExprPath}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary}; use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl}; -use ast::{Once, Many}; +use ast::{Many}; use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind}; use ast::{FnOnceUnboxedClosureKind}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy}; -use ast::{Ident, NormalFn, Inherited, ImplItem, Item, Item_, ItemStatic}; +use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic}; use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst}; use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy}; use ast::{LifetimeDef, Lit, Lit_}; use ast::{LitBool, LitChar, LitByte, LitBinary}; use ast::{LitStr, LitInt, Local, LocalLet}; -use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchNormal}; +use ast::{MacStmtWithBraces, MacStmtWithSemicolon, MacStmtWithoutBraces}; +use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchSource}; use ast::{Method, MutTy, BiMul, Mutability}; -use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot}; +use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, NodeId, UnNot}; use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct}; use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle}; use ast::{PolyTraitRef}; use ast::{QPath, RequiredMethod}; use ast::{Return, BiShl, BiShr, Stmt, StmtDecl}; use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField}; -use ast::{StructVariantKind, BiSub}; -use ast::StrStyle; +use ast::{StructVariantKind, BiSub, StrStyle}; use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue}; use ast::{Delimited, SequenceRepetition, TokenTree, TraitItem, TraitRef}; use ast::{TtDelimited, TtSequence, TtToken}; -use ast::{TupleVariantKind, Ty, Ty_}; -use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn}; +use ast::{TupleVariantKind, Ty, Ty_, TypeBinding}; +use ast::{TypeField, TyFixedLengthVec, TyClosure, TyBareFn}; use ast::{TyTypeof, TyInfer, TypeMethod}; use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath}; use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq}; use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind}; use ast::{UnnamedField, UnsafeBlock}; -use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse}; +use ast::{ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; -use ast::{Visibility, WhereClause, WherePredicate}; +use ast::{Visibility, WhereClause}; use ast; -use ast_util::{as_prec, ident_to_path, operator_prec}; -use ast_util; -use codemap::{Span, BytePos, Spanned, spanned, mk_sp}; -use codemap; +use ast_util::{mod, as_prec, ident_to_path, operator_prec}; +use codemap::{mod, Span, BytePos, Spanned, spanned, mk_sp}; use diagnostic; use ext::tt::macro_parser; use parse; use parse::attr::ParserAttr; use parse::classify; -use parse::common::{SeqSep, seq_sep_none}; -use parse::common::{seq_sep_trailing_allowed}; -use parse::lexer::Reader; -use parse::lexer::TokenAndSpan; +use parse::common::{SeqSep, seq_sep_none, seq_sep_trailing_allowed}; +use parse::lexer::{Reader, TokenAndSpan}; use parse::obsolete::*; -use parse::token::{MatchNt, SubstNt, InternedString}; +use parse::token::{mod, MatchNt, SubstNt, InternedString}; use parse::token::{keywords, special_idents}; -use parse::token; use parse::{new_sub_parser_from_file, ParseSess}; use print::pprust; use ptr::P; @@ -89,26 +84,28 @@ use owned_slice::OwnedSlice; use std::collections::HashSet; use std::io::fs::PathExtensions; -use std::mem::replace; use std::mem; use std::num::Float; use std::rc::Rc; use std::iter; +use std::slice; bitflags! { flags Restrictions: u8 { const UNRESTRICTED = 0b0000, const RESTRICTION_STMT_EXPR = 0b0001, const RESTRICTION_NO_BAR_OP = 0b0010, - const RESTRICTION_NO_STRUCT_LITERAL = 0b0100 + const RESTRICTION_NO_STRUCT_LITERAL = 0b0100, + const RESTRICTION_NO_DOTS = 0b1000, } } + type ItemInfo = (Ident, Item_, Option<Vec<Attribute> >); /// How to parse a path. There are four different kinds of paths, all of which /// are parsed somewhat differently. -#[deriving(PartialEq)] +#[deriving(Copy, PartialEq)] pub enum PathParsingMode { /// A path with no type parameters; e.g. `foo::bar::Baz` NoTypesAllowed, @@ -118,16 +115,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 { @@ -145,7 +132,7 @@ enum ItemOrViewItem { /// macro expansion). Placement of these is not as complex as I feared it would /// be. The important thing is to make sure that lookahead doesn't balk at /// `token::Interpolated` tokens. -macro_rules! maybe_whole_expr ( +macro_rules! maybe_whole_expr { ($p:expr) => ( { let found = match $p.token { @@ -183,10 +170,10 @@ macro_rules! maybe_whole_expr ( } } ) -) +} /// As maybe_whole_expr, but for things other than expressions -macro_rules! maybe_whole ( +macro_rules! maybe_whole { ($p:expr, $constructor:ident) => ( { let found = match ($p).token { @@ -195,11 +182,8 @@ macro_rules! maybe_whole ( } _ => None }; - match found { - Some(token::Interpolated(token::$constructor(x))) => { - return x.clone() - } - _ => {} + if let Some(token::Interpolated(token::$constructor(x))) = found { + return x.clone(); } } ); @@ -211,11 +195,8 @@ macro_rules! maybe_whole ( } _ => None }; - match found { - Some(token::Interpolated(token::$constructor(x))) => { - return x - } - _ => {} + if let Some(token::Interpolated(token::$constructor(x))) = found { + return x; } } ); @@ -227,11 +208,8 @@ macro_rules! maybe_whole ( } _ => None }; - match found { - Some(token::Interpolated(token::$constructor(x))) => { - return (*x).clone() - } - _ => {} + if let Some(token::Interpolated(token::$constructor(x))) = found { + return (*x).clone(); } } ); @@ -243,11 +221,8 @@ macro_rules! maybe_whole ( } _ => None }; - match found { - Some(token::Interpolated(token::$constructor(x))) => { - return Some(x.clone()), - } - _ => {} + if let Some(token::Interpolated(token::$constructor(x))) = found { + return Some(x.clone()); } } ); @@ -259,11 +234,8 @@ macro_rules! maybe_whole ( } _ => None }; - match found { - Some(token::Interpolated(token::$constructor(x))) => { - return IoviItem(x.clone()) - } - _ => {} + if let Some(token::Interpolated(token::$constructor(x))) = found { + return IoviItem(x.clone()); } } ); @@ -275,15 +247,12 @@ macro_rules! maybe_whole ( } _ => None }; - match found { - Some(token::Interpolated(token::$constructor(x))) => { - return (Vec::new(), x) - } - _ => {} + if let Some(token::Interpolated(token::$constructor(x))) = found { + return (Vec::new(), x); } } ) -) +} fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>) @@ -338,6 +307,22 @@ pub struct Parser<'a> { /// name is not known. This does not change while the parser is descending /// into modules, and sub-parsers have new values for this name. pub root_module_name: Option<String>, + pub expected_tokens: Vec<TokenType>, +} + +#[deriving(PartialEq, Eq, Clone)] +pub enum TokenType { + Token(token::Token), + Operator, +} + +impl TokenType { + fn to_string(&self) -> String { + match *self { + TokenType::Token(ref t) => format!("`{}`", Parser::token_to_string(t)), + TokenType::Operator => "an operator".to_string(), + } + } } fn is_plain_ident_or_underscore(t: &token::Token) -> bool { @@ -382,6 +367,7 @@ impl<'a> Parser<'a> { open_braces: Vec::new(), owns_directory: true, root_module_name: None, + expected_tokens: Vec::new(), } } @@ -399,25 +385,29 @@ impl<'a> Parser<'a> { let token_str = Parser::token_to_string(t); let last_span = self.last_span; self.span_fatal(last_span, format!("unexpected token: `{}`", - token_str).as_slice()); + token_str)[]); } pub fn unexpected(&mut self) -> ! { let this_token = self.this_token_to_string(); - self.fatal(format!("unexpected token: `{}`", this_token).as_slice()); + self.fatal(format!("unexpected token: `{}`", this_token)[]); } /// Expect and consume the token t. Signal an error if /// the next token is not t. pub fn expect(&mut self, t: &token::Token) { - if self.token == *t { - self.bump(); + if self.expected_tokens.is_empty() { + if self.token == *t { + self.bump(); + } else { + let token_str = Parser::token_to_string(t); + let this_token_str = self.this_token_to_string(); + self.fatal(format!("expected `{}`, found `{}`", + token_str, + this_token_str)[]) + } } else { - let token_str = Parser::token_to_string(t); - let this_token_str = self.this_token_to_string(); - self.fatal(format!("expected `{}`, found `{}`", - token_str, - this_token_str).as_slice()) + self.expect_one_of(slice::ref_slice(t), &[]); } } @@ -427,15 +417,20 @@ impl<'a> Parser<'a> { pub fn expect_one_of(&mut self, edible: &[token::Token], inedible: &[token::Token]) { - fn tokens_to_string(tokens: &[token::Token]) -> String { + fn tokens_to_string(tokens: &[TokenType]) -> String { let mut i = tokens.iter(); // This might be a sign we need a connect method on Iterator. let b = i.next() - .map_or("".to_string(), |t| Parser::token_to_string(t)); - i.fold(b, |b,a| { - let mut b = b; - b.push_str("`, `"); - b.push_str(Parser::token_to_string(a).as_slice()); + .map_or("".to_string(), |t| t.to_string()); + i.enumerate().fold(b, |mut b, (i, ref a)| { + if tokens.len() > 2 && i == tokens.len() - 2 { + b.push_str(", or "); + } else if tokens.len() == 2 && i == tokens.len() - 2 { + b.push_str(" or "); + } else { + b.push_str(", "); + } + b.push_str(&*a.to_string()); b }) } @@ -444,20 +439,24 @@ impl<'a> Parser<'a> { } else if inedible.contains(&self.token) { // leave it in the input } else { - let mut expected = edible.iter().map(|x| x.clone()).collect::<Vec<_>>(); - expected.push_all(inedible); - let expect = tokens_to_string(expected.as_slice()); + let mut expected = edible.iter().map(|x| TokenType::Token(x.clone())) + .collect::<Vec<_>>(); + expected.extend(inedible.iter().map(|x| TokenType::Token(x.clone()))); + expected.push_all(&*self.expected_tokens); + expected.sort_by(|a, b| a.to_string().cmp(&b.to_string())); + expected.dedup(); + let expect = tokens_to_string(expected[]); let actual = self.this_token_to_string(); self.fatal( (if expected.len() != 1 { - (format!("expected one of `{}`, found `{}`", + (format!("expected one of {}, found `{}`", expect, actual)) } else { - (format!("expected `{}`, found `{}`", + (format!("expected {}, found `{}`", expect, actual)) - }).as_slice() + })[] ) } } @@ -486,15 +485,11 @@ impl<'a> Parser<'a> { /// from anticipated input errors, discarding erroneous characters. pub fn commit_expr(&mut self, e: &Expr, edible: &[token::Token], inedible: &[token::Token]) { debug!("commit_expr {}", e); - match e.node { - ExprPath(..) => { - // might be unit-struct construction; check for recoverableinput error. - let mut expected = edible.iter().map(|x| x.clone()).collect::<Vec<_>>(); - expected.push_all(inedible); - self.check_for_erroneous_unit_struct_expecting( - expected.as_slice()); - } - _ => {} + if let ExprPath(..) = e.node { + // might be unit-struct construction; check for recoverableinput error. + let mut expected = edible.iter().map(|x| x.clone()).collect::<Vec<_>>(); + expected.push_all(inedible); + self.check_for_erroneous_unit_struct_expecting(expected[]); } self.expect_one_of(edible, inedible) } @@ -511,9 +506,9 @@ impl<'a> Parser<'a> { .as_ref() .map_or(false, |t| t.is_ident() || t.is_path()) { let mut expected = edible.iter().map(|x| x.clone()).collect::<Vec<_>>(); - expected.push_all(inedible.as_slice()); + expected.push_all(inedible[]); self.check_for_erroneous_unit_struct_expecting( - expected.as_slice()); + expected[]); } self.expect_one_of(edible, inedible) } @@ -536,7 +531,7 @@ impl<'a> Parser<'a> { _ => { let token_str = self.this_token_to_string(); self.fatal((format!("expected ident, found `{}`", - token_str)).as_slice()) + token_str))[]) } } } @@ -553,10 +548,20 @@ impl<'a> Parser<'a> { spanned(lo, hi, node) } + /// Check if the next token is `tok`, and return `true` if so. + /// + /// This method is will automatically add `tok` to `expected_tokens` if `tok` is not + /// encountered. + pub fn check(&mut self, tok: &token::Token) -> bool { + let is_present = self.token == *tok; + if !is_present { self.expected_tokens.push(TokenType::Token(tok.clone())); } + is_present + } + /// Consume token 'tok' if it exists. Returns true if the given /// token was present, false otherwise. pub fn eat(&mut self, tok: &token::Token) -> bool { - let is_present = self.token == *tok; + let is_present = self.check(tok); if is_present { self.bump() } is_present } @@ -580,7 +585,7 @@ impl<'a> Parser<'a> { let id_interned_str = token::get_name(kw.to_name()); let token_str = self.this_token_to_string(); self.fatal(format!("expected `{}`, found `{}`", - id_interned_str, token_str).as_slice()) + id_interned_str, token_str)[]) } } @@ -591,7 +596,7 @@ impl<'a> Parser<'a> { let span = self.span; self.span_err(span, format!("expected identifier, found keyword `{}`", - token_str).as_slice()); + token_str)[]); } } @@ -600,7 +605,7 @@ impl<'a> Parser<'a> { if self.token.is_reserved_keyword() { let token_str = self.this_token_to_string(); self.fatal(format!("`{}` is a reserved keyword", - token_str).as_slice()) + token_str)[]) } } @@ -620,7 +625,7 @@ impl<'a> Parser<'a> { Parser::token_to_string(&token::BinOp(token::And)); self.fatal(format!("expected `{}`, found `{}`", found_token, - token_str).as_slice()) + token_str)[]) } } } @@ -641,7 +646,7 @@ impl<'a> Parser<'a> { Parser::token_to_string(&token::BinOp(token::Or)); self.fatal(format!("expected `{}`, found `{}`", token_str, - found_token).as_slice()) + found_token)[]) } } } @@ -707,16 +712,17 @@ impl<'a> Parser<'a> { let token_str = Parser::token_to_string(&token::Lt); self.fatal(format!("expected `{}`, found `{}`", token_str, - found_token).as_slice()) + found_token)[]) } } /// Parse a sequence bracketed by `|` and `|`, stopping before the `|`. - fn parse_seq_to_before_or<T>( - &mut self, - sep: &token::Token, - f: |&mut Parser| -> T) - -> Vec<T> { + fn parse_seq_to_before_or<T, F>(&mut self, + sep: &token::Token, + mut f: F) + -> Vec<T> where + F: FnMut(&mut Parser) -> T, + { let mut first = true; let mut vector = Vec::new(); while self.token != token::BinOp(token::Or) && @@ -758,18 +764,17 @@ impl<'a> Parser<'a> { let this_token_str = self.this_token_to_string(); self.fatal(format!("expected `{}`, found `{}`", gt_str, - this_token_str).as_slice()) + this_token_str)[]) } } } - /// Parse a sequence bracketed by '<' and '>', stopping - /// before the '>'. - pub fn parse_seq_to_before_gt<T>( - &mut self, - sep: Option<token::Token>, - f: |&mut Parser| -> T) - -> OwnedSlice<T> { + pub fn parse_seq_to_before_gt_or_return<T, F>(&mut self, + sep: Option<token::Token>, + mut f: F) + -> (OwnedSlice<T>, bool) where + F: FnMut(&mut Parser) -> Option<T>, + { let mut v = Vec::new(); // This loop works by alternating back and forth between parsing types // and commas. For example, given a string `A, B,>`, the parser would @@ -778,7 +783,7 @@ impl<'a> Parser<'a> { // commas in generic parameters, because it can stop either after // parsing a type or after parsing a comma. for i in iter::count(0u, 1) { - if self.token == token::Gt + if self.check(&token::Gt) || self.token == token::BinOp(token::Shr) || self.token == token::Ge || self.token == token::BinOpEq(token::Shr) { @@ -786,33 +791,64 @@ impl<'a> Parser<'a> { } if i % 2 == 0 { - v.push(f(self)); + match f(self) { + Some(result) => v.push(result), + None => return (OwnedSlice::from_vec(v), true) + } } else { sep.as_ref().map(|t| self.expect(t)); } } - return OwnedSlice::from_vec(v); + return (OwnedSlice::from_vec(v), false); } - pub fn parse_seq_to_gt<T>( - &mut self, - sep: Option<token::Token>, - f: |&mut Parser| -> T) - -> OwnedSlice<T> { + /// Parse a sequence bracketed by '<' and '>', stopping + /// before the '>'. + pub fn parse_seq_to_before_gt<T, F>(&mut self, + sep: Option<token::Token>, + mut f: F) + -> OwnedSlice<T> where + F: FnMut(&mut Parser) -> T, + { + let (result, returned) = self.parse_seq_to_before_gt_or_return(sep, |p| Some(f(p))); + assert!(!returned); + return result; + } + + pub fn parse_seq_to_gt<T, F>(&mut self, + sep: Option<token::Token>, + f: F) + -> OwnedSlice<T> where + F: FnMut(&mut Parser) -> T, + { let v = self.parse_seq_to_before_gt(sep, f); self.expect_gt(); return v; } + pub fn parse_seq_to_gt_or_return<T, F>(&mut self, + sep: Option<token::Token>, + f: F) + -> (OwnedSlice<T>, bool) where + F: FnMut(&mut Parser) -> Option<T>, + { + let (v, returned) = self.parse_seq_to_before_gt_or_return(sep, f); + if !returned { + self.expect_gt(); + } + return (v, returned); + } + /// Parse a sequence, including the closing delimiter. The function /// f must consume tokens until reaching the next separator or /// closing bracket. - pub fn parse_seq_to_end<T>( - &mut self, - ket: &token::Token, - sep: SeqSep, - f: |&mut Parser| -> T) - -> Vec<T> { + pub fn parse_seq_to_end<T, F>(&mut self, + ket: &token::Token, + sep: SeqSep, + f: F) + -> Vec<T> where + F: FnMut(&mut Parser) -> T, + { let val = self.parse_seq_to_before_end(ket, sep, f); self.bump(); val @@ -821,12 +857,13 @@ impl<'a> Parser<'a> { /// Parse a sequence, not including the closing delimiter. The function /// f must consume tokens until reaching the next separator or /// closing bracket. - pub fn parse_seq_to_before_end<T>( - &mut self, - ket: &token::Token, - sep: SeqSep, - f: |&mut Parser| -> T) - -> Vec<T> { + pub fn parse_seq_to_before_end<T, F>(&mut self, + ket: &token::Token, + sep: SeqSep, + mut f: F) + -> Vec<T> where + F: FnMut(&mut Parser) -> T, + { let mut first: bool = true; let mut v = vec!(); while self.token != *ket { @@ -837,7 +874,7 @@ impl<'a> Parser<'a> { } _ => () } - if sep.trailing_sep_allowed && self.token == *ket { break; } + if sep.trailing_sep_allowed && self.check(ket) { break; } v.push(f(self)); } return v; @@ -846,13 +883,14 @@ impl<'a> Parser<'a> { /// Parse a sequence, including the closing delimiter. The function /// f must consume tokens until reaching the next separator or /// closing bracket. - pub fn parse_unspanned_seq<T>( - &mut self, - bra: &token::Token, - ket: &token::Token, - sep: SeqSep, - f: |&mut Parser| -> T) - -> Vec<T> { + pub fn parse_unspanned_seq<T, F>(&mut self, + bra: &token::Token, + ket: &token::Token, + sep: SeqSep, + f: F) + -> Vec<T> where + F: FnMut(&mut Parser) -> T, + { self.expect(bra); let result = self.parse_seq_to_before_end(ket, sep, f); self.bump(); @@ -861,13 +899,14 @@ impl<'a> Parser<'a> { /// Parse a sequence parameter of enum variant. For consistency purposes, /// these should not be empty. - pub fn parse_enum_variant_seq<T>( - &mut self, - bra: &token::Token, - ket: &token::Token, - sep: SeqSep, - f: |&mut Parser| -> T) - -> Vec<T> { + pub fn parse_enum_variant_seq<T, F>(&mut self, + bra: &token::Token, + ket: &token::Token, + sep: SeqSep, + f: F) + -> Vec<T> where + F: FnMut(&mut Parser) -> T, + { let result = self.parse_unspanned_seq(bra, ket, sep, f); if result.is_empty() { let last_span = self.last_span; @@ -879,13 +918,14 @@ impl<'a> Parser<'a> { // NB: Do not use this function unless you actually plan to place the // spanned list in the AST. - pub fn parse_seq<T>( - &mut self, - bra: &token::Token, - ket: &token::Token, - sep: SeqSep, - f: |&mut Parser| -> T) - -> Spanned<Vec<T> > { + pub fn parse_seq<T, F>(&mut self, + bra: &token::Token, + ket: &token::Token, + sep: SeqSep, + f: F) + -> Spanned<Vec<T>> where + F: FnMut(&mut Parser) -> T, + { let lo = self.span.lo; self.expect(bra); let result = self.parse_seq_to_before_end(ket, sep, f); @@ -915,16 +955,17 @@ impl<'a> Parser<'a> { tok: token::Underscore, sp: self.span, }; - replace(&mut self.buffer[buffer_start], placeholder) + mem::replace(&mut self.buffer[buffer_start], placeholder) }; self.span = next.sp; self.token = next.tok; self.tokens_consumed += 1u; + self.expected_tokens.clear(); } /// Advance the parser by one token and return the bumped token. pub fn bump_and_get(&mut self) -> token::Token { - let old_token = replace(&mut self.token, token::Underscore); + let old_token = mem::replace(&mut self.token, token::Underscore); self.bump(); old_token } @@ -944,8 +985,9 @@ impl<'a> Parser<'a> { } return (4 - self.buffer_start) + self.buffer_end; } - pub fn look_ahead<R>(&mut self, distance: uint, f: |&token::Token| -> R) - -> R { + pub fn look_ahead<R, F>(&mut self, distance: uint, f: F) -> R where + F: FnOnce(&token::Token) -> R, + { let dist = distance as int; while self.buffer_length() < dist { self.buffer[self.buffer_end as uint] = self.reader.real_token(); @@ -1021,7 +1063,6 @@ impl<'a> Parser<'a> { Deprecated: - for <'lt> |S| -> T - - for <'lt> proc(S) -> T Eventually: @@ -1038,7 +1079,7 @@ impl<'a> Parser<'a> { self.parse_proc_type(lifetime_defs) } else if self.token_is_bare_fn_keyword() || self.token_is_closure_keyword() { self.parse_ty_bare_fn_or_ty_closure(lifetime_defs) - } else if self.token == token::ModSep || + } else if self.check(&token::ModSep) || self.token.is_ident() || self.token.is_path() { @@ -1060,17 +1101,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: @@ -1087,7 +1120,7 @@ impl<'a> Parser<'a> { Function Style */ - let fn_style = self.parse_unsafety(); + let unsafety = self.parse_unsafety(); let abi = if self.eat_keyword(keywords::Extern) { self.parse_opt_abi().unwrap_or(abi::C) } else { @@ -1105,7 +1138,7 @@ impl<'a> Parser<'a> { }); TyBareFn(P(BareFnTy { abi: abi, - fn_style: fn_style, + unsafety: unsafety, lifetimes: lifetime_defs, decl: decl })) @@ -1123,32 +1156,27 @@ impl<'a> Parser<'a> { | | | Bounds | | Argument types | Legacy lifetimes - the `proc` keyword + the `proc` keyword (already consumed) */ - let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs); - let (inputs, variadic) = self.parse_fn_args(false, false); - let bounds = self.parse_colon_then_ty_param_bounds(); - let ret_ty = self.parse_ret_ty(); - let decl = P(FnDecl { - inputs: inputs, - output: ret_ty, - variadic: variadic - }); - TyProc(P(ClosureTy { - fn_style: NormalFn, - onceness: Once, - bounds: bounds, - decl: decl, - lifetimes: lifetime_defs, - })) + let proc_span = self.last_span; + + // To be helpful, parse the proc as ever + let _ = self.parse_legacy_lifetime_defs(lifetime_defs); + let _ = self.parse_fn_args(false, false); + let _ = self.parse_colon_then_ty_param_bounds(); + let _ = self.parse_ret_ty(); + + self.obsolete(proc_span, ObsoleteProcType); + + TyInfer } /// Parses an optional unboxed closure kind (`&:`, `&mut:`, or `:`). pub fn parse_optional_unboxed_closure_kind(&mut self) -> Option<UnboxedClosureKind> { - if self.token == token::BinOp(token::And) && + if self.check(&token::BinOp(token::And)) && self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) && self.look_ahead(2, |t| *t == token::Colon) { self.bump(); @@ -1211,7 +1239,7 @@ impl<'a> Parser<'a> { */ - let fn_style = self.parse_unsafety(); + let unsafety = self.parse_unsafety(); let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs); @@ -1237,7 +1265,7 @@ impl<'a> Parser<'a> { }); TyClosure(P(ClosureTy { - fn_style: fn_style, + unsafety: unsafety, onceness: Many, bounds: bounds, decl: decl, @@ -1245,11 +1273,11 @@ impl<'a> Parser<'a> { })) } - pub fn parse_unsafety(&mut self) -> FnStyle { + pub fn parse_unsafety(&mut self) -> Unsafety { if self.eat_keyword(keywords::Unsafe) { - return UnsafeFn; + return Unsafety::Unsafe; } else { - return NormalFn; + return Unsafety::Normal; } } @@ -1258,7 +1286,8 @@ impl<'a> Parser<'a> { lifetime_defs: Vec<ast::LifetimeDef>) -> Vec<ast::LifetimeDef> { - if self.eat(&token::Lt) { + if self.token == token::Lt { + self.bump(); if lifetime_defs.is_empty() { self.warn("deprecated syntax; use the `for` keyword now \ (e.g. change `fn<'a>` to `for<'a> fn`)"); @@ -1293,7 +1322,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 { @@ -1321,13 +1350,14 @@ impl<'a> Parser<'a> { let lo = p.span.lo; let vis = p.parse_visibility(); + let style = p.parse_unsafety(); let abi = if p.eat_keyword(keywords::Extern) { p.parse_opt_abi().unwrap_or(abi::C) } else { abi::Rust }; + p.expect_keyword(keywords::Fn); - let style = p.parse_fn_style(); let ident = p.parse_ident(); let mut generics = p.parse_generics(); @@ -1348,7 +1378,7 @@ impl<'a> Parser<'a> { RequiredMethod(TypeMethod { ident: ident, attrs: attrs, - fn_style: style, + unsafety: style, decl: d, generics: generics, abi: abi, @@ -1363,7 +1393,7 @@ impl<'a> Parser<'a> { let (inner_attrs, body) = p.parse_inner_attrs_and_block(); let mut attrs = attrs; - attrs.push_all(inner_attrs.as_slice()); + attrs.push_all(inner_attrs[]); ProvidedMethod(P(ast::Method { attrs: attrs, id: ast::DUMMY_NODE_ID, @@ -1382,7 +1412,7 @@ impl<'a> Parser<'a> { _ => { let token_str = p.this_token_to_string(); p.fatal((format!("expected `;` or `{{`, found `{}`", - token_str)).as_slice()) + token_str))[]) } } } @@ -1392,7 +1422,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 } } @@ -1403,7 +1433,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, @@ -1418,7 +1448,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 438 for details"); + } + + Return(t) } } else { let pos = self.span.lo; @@ -1430,16 +1472,38 @@ 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; - let t = if self.token == token::OpenDelim(token::Paren) { + let t = if self.check(&token::OpenDelim(token::Paren)) { self.bump(); // (t) is a parenthesized ty @@ -1448,8 +1512,8 @@ 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)); - if self.token == token::Comma { + ts.push(self.parse_ty_sum()); + if self.check(&token::Comma) { last_comma = true; self.bump(); } else { @@ -1472,25 +1536,25 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Bracket) => self.obsolete(last_span, ObsoleteOwnedVector), _ => self.obsolete(last_span, ObsoleteOwnedType) } - TyTup(vec![self.parse_ty(false)]) - } else if self.token == token::BinOp(token::Star) { + TyTup(vec![self.parse_ty()]) + } else if self.check(&token::BinOp(token::Star)) { // STAR POINTER (bare pointer?) self.bump(); TyPtr(self.parse_ptr()) - } else if self.token == token::OpenDelim(token::Bracket) { + } else if self.check(&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 ]` + // Parse the `; e` in `[ int; e ]` // where `e` is a const expression - let t = match self.maybe_parse_fixed_vstore() { + let t = match self.maybe_parse_fixed_length_of_vec() { None => TyVec(t), Some(suffix) => TyFixedLengthVec(t, suffix) }; self.expect(&token::CloseDelim(token::Bracket)); t - } else if self.token == token::BinOp(token::And) || + } else if self.check(&token::BinOp(token::And)) || self.token == token::AndAnd { // BORROWED POINTER self.expect_and(); @@ -1501,7 +1565,7 @@ impl<'a> Parser<'a> { self.token_is_closure_keyword() { // BARE FUNCTION OR CLOSURE self.parse_ty_bare_fn_or_ty_closure(Vec::new()) - } else if self.token == token::BinOp(token::Or) || + } else if self.check(&token::BinOp(token::Or)) || self.token == token::OrOr || (self.token == token::Lt && self.look_ahead(1, |t| { @@ -1518,10 +1582,10 @@ impl<'a> Parser<'a> { TyTypeof(e) } else if self.eat_keyword(keywords::Proc) { self.parse_proc_type(Vec::new()) - } else if self.token == token::Lt { + } else if self.check(&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); @@ -1532,17 +1596,18 @@ impl<'a> Parser<'a> { trait_ref: P(trait_ref), item_name: item_name, })) - } else if self.token == token::ModSep || + } else if self.check(&token::ModSep) || 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 } else { - let msg = format!("expected type, found token {}", self.token); - self.fatal(msg.as_slice()); + let this_token_str = self.this_token_to_string(); + let msg = format!("expected type, found `{}`", this_token_str); + self.fatal(msg[]); }; let sp = mk_sp(lo, self.last_span.hi); @@ -1570,7 +1635,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 } } @@ -1610,7 +1675,7 @@ impl<'a> Parser<'a> { special_idents::invalid) }; - let t = self.parse_ty(true); + let t = self.parse_ty_sum(); Arg { ty: t, @@ -1628,7 +1693,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, @@ -1643,11 +1708,14 @@ impl<'a> Parser<'a> { } } - pub fn maybe_parse_fixed_vstore(&mut self) -> Option<P<ast::Expr>> { - if self.token == token::Comma && + pub fn maybe_parse_fixed_length_of_vec(&mut self) -> Option<P<ast::Expr>> { + if self.check(&token::Comma) && self.look_ahead(1, |t| *t == token::DotDot) { self.bump(); self.bump(); + Some(self.parse_expr_res(RESTRICTION_NO_DOTS)) + } else if self.check(&token::Semi) { + self.bump(); Some(self.parse_expr()) } else { None @@ -1657,10 +1725,16 @@ impl<'a> Parser<'a> { /// Matches token_lit = LIT_INTEGER | ... pub fn lit_from_token(&mut self, tok: &token::Token) -> Lit_ { match *tok { + token::Interpolated(token::NtExpr(ref v)) => { + match v.node { + ExprLit(ref lit) => { lit.node.clone() } + _ => { self.unexpected_last(tok); } + } + } token::Literal(lit, suf) => { let (suffix_illegal, out) = match lit { - token::Byte(i) => (true, LitByte(parse::byte_lit(i.as_str()).val0())), - token::Char(i) => (true, LitChar(parse::char_lit(i.as_str()).val0())), + token::Byte(i) => (true, LitByte(parse::byte_lit(i.as_str()).0)), + token::Char(i) => (true, LitChar(parse::char_lit(i.as_str()).0)), // there are some valid suffixes for integer and // float literals, so all the handling is done @@ -1680,14 +1754,14 @@ impl<'a> Parser<'a> { token::Str_(s) => { (true, - LitStr(token::intern_and_get_ident(parse::str_lit(s.as_str()).as_slice()), + LitStr(token::intern_and_get_ident(parse::str_lit(s.as_str())[]), ast::CookedStr)) } token::StrRaw(s, n) => { (true, LitStr( token::intern_and_get_ident( - parse::raw_str_lit(s.as_str()).as_slice()), + parse::raw_str_lit(s.as_str())[]), ast::RawStr(n))) } token::Binary(i) => @@ -1746,20 +1820,14 @@ 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()), _ => None, }; - match found { - Some(token::Interpolated(token::NtPath(box path))) => { - return PathAndBounds { - path: path, - bounds: None - } - } - _ => {} + if let Some(token::Interpolated(token::NtPath(box path))) = found { + return path; } let lo = self.span.lo; @@ -1769,8 +1837,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 => { @@ -1781,44 +1848,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, } } @@ -1834,20 +1871,21 @@ impl<'a> Parser<'a> { // Parse types, optionally. let parameters = if self.eat_lt(false) { - let (lifetimes, types) = self.parse_generic_values_after_lt(); + let (lifetimes, types, bindings) = self.parse_generic_values_after_lt(); ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: OwnedSlice::from_vec(types), + bindings: OwnedSlice::from_vec(bindings), }) } 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)); + |p| p.parse_ty_sum()); let output_ty = if self.eat(&token::RArrow) { - Some(self.parse_ty(true)) + Some(self.parse_ty()) } else { None }; @@ -1886,6 +1924,7 @@ impl<'a> Parser<'a> { parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: Vec::new(), types: OwnedSlice::empty(), + bindings: OwnedSlice::empty(), }) }); return segments; @@ -1894,12 +1933,13 @@ impl<'a> Parser<'a> { // 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(); + let (lifetimes, types, bindings) = self.parse_generic_values_after_lt(); segments.push(ast::PathSegment { identifier: identifier, parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData { lifetimes: lifetimes, types: OwnedSlice::from_vec(types), + bindings: OwnedSlice::from_vec(bindings), }), }); @@ -1965,16 +2005,14 @@ impl<'a> Parser<'a> { }; } _ => { - self.fatal(format!("expected a lifetime name").as_slice()); + self.fatal(format!("expected a lifetime name")[]); } } } + /// 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 { @@ -2001,25 +2039,23 @@ impl<'a> Parser<'a> { token::Gt => { return res; } token::BinOp(token::Shr) => { return res; } _ => { + let this_token_str = self.this_token_to_string(); let msg = format!("expected `,` or `>` after lifetime \ - name, got: {}", - self.token); - self.fatal(msg.as_slice()); + name, found `{}`", + this_token_str); + self.fatal(msg[]); } } } } - // 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 { @@ -2095,7 +2131,8 @@ impl<'a> Parser<'a> { ExprIndex(expr, idx) } - pub fn mk_slice(&mut self, expr: P<Expr>, + pub fn mk_slice(&mut self, + expr: P<Expr>, start: Option<P<Expr>>, end: Option<P<Expr>>, mutbl: Mutability) @@ -2103,14 +2140,19 @@ impl<'a> Parser<'a> { ExprSlice(expr, start, end, mutbl) } - pub fn mk_field(&mut self, expr: P<Expr>, ident: ast::SpannedIdent, - tys: Vec<P<Ty>>) -> ast::Expr_ { - ExprField(expr, ident, tys) + pub fn mk_range(&mut self, + start: P<Expr>, + end: Option<P<Expr>>) + -> ast::Expr_ { + ExprRange(start, end) } - pub fn mk_tup_field(&mut self, expr: P<Expr>, idx: codemap::Spanned<uint>, - tys: Vec<P<Ty>>) -> ast::Expr_ { - ExprTupField(expr, idx, tys) + pub fn mk_field(&mut self, expr: P<Expr>, ident: ast::SpannedIdent) -> ast::Expr_ { + ExprField(expr, ident) + } + + pub fn mk_tup_field(&mut self, expr: P<Expr>, idx: codemap::Spanned<uint>) -> ast::Expr_ { + ExprTupField(expr, idx) } pub fn mk_assign_op(&mut self, binop: ast::BinOp, @@ -2173,7 +2215,7 @@ impl<'a> Parser<'a> { es.push(self.parse_expr()); self.commit_expr(&**es.last().unwrap(), &[], &[token::Comma, token::CloseDelim(token::Paren)]); - if self.token == token::Comma { + if self.check(&token::Comma) { trailing_comma = true; self.bump(); @@ -2214,14 +2256,14 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Bracket) => { self.bump(); - if self.token == token::CloseDelim(token::Bracket) { + if self.check(&token::CloseDelim(token::Bracket)) { // Empty vector. self.bump(); ex = ExprVec(Vec::new()); } else { // Nonempty vector. let first_expr = self.parse_expr(); - if self.token == token::Comma && + if self.check(&token::Comma) && self.look_ahead(1, |t| *t == token::DotDot) { // Repeating vector syntax: [ 0, ..512 ] self.bump(); @@ -2229,7 +2271,13 @@ impl<'a> Parser<'a> { let count = self.parse_expr(); self.expect(&token::CloseDelim(token::Bracket)); ex = ExprRepeat(first_expr, count); - } else if self.token == token::Comma { + } else if self.check(&token::Semi) { + // Repeating vector syntax: [ 0; 512 ] + self.bump(); + let count = self.parse_expr(); + self.expect(&token::CloseDelim(token::Bracket)); + ex = ExprRepeat(first_expr, count); + } else if self.check(&token::Comma) { // Vector with two or more elements. self.bump(); let remaining_exprs = self.parse_seq_to_end( @@ -2253,17 +2301,10 @@ impl<'a> Parser<'a> { return self.parse_lambda_expr(CaptureByValue); } if self.eat_keyword(keywords::Proc) { - let decl = self.parse_proc_decl(); - let body = self.parse_expr(); - let fakeblock = P(ast::Block { - id: ast::DUMMY_NODE_ID, - view_items: Vec::new(), - stmts: Vec::new(), - rules: DefaultBlock, - span: body.span, - expr: Some(body), - }); - return self.mk_expr(lo, fakeblock.span.hi, ExprProc(decl, fakeblock)); + let span = self.last_span; + let _ = self.parse_proc_decl(); + let _ = self.parse_expr(); + return self.obsolete_expr(span, ObsoleteProcExpr); } if self.eat_keyword(keywords::If) { return self.parse_if_expr(); @@ -2331,15 +2372,15 @@ impl<'a> Parser<'a> { ex = ExprBreak(None); } hi = self.span.hi; - } else if self.token == token::ModSep || + } else if self.check(&token::ModSep) || self.token.is_ident() && !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 { + if self.check(&token::Not) { // MACRO INVOCATION expression self.bump(); @@ -2356,7 +2397,7 @@ impl<'a> Parser<'a> { tts, EMPTY_CTXT)); } - if self.token == token::OpenDelim(token::Brace) { + if self.check(&token::OpenDelim(token::Brace)) { // This is a struct literal, unless we're prohibited // from parsing struct literals here. if !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL) { @@ -2433,13 +2474,18 @@ impl<'a> Parser<'a> { let dot = self.last_span.hi; hi = self.span.hi; self.bump(); - let (_, tys) = if self.eat(&token::ModSep) { + let (_, tys, bindings) = if self.eat(&token::ModSep) { self.expect_lt(); self.parse_generic_values_after_lt() } else { - (Vec::new(), Vec::new()) + (Vec::new(), Vec::new(), Vec::new()) }; + if bindings.len() > 0 { + let last_span = self.last_span; + self.span_err(last_span, "type bindings are only permitted on trait paths"); + } + // expr.f() method call match self.token { token::OpenDelim(token::Paren) => { @@ -2465,31 +2511,26 @@ impl<'a> Parser<'a> { } let id = spanned(dot, hi, i); - let field = self.mk_field(e, id, tys); + let field = self.mk_field(e, id); e = self.mk_expr(lo, hi, field); } } } token::Literal(token::Integer(n), suf) => { let sp = self.span; + + // A tuple index may not have a suffix self.expect_no_suffix(sp, "tuple index", suf); - let index = n.as_str(); let dot = self.last_span.hi; hi = self.span.hi; self.bump(); - let (_, tys) = if self.eat(&token::ModSep) { - self.expect_lt(); - self.parse_generic_values_after_lt() - } else { - (Vec::new(), Vec::new()) - }; - let num = from_str::<uint>(index); - match num { + let index = n.as_str().parse::<uint>(); + match index { Some(n) => { let id = spanned(dot, hi, n); - let field = self.mk_tup_field(e, id, tys); + let field = self.mk_tup_field(e, id); e = self.mk_expr(lo, hi, field); } None => { @@ -2503,16 +2544,16 @@ impl<'a> Parser<'a> { let last_span = self.last_span; let fstr = n.as_str(); self.span_err(last_span, - format!("unexpected token: `{}`", n.as_str()).as_slice()); + format!("unexpected token: `{}`", n.as_str())[]); if fstr.chars().all(|x| "0123456789.".contains_char(x)) { - let float = match from_str::<f64>(fstr) { + let float = match fstr.parse::<f64>() { Some(f) => f, None => continue, }; self.span_help(last_span, format!("try parenthesizing the first index; e.g., `(foo.{}){}`", float.trunc() as uint, - float.fract().to_string()[1..]).as_slice()); + float.fract().to_string()[1..])[]); } self.abort_if_errors(); @@ -2583,7 +2624,7 @@ impl<'a> Parser<'a> { } // e[e] | e[e..] | e[e..e] _ => { - let ix = self.parse_expr(); + let ix = self.parse_expr_res(RESTRICTION_NO_DOTS); match self.token { // e[e..] | e[e..e] token::DotDot => { @@ -2596,7 +2637,7 @@ impl<'a> Parser<'a> { } // e[e..e] _ => { - let e2 = self.parse_expr(); + let e2 = self.parse_expr_res(RESTRICTION_NO_DOTS); self.commit_expr_expecting(&*e2, token::CloseDelim(token::Bracket)); Some(e2) @@ -2622,6 +2663,21 @@ impl<'a> Parser<'a> { } } + // A range expression, either `expr..expr` or `expr..`. + token::DotDot if !self.restrictions.contains(RESTRICTION_NO_DOTS) => { + self.bump(); + + let opt_end = if self.token.can_begin_expr() { + let end = self.parse_expr_res(RESTRICTION_NO_DOTS); + Some(end) + } else { + None + }; + + let hi = self.span.hi; + let range = self.mk_range(e, opt_end); + return self.mk_expr(lo, hi, range); + } _ => return e } } @@ -2684,7 +2740,7 @@ impl<'a> Parser<'a> { }; let token_str = p.this_token_to_string(); p.fatal(format!("incorrect close delimiter: `{}`", - token_str).as_slice()) + token_str)[]) }, /* we ought to allow different depths of unquotation */ token::Dollar if p.quote_depth > 0u => { @@ -2702,7 +2758,7 @@ impl<'a> Parser<'a> { let seq = match seq { Spanned { node, .. } => node, }; - let name_num = macro_parser::count_names(seq.as_slice()); + let name_num = macro_parser::count_names(seq[]); TtSequence(mk_sp(sp.lo, p.span.hi), Rc::new(SequenceRepetition { tts: seq, @@ -2853,7 +2909,7 @@ impl<'a> Parser<'a> { let this_token_to_string = self.this_token_to_string(); self.span_err(span, format!("expected expression, found `{}`", - this_token_to_string).as_slice()); + this_token_to_string)[]); let box_span = mk_sp(lo, self.last_span.hi); self.span_help(box_span, "perhaps you meant `box() (foo)` instead?"); @@ -2861,7 +2917,7 @@ impl<'a> Parser<'a> { } let subexpression = self.parse_prefix_expr(); hi = subexpression.span.hi; - ex = ExprBox(place, subexpression); + ex = ExprBox(Some(place), subexpression); return self.mk_expr(lo, hi, ex); } } @@ -2869,6 +2925,9 @@ impl<'a> Parser<'a> { // Otherwise, we use the unique pointer default. let subexpression = self.parse_prefix_expr(); hi = subexpression.span.hi; + // FIXME (pnkfelix): After working out kinks with box + // desugaring, should be `ExprBox(None, subexpression)` + // instead. ex = self.mk_unary(UnUniq, subexpression); } _ => return self.parse_dot_or_call_expr() @@ -2892,6 +2951,7 @@ impl<'a> Parser<'a> { self.restrictions.contains(RESTRICTION_NO_BAR_OP) { return lhs; } + self.expected_tokens.push(TokenType::Operator); let cur_opt = self.token.to_binop(); match cur_opt { @@ -2912,7 +2972,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)); @@ -3084,7 +3144,7 @@ impl<'a> Parser<'a> { } let hi = self.span.hi; self.bump(); - return self.mk_expr(lo, hi, ExprMatch(discriminant, arms, MatchNormal)); + return self.mk_expr(lo, hi, ExprMatch(discriminant, arms, MatchSource::Normal)); } pub fn parse_arm(&mut self) -> Arm { @@ -3131,7 +3191,7 @@ impl<'a> Parser<'a> { /// Parse the RHS of a local variable declaration (e.g. '= 14;') fn parse_initializer(&mut self) -> Option<P<Expr>> { - if self.token == token::Eq { + if self.check(&token::Eq) { self.bump(); Some(self.parse_expr()) } else { @@ -3144,7 +3204,7 @@ impl<'a> Parser<'a> { let mut pats = Vec::new(); loop { pats.push(self.parse_pat()); - if self.token == token::BinOp(token::Or) { self.bump(); } + if self.check(&token::BinOp(token::Or)) { self.bump(); } else { return pats; } }; } @@ -3163,14 +3223,19 @@ impl<'a> Parser<'a> { first = false; } else { self.expect(&token::Comma); + + if self.token == token::CloseDelim(token::Bracket) + && (before_slice || after.len() != 0) { + break + } } if before_slice { - if self.token == token::DotDot { + if self.check(&token::DotDot) { self.bump(); - if self.token == token::Comma || - self.token == token::CloseDelim(token::Bracket) { + if self.check(&token::Comma) || + self.check(&token::CloseDelim(token::Bracket)) { slice = Some(P(ast::Pat { id: ast::DUMMY_NODE_ID, node: PatWild(PatWildMulti), @@ -3187,7 +3252,7 @@ impl<'a> Parser<'a> { } let subpat = self.parse_pat(); - if before_slice && self.token == token::DotDot { + if before_slice && self.check(&token::DotDot) { self.bump(); slice = Some(subpat); before_slice = false; @@ -3212,18 +3277,18 @@ impl<'a> Parser<'a> { } else { self.expect(&token::Comma); // accept trailing commas - if self.token == token::CloseDelim(token::Brace) { break } + if self.check(&token::CloseDelim(token::Brace)) { break } } let lo = self.span.lo; let hi; - if self.token == token::DotDot { + if self.check(&token::DotDot) { self.bump(); if self.token != token::CloseDelim(token::Brace) { let token_str = self.this_token_to_string(); self.fatal(format!("expected `{}`, found `{}`", "}", - token_str).as_slice()) + token_str)[]) } etc = true; break; @@ -3239,12 +3304,12 @@ impl<'a> Parser<'a> { let fieldname = self.parse_ident(); - let (subpat, is_shorthand) = if self.token == token::Colon { + let (subpat, is_shorthand) = if self.check(&token::Colon) { match bind_type { BindByRef(..) | BindByValue(MutMutable) => { let token_str = self.this_token_to_string(); self.fatal(format!("unexpected `{}`", - token_str).as_slice()) + token_str)[]) } _ => {} } @@ -3319,15 +3384,15 @@ impl<'a> Parser<'a> { token::OpenDelim(token::Paren) => { // parse (pat,pat,pat,...) as tuple self.bump(); - if self.token == token::CloseDelim(token::Paren) { + if self.check(&token::CloseDelim(token::Paren)) { self.bump(); pat = PatTup(vec![]); } else { let mut fields = vec!(self.parse_pat()); if self.look_ahead(1, |t| *t != token::CloseDelim(token::Paren)) { - while self.token == token::Comma { + while self.check(&token::Comma) { self.bump(); - if self.token == token::CloseDelim(token::Paren) { break; } + if self.check(&token::CloseDelim(token::Paren)) { break; } fields.push(self.parse_pat()); } } @@ -3370,14 +3435,13 @@ impl<'a> Parser<'a> { // These expressions are limited to literals (possibly // preceded by unary-minus) or identifiers. let val = self.parse_literal_maybe_minus(); - if (self.token == token::DotDotDot) && + if (self.check(&token::DotDotDot)) && self.look_ahead(1, |t| { *t != token::Comma && *t != token::CloseDelim(token::Bracket) }) { 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 { @@ -3447,8 +3511,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(); @@ -3524,7 +3587,7 @@ impl<'a> Parser<'a> { let span = self.span; let tok_str = self.this_token_to_string(); self.span_fatal(span, - format!("expected identifier, found `{}`", tok_str).as_slice()); + format!("expected identifier, found `{}`", tok_str)[]); } let ident = self.parse_ident(); let last_span = self.last_span; @@ -3562,7 +3625,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 { @@ -3591,7 +3654,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, @@ -3625,7 +3688,7 @@ impl<'a> Parser<'a> { let lo = self.span.lo; if self.token.is_keyword(keywords::Let) { - check_expected_item(self, item_attrs.as_slice()); + check_expected_item(self, item_attrs[]); self.expect_keyword(keywords::Let); let decl = self.parse_let(); P(spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID))) @@ -3634,11 +3697,11 @@ impl<'a> Parser<'a> { && self.look_ahead(1, |t| *t == token::Not) { // it's a macro invocation: - check_expected_item(self, item_attrs.as_slice()); + check_expected_item(self, item_attrs[]); // 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 { @@ -3662,7 +3725,7 @@ impl<'a> Parser<'a> { let tok_str = self.this_token_to_string(); self.fatal(format!("expected {}`(` or `{{`, found `{}`", ident_str, - tok_str).as_slice()) + tok_str)[]) }, }; @@ -3674,21 +3737,32 @@ impl<'a> Parser<'a> { ); let hi = self.span.hi; + let style = if delim == token::Brace { + MacStmtWithBraces + } else { + MacStmtWithoutBraces + }; + if id.name == token::special_idents::invalid.name { - if self.token == token::Dot { - let span = self.span; - let token_string = self.this_token_to_string(); - self.span_err(span, - format!("expected statement, found `{}`", - token_string).as_slice()); - let mac_span = mk_sp(lo, hi); - self.span_help(mac_span, "try parenthesizing this macro invocation"); - self.abort_if_errors(); - } - P(spanned(lo, hi, StmtMac( - spanned(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT)), false))) + P(spanned(lo, + hi, + StmtMac(spanned(lo, + hi, + MacInvocTT(pth, tts, EMPTY_CTXT)), + style))) } else { // if it has a special ident, it's definitely an item + // + // Require a semicolon or braces. + if style != MacStmtWithBraces { + if !self.eat(&token::Semi) { + let last_span = self.last_span; + self.span_err(last_span, + "macros that expand to items must \ + either be surrounded with braces or \ + followed by a semicolon"); + } + } P(spanned(lo, hi, StmtDecl( P(spanned(lo, hi, DeclItem( self.mk_item( @@ -3697,10 +3771,9 @@ impl<'a> Parser<'a> { Inherited, Vec::new(/*no attrs*/))))), ast::DUMMY_NODE_ID))) } - } else { let found_attrs = !item_attrs.is_empty(); - let item_err = Parser::expected_item_err(item_attrs.as_slice()); + let item_err = Parser::expected_item_err(item_attrs[]); match self.parse_item_or_view_item(item_attrs, false) { IoviItem(i) => { let hi = i.span.hi; @@ -3744,7 +3817,7 @@ impl<'a> Parser<'a> { let sp = self.span; let tok = self.this_token_to_string(); self.span_fatal_help(sp, - format!("expected `{{`, found `{}`", tok).as_slice(), + format!("expected `{{`, found `{}`", tok)[], "place this code inside a block"); } @@ -3798,13 +3871,13 @@ impl<'a> Parser<'a> { while self.token != token::CloseDelim(token::Brace) { // parsing items even when they're not allowed lets us give // better error messages and recover more gracefully. - attributes_box.push_all(self.parse_outer_attributes().as_slice()); + attributes_box.push_all(self.parse_outer_attributes()[]); match self.token { token::Semi => { if !attributes_box.is_empty() { let last_span = self.last_span; self.span_err(last_span, - Parser::expected_item_err(attributes_box.as_slice())); + Parser::expected_item_err(attributes_box[])); attributes_box = Vec::new(); } self.bump(); // empty @@ -3817,43 +3890,46 @@ impl<'a> Parser<'a> { attributes_box = Vec::new(); stmt.and_then(|Spanned {node, span}| match node { StmtExpr(e, stmt_id) => { - // expression without semicolon - if classify::expr_requires_semi_to_be_stmt(&*e) { - // Just check for errors and recover; do not eat semicolon yet. - self.commit_stmt(&[], &[token::Semi, - token::CloseDelim(token::Brace)]); - } - + self.handle_expression_like_statement(e, + stmt_id, + span, + &mut stmts, + &mut expr); + } + StmtMac(macro, MacStmtWithoutBraces) => { + // statement macro without braces; might be an + // expr depending on whether a semicolon follows match self.token { token::Semi => { - self.bump(); - let span_with_semi = Span { - lo: span.lo, - hi: self.last_span.hi, - expn_id: span.expn_id, - }; stmts.push(P(Spanned { - node: StmtSemi(e, stmt_id), - span: span_with_semi, + node: StmtMac(macro, + MacStmtWithSemicolon), + span: span, })); - } - token::CloseDelim(token::Brace) => { - expr = Some(e); + self.bump(); } _ => { - stmts.push(P(Spanned { - node: StmtExpr(e, stmt_id), - span: span - })); + let e = self.mk_mac_expr(span.lo, + span.hi, + macro.node); + let e = + self.parse_dot_or_call_expr_with(e); + self.handle_expression_like_statement( + e, + ast::DUMMY_NODE_ID, + span, + &mut stmts, + &mut expr); } } } - StmtMac(m, semi) => { + StmtMac(m, style) => { // statement macro; might be an expr match self.token { token::Semi => { stmts.push(P(Spanned { - node: StmtMac(m, true), + node: StmtMac(m, + MacStmtWithSemicolon), span: span, })); self.bump(); @@ -3868,7 +3944,7 @@ impl<'a> Parser<'a> { } _ => { stmts.push(P(Spanned { - node: StmtMac(m, semi), + node: StmtMac(m, style), span: span })); } @@ -3892,7 +3968,7 @@ impl<'a> Parser<'a> { if !attributes_box.is_empty() { let last_span = self.last_span; self.span_err(last_span, - Parser::expected_item_err(attributes_box.as_slice())); + Parser::expected_item_err(attributes_box[])); } let hi = self.span.hi; @@ -3907,6 +3983,43 @@ impl<'a> Parser<'a> { }) } + fn handle_expression_like_statement( + &mut self, + e: P<Expr>, + stmt_id: NodeId, + span: Span, + stmts: &mut Vec<P<Stmt>>, + last_block_expr: &mut Option<P<Expr>>) { + // expression without semicolon + if classify::expr_requires_semi_to_be_stmt(&*e) { + // Just check for errors and recover; do not eat semicolon yet. + self.commit_stmt(&[], + &[token::Semi, token::CloseDelim(token::Brace)]); + } + + match self.token { + token::Semi => { + self.bump(); + let span_with_semi = Span { + lo: span.lo, + hi: self.last_span.hi, + expn_id: span.expn_id, + }; + stmts.push(P(Spanned { + node: StmtSemi(e, stmt_id), + span: span_with_semi, + })); + } + token::CloseDelim(token::Brace) => *last_block_expr = Some(e), + _ => { + stmts.push(P(Spanned { + node: StmtExpr(e, stmt_id), + span: span + })); + } + } + } + // Parses a sequence of bounds if a `:` is found, // otherwise returns empty list. fn parse_colon_then_ty_param_bounds(&mut self) @@ -3988,9 +4101,9 @@ impl<'a> Parser<'a> { let bounds = self.parse_colon_then_ty_param_bounds(); - let default = if self.token == token::Eq { + let default = if self.check(&token::Eq) { self.bump(); - Some(self.parse_ty(true)) + Some(self.parse_ty_sum()) } else { None }; @@ -4040,16 +4153,51 @@ impl<'a> Parser<'a> { } } - fn parse_generic_values_after_lt(&mut self) -> (Vec<ast::Lifetime>, Vec<P<Ty>> ) { + fn parse_generic_values_after_lt(&mut self) + -> (Vec<ast::Lifetime>, Vec<P<Ty>>, Vec<P<TypeBinding>>) { let lifetimes = self.parse_lifetimes(token::Comma); - let result = self.parse_seq_to_gt( + + // First parse types. + let (types, returned) = self.parse_seq_to_gt_or_return( Some(token::Comma), |p| { p.forbid_lifetime(); - p.parse_ty(true) + if p.look_ahead(1, |t| t == &token::Eq) { + None + } else { + Some(p.parse_ty_sum()) + } } ); - (lifetimes, result.into_vec()) + + // If we found the `>`, don't continue. + if !returned { + return (lifetimes, types.into_vec(), Vec::new()); + } + + // Then parse type bindings. + let bindings = self.parse_seq_to_gt( + Some(token::Comma), + |p| { + p.forbid_lifetime(); + let lo = p.span.lo; + let ident = p.parse_ident(); + let found_eq = p.eat(&token::Eq); + if !found_eq { + let span = p.span; + p.span_warn(span, "whoops, no =?"); + } + let ty = p.parse_ty(); + let hi = p.span.hi; + let span = mk_sp(lo, hi); + return P(TypeBinding{id: ast::DUMMY_NODE_ID, + ident: ident, + ty: ty, + span: span, + }); + } + ); + (lifetimes, types.into_vec(), bindings.into_vec()) } fn forbid_lifetime(&mut self) { @@ -4061,6 +4209,10 @@ impl<'a> Parser<'a> { } /// Parses an optional `where` clause and places it in `generics`. + /// + /// ``` + /// where T : Trait<U, V> + 'b, 'a : 'b + /// ``` fn parse_where_clause(&mut self, generics: &mut ast::Generics) { if !self.eat_keyword(keywords::Where) { return @@ -4069,29 +4221,79 @@ impl<'a> Parser<'a> { let mut parsed_something = false; loop { let lo = self.span.lo; - let ident = match self.token { - token::Ident(..) => self.parse_ident(), - _ => break, - }; - self.expect(&token::Colon); + match self.token { + token::OpenDelim(token::Brace) => { + break + } - let bounds = self.parse_ty_param_bounds(); - let hi = self.span.hi; - let span = mk_sp(lo, hi); + token::Lifetime(..) => { + let bounded_lifetime = + self.parse_lifetime(); - if bounds.len() == 0 { - self.span_err(span, - "each predicate in a `where` clause must have \ - at least one bound in it"); - } + self.eat(&token::Colon); - generics.where_clause.predicates.push(ast::WherePredicate { - id: ast::DUMMY_NODE_ID, - span: span, - ident: ident, - bounds: bounds, - }); - parsed_something = true; + let bounds = + self.parse_lifetimes(token::BinOp(token::Plus)); + + let hi = self.span.hi; + let span = mk_sp(lo, hi); + + generics.where_clause.predicates.push(ast::WherePredicate::RegionPredicate( + ast::WhereRegionPredicate { + span: span, + lifetime: bounded_lifetime, + bounds: bounds + } + )); + + parsed_something = true; + } + + _ => { + let bounded_ty = self.parse_ty(); + + if self.eat(&token::Colon) { + let bounds = self.parse_ty_param_bounds(); + let hi = self.span.hi; + let span = mk_sp(lo, hi); + + if bounds.len() == 0 { + self.span_err(span, + "each predicate in a `where` clause must have \ + at least one bound in it"); + } + + generics.where_clause.predicates.push(ast::WherePredicate::BoundPredicate( + ast::WhereBoundPredicate { + span: span, + bounded_ty: bounded_ty, + bounds: bounds, + })); + + parsed_something = true; + } else if self.eat(&token::Eq) { + // let ty = self.parse_ty(); + let hi = self.span.hi; + let span = mk_sp(lo, hi); + // generics.where_clause.predicates.push( + // ast::WherePredicate::EqPredicate(ast::WhereEqPredicate { + // id: ast::DUMMY_NODE_ID, + // span: span, + // path: panic!("NYI"), //bounded_ty, + // ty: ty, + // })); + // parsed_something = true; + // // FIXME(#18433) + self.span_err(span, + "equality constraints are not yet supported \ + in where clauses (#20041)"); + } else { + let last_span = self.last_span; + self.span_err(last_span, + "unexpected token in `where` clause"); + } + } + }; if !self.eat(&token::Comma) { break @@ -4184,15 +4386,16 @@ impl<'a> Parser<'a> { _ => { let token_str = self.this_token_to_string(); self.fatal(format!("expected `self`, found `{}`", - token_str).as_slice()) + token_str)[]) } } } /// Parse the argument list and result type of a function /// that may have a self type. - fn parse_fn_decl_with_self(&mut self, parse_arg_fn: |&mut Parser| -> Arg) - -> (ExplicitSelf, P<FnDecl>) { + fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> (ExplicitSelf, P<FnDecl>) where + F: FnMut(&mut Parser) -> Arg, + { fn maybe_parse_borrowed_explicit_self(this: &mut Parser) -> ast::ExplicitSelf_ { // The following things are possible to see here: @@ -4279,7 +4482,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) } @@ -4291,7 +4494,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) } @@ -4337,7 +4540,7 @@ impl<'a> Parser<'a> { _ => { let token_str = self.this_token_to_string(); self.fatal(format!("expected `,` or `)`, found `{}`", - token_str).as_slice()) + token_str)[]) } } } @@ -4388,7 +4591,7 @@ impl<'a> Parser<'a> { (optional_unboxed_closure_kind, args) } }; - let output = if self.token == token::RArrow { + let output = if self.check(&token::RArrow) { self.parse_ret_ty() } else { Return(P(Ty { @@ -4413,7 +4616,7 @@ impl<'a> Parser<'a> { seq_sep_trailing_allowed(token::Comma), |p| p.parse_fn_block_arg()); - let output = if self.token == token::RArrow { + let output = if self.check(&token::RArrow) { self.parse_ret_ty() } else { Return(P(Ty { @@ -4451,12 +4654,12 @@ impl<'a> Parser<'a> { } /// Parse an item-position function declaration. - fn parse_item_fn(&mut self, fn_style: FnStyle, abi: abi::Abi) -> ItemInfo { + fn parse_item_fn(&mut self, unsafety: Unsafety, abi: abi::Abi) -> ItemInfo { let (ident, mut generics) = self.parse_fn_header(); let decl = self.parse_fn_decl(false); self.parse_where_clause(&mut generics); let (inner_attrs, body) = self.parse_inner_attrs_and_block(); - (ident, ItemFn(decl, fn_style, abi, generics, body), Some(inner_attrs)) + (ident, ItemFn(decl, unsafety, abi, generics, body), Some(inner_attrs)) } /// Parse a method in a trait impl @@ -4480,7 +4683,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: @@ -4492,14 +4695,18 @@ impl<'a> Parser<'a> { let m: ast::Mac = codemap::Spanned { node: m_, span: mk_sp(self.span.lo, self.span.hi) }; + if delim != token::Brace { + self.expect(&token::Semi) + } (ast::MethMac(m), self.span.hi, attrs) } else { + let unsafety = self.parse_unsafety(); let abi = if self.eat_keyword(keywords::Extern) { self.parse_opt_abi().unwrap_or(abi::C) } else { abi::Rust }; - let fn_style = self.parse_fn_style(); + self.expect_keyword(keywords::Fn); let ident = self.parse_ident(); let mut generics = self.parse_generics(); let (explicit_self, decl) = self.parse_fn_decl_with_self(|p| { @@ -4509,12 +4716,12 @@ impl<'a> Parser<'a> { let (inner_attrs, body) = self.parse_inner_attrs_and_block(); let body_span = body.span; let mut new_attrs = attrs; - new_attrs.push_all(inner_attrs.as_slice()); + new_attrs.push_all(inner_attrs[]); (ast::MethDecl(ident, generics, abi, explicit_self, - fn_style, + unsafety, decl, body, visa), @@ -4530,7 +4737,7 @@ impl<'a> Parser<'a> { } /// Parse trait Foo { ... } - fn parse_item_trait(&mut self) -> ItemInfo { + fn parse_item_trait(&mut self, unsafety: Unsafety) -> ItemInfo { let ident = self.parse_ident(); let mut tps = self.parse_generics(); let sized = self.parse_for_sized(); @@ -4541,7 +4748,7 @@ impl<'a> Parser<'a> { self.parse_where_clause(&mut tps); let meths = self.parse_trait_items(); - (ident, ItemTrait(tps, sized, bounds, meths), None) + (ident, ItemTrait(unsafety, tps, sized, bounds, meths), None) } fn parse_impl_items(&mut self) -> (Vec<ImplItem>, Vec<Attribute>) { @@ -4569,7 +4776,7 @@ impl<'a> Parser<'a> { /// Parses two variants (with the region/type params always optional): /// impl<T> Foo { ... } /// impl<T> ToString for ~[T] { ... } - fn parse_item_impl(&mut self) -> ItemInfo { + fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo { // First, parse type parameters if necessary. let mut generics = self.parse_generics(); @@ -4578,30 +4785,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 @@ -4613,14 +4815,14 @@ impl<'a> Parser<'a> { let ident = ast_util::impl_pretty_name(&opt_trait, &*ty); (ident, - ItemImpl(generics, opt_trait, ty, impl_items), + ItemImpl(unsafety, generics, opt_trait, ty, impl_items), Some(attrs)) } /// 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, } } @@ -4652,7 +4854,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"); } @@ -4671,10 +4873,10 @@ impl<'a> Parser<'a> { if fields.len() == 0 { self.fatal(format!("unit-like struct definition should be \ written as `struct {};`", - token::get_ident(class_name)).as_slice()); + token::get_ident(class_name))[]); } self.bump(); - } else if self.token == token::OpenDelim(token::Paren) { + } else if self.check(&token::OpenDelim(token::Paren)) { // It's a tuple-like struct. is_tuple_like = true; fields = self.parse_unspanned_seq( @@ -4687,7 +4889,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_) @@ -4695,7 +4897,7 @@ impl<'a> Parser<'a> { if fields.len() == 0 { self.fatal(format!("unit-like struct definition should be \ written as `struct {};`", - token::get_ident(class_name)).as_slice()); + token::get_ident(class_name))[]); } self.expect(&token::Semi); } else if self.eat(&token::Semi) { @@ -4706,7 +4908,7 @@ impl<'a> Parser<'a> { let token_str = self.this_token_to_string(); self.fatal(format!("expected `{}`, `(`, or `;` after struct \ name, found `{}`", "{", - token_str).as_slice()) + token_str)[]) } let _ = ast::DUMMY_NODE_ID; // FIXME: Workaround for crazy bug. @@ -4735,7 +4937,7 @@ impl<'a> Parser<'a> { let token_str = self.this_token_to_string(); self.span_fatal_help(span, format!("expected `,`, or `}}`, found `{}`", - token_str).as_slice(), + token_str)[], "struct fields should be separated by commas") } } @@ -4805,7 +5007,7 @@ impl<'a> Parser<'a> { let mut attrs = self.parse_outer_attributes(); if first { let mut tmp = attrs_remaining.clone(); - tmp.push_all(attrs.as_slice()); + tmp.push_all(attrs[]); attrs = tmp; first = false; } @@ -4822,7 +5024,7 @@ impl<'a> Parser<'a> { _ => { let token_str = self.this_token_to_string(); self.fatal(format!("expected item, found `{}`", - token_str).as_slice()) + token_str)[]) } } } @@ -4831,7 +5033,7 @@ impl<'a> Parser<'a> { // We parsed attributes for the first item but didn't find it let last_span = self.last_span; self.span_err(last_span, - Parser::expected_item_err(attrs_remaining.as_slice())); + Parser::expected_item_err(attrs_remaining[])); } ast::Mod { @@ -4844,7 +5046,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); @@ -4859,7 +5061,7 @@ impl<'a> Parser<'a> { fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> ItemInfo { let id_span = self.span; let id = self.parse_ident(); - if self.token == token::Semi { + if self.check(&token::Semi) { self.bump(); // This mod is in an external file. Let's go get it! let (m, attrs) = self.eval_src_mod(id, outer_attrs, id_span); @@ -4901,7 +5103,7 @@ impl<'a> Parser<'a> { -> (ast::Item_, Vec<ast::Attribute> ) { let mut prefix = Path::new(self.sess.span_diagnostic.cm.span_to_filename(self.span)); prefix.pop(); - let mod_path = Path::new(".").join_many(self.mod_path_stack.as_slice()); + let mod_path = Path::new(".").join_many(self.mod_path_stack[]); let dir_path = prefix.join(&mod_path); let mod_string = token::get_ident(id); let (file_path, owns_directory) = match ::attr::first_attr_value_str_by_name( @@ -4911,8 +5113,8 @@ impl<'a> Parser<'a> { let mod_name = mod_string.get().to_string(); let default_path_str = format!("{}.rs", mod_name); let secondary_path_str = format!("{}/mod.rs", mod_name); - let default_path = dir_path.join(default_path_str.as_slice()); - let secondary_path = dir_path.join(secondary_path_str.as_slice()); + let default_path = dir_path.join(default_path_str[]); + let secondary_path = dir_path.join(secondary_path_str[]); let default_exists = default_path.exists(); let secondary_exists = secondary_path.exists(); @@ -4927,13 +5129,13 @@ impl<'a> Parser<'a> { format!("maybe move this module `{0}` \ to its own directory via \ `{0}/mod.rs`", - this_module).as_slice()); + this_module)[]); if default_exists || secondary_exists { self.span_note(id_sp, format!("... or maybe `use` the module \ `{}` instead of possibly \ redeclaring it", - mod_name).as_slice()); + mod_name)[]); } self.abort_if_errors(); } @@ -4944,12 +5146,12 @@ impl<'a> Parser<'a> { (false, false) => { self.span_fatal_help(id_sp, format!("file not found for module `{}`", - mod_name).as_slice(), + mod_name)[], format!("name the file either {} or {} inside \ the directory {}", default_path_str, secondary_path_str, - dir_path.display()).as_slice()); + dir_path.display())[]); } (true, true) => { self.span_fatal_help( @@ -4958,7 +5160,7 @@ impl<'a> Parser<'a> { and {}", mod_name, default_path_str, - secondary_path_str).as_slice(), + secondary_path_str)[], "delete or rename one of them to remove the ambiguity"); } } @@ -4980,11 +5182,11 @@ impl<'a> Parser<'a> { let mut err = String::from_str("circular modules: "); let len = included_mod_stack.len(); for p in included_mod_stack.slice(i, len).iter() { - err.push_str(p.display().as_maybe_owned().as_slice()); + err.push_str(p.display().as_cow()[]); err.push_str(" -> "); } - err.push_str(path.display().as_maybe_owned().as_slice()); - self.span_fatal(id_sp, err.as_slice()); + err.push_str(path.display().as_cow()[]); + self.span_fatal(id_sp, err[]); } None => () } @@ -5037,7 +5239,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 { @@ -5050,17 +5252,6 @@ impl<'a> Parser<'a> { }) } - /// Parse safe/unsafe and fn - fn parse_fn_style(&mut self) -> FnStyle { - if self.eat_keyword(keywords::Fn) { NormalFn } - else if self.eat_keyword(keywords::Unsafe) { - self.expect_keyword(keywords::Fn); - UnsafeFn - } - else { self.unexpected(); } - } - - /// At this point, this is essentially a wrapper for /// parse_foreign_items. fn parse_foreign_mod_items(&mut self, @@ -5076,7 +5267,7 @@ impl<'a> Parser<'a> { if !attrs_remaining.is_empty() { let last_span = self.last_span; self.span_err(last_span, - Parser::expected_item_err(attrs_remaining.as_slice())); + Parser::expected_item_err(attrs_remaining[])); } assert!(self.token == token::CloseDelim(token::Brace)); ast::ForeignMod { @@ -5103,7 +5294,8 @@ impl<'a> Parser<'a> { let (maybe_path, ident) = match self.token { token::Ident(..) => { let the_ident = self.parse_ident(); - let path = if self.eat(&token::Eq) { + let path = if self.token == token::Eq { + self.bump(); let path = self.parse_str(); let span = self.span; self.obsolete(span, ObsoleteExternCrateRenaming); @@ -5116,7 +5308,7 @@ impl<'a> Parser<'a> { self.span_help(span, format!("perhaps you meant to enclose the crate name `{}` in \ a string?", - the_ident.as_str()).as_slice()); + the_ident.as_str())[]); None } else { None @@ -5142,7 +5334,7 @@ impl<'a> Parser<'a> { self.span_fatal(span, format!("expected extern crate name but \ found `{}`", - token_str).as_slice()); + token_str)[]); } }; @@ -5195,7 +5387,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) } @@ -5240,16 +5432,16 @@ impl<'a> Parser<'a> { self.span_err(start_span, format!("unit-like struct variant should be written \ without braces, as `{},`", - token::get_ident(ident)).as_slice()); + token::get_ident(ident))[]); } kind = StructVariantKind(struct_def); - } else if self.token == token::OpenDelim(token::Paren) { + } else if self.check(&token::OpenDelim(token::Paren)) { all_nullary = false; let arg_tys = self.parse_enum_variant_seq( &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 { @@ -5325,7 +5517,7 @@ impl<'a> Parser<'a> { format!("illegal ABI: expected one of [{}], \ found `{}`", abi::all_names().connect(", "), - the_string).as_slice()); + the_string)[]); None } } @@ -5387,7 +5579,7 @@ impl<'a> Parser<'a> { format!("`extern mod` is obsolete, use \ `extern crate` instead \ to refer to external \ - crates.").as_slice()) + crates.")[]) } return self.parse_item_extern_crate(lo, visibility, attrs); } @@ -5398,7 +5590,7 @@ impl<'a> Parser<'a> { // EXTERN FUNCTION ITEM let abi = opt_abi.unwrap_or(abi::C); let (ident, item_, extra_attrs) = - self.parse_item_fn(NormalFn, abi); + self.parse_item_fn(Unsafety::Normal, abi); let last_span = self.last_span; let item = self.mk_item(lo, last_span.hi, @@ -5407,7 +5599,7 @@ impl<'a> Parser<'a> { visibility, maybe_append(attrs, extra_attrs)); return IoviItem(item); - } else if self.token == token::OpenDelim(token::Brace) { + } else if self.check(&token::OpenDelim(token::Brace)) { return self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs); } @@ -5415,7 +5607,7 @@ impl<'a> Parser<'a> { let token_str = self.this_token_to_string(); self.span_fatal(span, format!("expected `{}` or `fn`, found `{}`", "{", - token_str).as_slice()); + token_str)[]); } if self.eat_keyword(keywords::Virtual) { @@ -5456,12 +5648,45 @@ impl<'a> Parser<'a> { maybe_append(attrs, extra_attrs)); return IoviItem(item); } + if self.token.is_keyword(keywords::Unsafe) && + self.look_ahead(1u, |t| t.is_keyword(keywords::Trait)) + { + // UNSAFE TRAIT ITEM + self.expect_keyword(keywords::Unsafe); + self.expect_keyword(keywords::Trait); + let (ident, item_, extra_attrs) = + self.parse_item_trait(ast::Unsafety::Unsafe); + let last_span = self.last_span; + let item = self.mk_item(lo, + last_span.hi, + ident, + item_, + visibility, + maybe_append(attrs, extra_attrs)); + return IoviItem(item); + } + if self.token.is_keyword(keywords::Unsafe) && + self.look_ahead(1u, |t| t.is_keyword(keywords::Impl)) + { + // IMPL ITEM + self.expect_keyword(keywords::Unsafe); + self.expect_keyword(keywords::Impl); + let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe); + let last_span = self.last_span; + let item = self.mk_item(lo, + last_span.hi, + ident, + item_, + visibility, + maybe_append(attrs, extra_attrs)); + return IoviItem(item); + } if self.token.is_keyword(keywords::Fn) && self.look_ahead(1, |f| !Parser::fn_expr_lookahead(f)) { // FUNCTION ITEM self.bump(); let (ident, item_, extra_attrs) = - self.parse_item_fn(NormalFn, abi::Rust); + self.parse_item_fn(Unsafety::Normal, abi::Rust); let last_span = self.last_span; let item = self.mk_item(lo, last_span.hi, @@ -5482,7 +5707,7 @@ impl<'a> Parser<'a> { }; self.expect_keyword(keywords::Fn); let (ident, item_, extra_attrs) = - self.parse_item_fn(UnsafeFn, abi); + self.parse_item_fn(Unsafety::Unsafe, abi); let last_span = self.last_span; let item = self.mk_item(lo, last_span.hi, @@ -5495,7 +5720,7 @@ impl<'a> Parser<'a> { if self.eat_keyword(keywords::Mod) { // MODULE ITEM let (ident, item_, extra_attrs) = - self.parse_item_mod(attrs.as_slice()); + self.parse_item_mod(attrs[]); let last_span = self.last_span; let item = self.mk_item(lo, last_span.hi, @@ -5531,7 +5756,8 @@ impl<'a> Parser<'a> { } if self.eat_keyword(keywords::Trait) { // TRAIT ITEM - let (ident, item_, extra_attrs) = self.parse_item_trait(); + let (ident, item_, extra_attrs) = + self.parse_item_trait(ast::Unsafety::Normal); let last_span = self.last_span; let item = self.mk_item(lo, last_span.hi, @@ -5543,7 +5769,7 @@ impl<'a> Parser<'a> { } if self.eat_keyword(keywords::Impl) { // IMPL ITEM - let (ident, item_, extra_attrs) = self.parse_item_impl(); + let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal); let last_span = self.last_span; let item = self.mk_item(lo, last_span.hi, @@ -5607,7 +5833,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) @@ -5628,6 +5854,17 @@ impl<'a> Parser<'a> { let m: ast::Mac = codemap::Spanned { node: m, span: mk_sp(self.span.lo, self.span.hi) }; + + if delim != token::Brace { + if !self.eat(&token::Semi) { + let last_span = self.last_span; + self.span_err(last_span, + "macros that expand to items must either \ + be surrounded with braces or followed by \ + a semicolon"); + } + } + let item_ = ItemMac(m); let last_span = self.last_span; let item = self.mk_item(lo, @@ -5688,7 +5925,7 @@ impl<'a> Parser<'a> { fn parse_view_path(&mut self) -> P<ViewPath> { let lo = self.span.lo; - if self.token == token::OpenDelim(token::Brace) { + if self.check(&token::OpenDelim(token::Brace)) { // use {foo,bar} let idents = self.parse_unspanned_seq( &token::OpenDelim(token::Brace), @@ -5712,7 +5949,7 @@ impl<'a> Parser<'a> { self.bump(); let path_lo = self.span.lo; path = vec!(self.parse_ident()); - while self.token == token::ModSep { + while self.check(&token::ModSep) { self.bump(); let id = self.parse_ident(); path.push(id); @@ -5736,7 +5973,7 @@ impl<'a> Parser<'a> { token::ModSep => { // foo::bar or foo::{a,b,c} or foo::* - while self.token == token::ModSep { + while self.check(&token::ModSep) { self.bump(); match self.token { @@ -5818,7 +6055,7 @@ impl<'a> Parser<'a> { macros_allowed: bool) -> ParsedItemsAndViewItems { let mut attrs = first_item_attrs; - attrs.push_all(self.parse_outer_attributes().as_slice()); + attrs.push_all(self.parse_outer_attributes()[]); // First, parse view items. let mut view_items : Vec<ast::ViewItem> = Vec::new(); let mut items = Vec::new(); @@ -5900,12 +6137,12 @@ impl<'a> Parser<'a> { macros_allowed: bool) -> ParsedItemsAndViewItems { let mut attrs = first_item_attrs; - attrs.push_all(self.parse_outer_attributes().as_slice()); + attrs.push_all(self.parse_outer_attributes()[]); let mut foreign_items = Vec::new(); loop { match self.parse_foreign_item(attrs, macros_allowed) { IoviNone(returned_attrs) => { - if self.token == token::CloseDelim(token::Brace) { + if self.check(&token::CloseDelim(token::Brace)) { attrs = returned_attrs; break } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 4272b57a4dc..f575d3d6c67 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -28,7 +28,7 @@ use std::path::BytesContainer; use std::rc::Rc; #[allow(non_camel_case_types)] -#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] +#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)] pub enum BinOpToken { Plus, Minus, @@ -43,7 +43,7 @@ pub enum BinOpToken { } /// A delimeter token -#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] +#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)] pub enum DelimToken { /// A round parenthesis: `(` or `)` Paren, @@ -53,14 +53,14 @@ pub enum DelimToken { Brace, } -#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] +#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)] pub enum IdentStyle { /// `::` follows the identifier with no whitespace in-between. ModName, Plain, } -#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] +#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)] pub enum Lit { Byte(ast::Name), Char(ast::Name), @@ -86,7 +86,7 @@ impl Lit { } #[allow(non_camel_case_types)] -#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)] +#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show)] pub enum Token { /* Expression-operator symbols. */ Eq, @@ -334,7 +334,7 @@ impl Token { } } -#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash)] +#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)] /// For interpolation during macro expansion. pub enum Nonterminal { NtItem(P<ast::Item>), @@ -421,17 +421,16 @@ 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; + #[deriving(Copy)] pub enum Keyword { $( $sk_variant, )* $( $rk_variant, )* @@ -455,7 +454,7 @@ macro_rules! declare_special_idents_and_keywords {( $(init_vec.push($si_str);)* $(init_vec.push($sk_str);)* $(init_vec.push($rk_str);)* - interner::StrInterner::prefill(init_vec.as_slice()) + interner::StrInterner::prefill(init_vec[]) } }} @@ -560,15 +559,16 @@ pub type IdentInterner = StrInterner; // fresh one. // FIXME(eddyb) #8726 This should probably use a task-local reference. pub fn get_ident_interner() -> Rc<IdentInterner> { - local_data_key!(key: Rc<::parse::token::IdentInterner>) - match key.get() { - Some(interner) => interner.clone(), - None => { - let interner = Rc::new(mk_fresh_ident_interner()); - key.replace(Some(interner.clone())); - interner - } - } + thread_local!(static KEY: Rc<::parse::token::IdentInterner> = { + Rc::new(mk_fresh_ident_interner()) + }); + KEY.with(|k| k.clone()) +} + +/// Reset the ident interner to its initial state. +pub fn reset_ident_interner() { + let interner = get_ident_interner(); + interner.reset(mk_fresh_ident_interner()); } /// Represents a string stored in the task-local interner. Because the @@ -602,10 +602,14 @@ impl InternedString { #[inline] pub fn get<'a>(&'a self) -> &'a str { - self.string.as_slice() + self.string[] } } +impl Deref<str> for InternedString { + fn deref(&self) -> &str { &*self.string } +} + impl BytesContainer for InternedString { fn container_as_bytes<'a>(&'a self) -> &'a [u8] { // FIXME #12938: This is a workaround for the incorrect signature @@ -620,26 +624,49 @@ impl BytesContainer for InternedString { impl fmt::Show for InternedString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.string.as_slice()) + write!(f, "{}", self.string[]) } } +#[allow(deprecated)] impl<'a> Equiv<&'a str> for InternedString { fn equiv(&self, other: & &'a str) -> bool { - (*other) == self.string.as_slice() + (*other) == self.string[] + } +} + +impl<'a> PartialEq<&'a str> for InternedString { + #[inline(always)] + fn eq(&self, other: & &'a str) -> bool { + PartialEq::eq(self.string[], *other) + } + #[inline(always)] + fn ne(&self, other: & &'a str) -> bool { + PartialEq::ne(self.string[], *other) + } +} + +impl<'a> PartialEq<InternedString > for &'a str { + #[inline(always)] + fn eq(&self, other: &InternedString) -> bool { + PartialEq::eq(*self, other.string[]) + } + #[inline(always)] + fn ne(&self, other: &InternedString) -> bool { + PartialEq::ne(*self, other.string[]) } } impl<D:Decoder<E>, E> Decodable<D, E> for InternedString { fn decode(d: &mut D) -> Result<InternedString, E> { Ok(get_name(get_ident_interner().intern( - try!(d.read_str()).as_slice()))) + try!(d.read_str())[]))) } } impl<S:Encoder<E>, E> Encodable<S, E> for InternedString { fn encode(&self, s: &mut S) -> Result<(), E> { - s.emit_str(self.string.as_slice()) + s.emit_str(self.string[]) } } diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 7ab3d5dbcd1..ab0e0f9585c 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -66,19 +66,19 @@ pub use self::Token::*; use std::io; use std::string; -#[deriving(Clone, PartialEq)] +#[deriving(Clone, Copy, PartialEq)] pub enum Breaks { Consistent, Inconsistent, } -#[deriving(Clone)] +#[deriving(Clone, Copy)] pub struct BreakToken { offset: int, blank_space: int } -#[deriving(Clone)] +#[deriving(Clone, Copy)] pub struct BeginToken { offset: int, breaks: Breaks @@ -139,19 +139,21 @@ pub fn buf_str(toks: Vec<Token>, } s.push_str(format!("{}={}", szs[i], - tok_str(toks[i].clone())).as_slice()); + tok_str(toks[i].clone()))[]); i += 1u; i %= n; } s.push(']'); - return s.into_string(); + s } +#[deriving(Copy)] pub enum PrintStackBreak { Fits, Broken(Breaks), } +#[deriving(Copy)] pub struct PrintStackElem { offset: int, pbreak: PrintStackBreak @@ -599,7 +601,7 @@ impl Printer { assert_eq!(l, len); // assert!(l <= space); self.space -= len; - self.print_str(s.as_slice()) + self.print_str(s[]) } Eof => { // Eof should never get here. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 4ce0d74bd37..3d53bd8aadf 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -11,31 +11,26 @@ pub use self::AnnNode::*; use abi; -use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind}; +use ast::{mod, FnUnboxedClosureKind, FnMutUnboxedClosureKind}; use ast::{FnOnceUnboxedClosureKind}; use ast::{MethodImplItem, RegionTyParamBound, TraitTyParamBound}; use ast::{RequiredMethod, ProvidedMethod, TypeImplItem, TypeTraitItem}; use ast::{UnboxedClosureKind}; -use ast; use ast_util; use owned_slice::OwnedSlice; use attr::{AttrMetaMethods, AttributeMethods}; -use codemap::{CodeMap, BytePos}; -use codemap; +use codemap::{mod, CodeMap, BytePos}; use diagnostic; -use parse::token::{BinOpToken, Token}; -use parse::token; +use parse::token::{mod, BinOpToken, Token}; use parse::lexer::comments; use parse; -use print::pp::{break_offset, word, space, zerobreak, hardbreak}; +use print::pp::{mod, break_offset, word, space, zerobreak, hardbreak}; use print::pp::{Breaks, Consistent, Inconsistent, eof}; -use print::pp; use ptr::P; -use std::ascii; -use std::io::IoResult; -use std::io; -use std::mem; +use std::{ascii, mem}; +use std::io::{mod, IoResult}; +use std::iter; pub enum AnnNode<'a> { NodeIdent(&'a ast::Ident), @@ -51,10 +46,12 @@ pub trait PpAnn { fn post(&self, _state: &mut State, _node: AnnNode) -> IoResult<()> { Ok(()) } } +#[deriving(Copy)] pub struct NoAnn; impl PpAnn for NoAnn {} +#[deriving(Copy)] pub struct CurrentCommentAndLiteral { cur_cmnt: uint, cur_lit: uint, @@ -67,7 +64,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, } @@ -117,7 +114,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, out, ann, is_expanded); - try!(s.print_mod(&krate.module, krate.attrs.as_slice())); + try!(s.print_mod(&krate.module, krate.attrs[])); try!(s.print_remaining_comments()); eof(&mut s.s) } @@ -167,7 +164,9 @@ impl<'a> State<'a> { } } -pub fn to_string(f: |&mut State| -> IoResult<()>) -> String { +pub fn to_string<F>(f: F) -> String where + F: FnOnce(&mut State) -> IoResult<()>, +{ use std::raw::TraitObject; let mut s = rust_printer(box Vec::new()); f(&mut s).unwrap(); @@ -199,56 +198,56 @@ pub fn binop_to_string(op: BinOpToken) -> &'static str { pub fn token_to_string(tok: &Token) -> String { match *tok { - token::Eq => "=".into_string(), - token::Lt => "<".into_string(), - token::Le => "<=".into_string(), - token::EqEq => "==".into_string(), - token::Ne => "!=".into_string(), - token::Ge => ">=".into_string(), - token::Gt => ">".into_string(), - token::Not => "!".into_string(), - token::Tilde => "~".into_string(), - token::OrOr => "||".into_string(), - token::AndAnd => "&&".into_string(), - token::BinOp(op) => binop_to_string(op).into_string(), + token::Eq => "=".to_string(), + token::Lt => "<".to_string(), + token::Le => "<=".to_string(), + token::EqEq => "==".to_string(), + token::Ne => "!=".to_string(), + token::Ge => ">=".to_string(), + token::Gt => ">".to_string(), + token::Not => "!".to_string(), + token::Tilde => "~".to_string(), + token::OrOr => "||".to_string(), + token::AndAnd => "&&".to_string(), + token::BinOp(op) => binop_to_string(op).to_string(), token::BinOpEq(op) => format!("{}=", binop_to_string(op)), /* Structural symbols */ - token::At => "@".into_string(), - token::Dot => ".".into_string(), - token::DotDot => "..".into_string(), - token::DotDotDot => "...".into_string(), - token::Comma => ",".into_string(), - token::Semi => ";".into_string(), - token::Colon => ":".into_string(), - token::ModSep => "::".into_string(), - token::RArrow => "->".into_string(), - token::LArrow => "<-".into_string(), - token::FatArrow => "=>".into_string(), - token::OpenDelim(token::Paren) => "(".into_string(), - token::CloseDelim(token::Paren) => ")".into_string(), - token::OpenDelim(token::Bracket) => "[".into_string(), - token::CloseDelim(token::Bracket) => "]".into_string(), - token::OpenDelim(token::Brace) => "{".into_string(), - token::CloseDelim(token::Brace) => "}".into_string(), - token::Pound => "#".into_string(), - token::Dollar => "$".into_string(), - token::Question => "?".into_string(), + token::At => "@".to_string(), + token::Dot => ".".to_string(), + token::DotDot => "..".to_string(), + token::DotDotDot => "...".to_string(), + token::Comma => ",".to_string(), + token::Semi => ";".to_string(), + token::Colon => ":".to_string(), + token::ModSep => "::".to_string(), + token::RArrow => "->".to_string(), + token::LArrow => "<-".to_string(), + token::FatArrow => "=>".to_string(), + token::OpenDelim(token::Paren) => "(".to_string(), + token::CloseDelim(token::Paren) => ")".to_string(), + token::OpenDelim(token::Bracket) => "[".to_string(), + token::CloseDelim(token::Bracket) => "]".to_string(), + token::OpenDelim(token::Brace) => "{".to_string(), + token::CloseDelim(token::Brace) => "}".to_string(), + token::Pound => "#".to_string(), + token::Dollar => "$".to_string(), + token::Question => "?".to_string(), /* Literals */ token::Literal(lit, suf) => { let mut out = match lit { token::Byte(b) => format!("b'{}'", b.as_str()), token::Char(c) => format!("'{}'", c.as_str()), - token::Float(c) => c.as_str().into_string(), - token::Integer(c) => c.as_str().into_string(), + token::Float(c) => c.as_str().to_string(), + token::Integer(c) => c.as_str().to_string(), token::Str_(s) => format!("\"{}\"", s.as_str()), token::StrRaw(s, n) => format!("r{delim}\"{string}\"{delim}", - delim="#".repeat(n), + delim=repeat("#", n), string=s.as_str()), token::Binary(v) => format!("b\"{}\"", v.as_str()), token::BinaryRaw(s, n) => format!("br{delim}\"{string}\"{delim}", - delim="#".repeat(n), + delim=repeat("#", n), string=s.as_str()), }; @@ -260,17 +259,17 @@ pub fn token_to_string(tok: &Token) -> String { } /* Name components */ - token::Ident(s, _) => token::get_ident(s).get().into_string(), + token::Ident(s, _) => token::get_ident(s).get().to_string(), token::Lifetime(s) => format!("{}", token::get_ident(s)), - token::Underscore => "_".into_string(), + token::Underscore => "_".to_string(), /* Other */ - token::DocComment(s) => s.as_str().into_string(), + token::DocComment(s) => s.as_str().to_string(), token::SubstNt(s, _) => format!("${}", s), token::MatchNt(s, t, _, _) => format!("${}:{}", s, t), - token::Eof => "<eof>".into_string(), - token::Whitespace => " ".into_string(), - token::Comment => "/* */".into_string(), + token::Eof => "<eof>".to_string(), + token::Whitespace => " ".to_string(), + token::Comment => "/* */".to_string(), token::Shebang(s) => format!("/* shebang: {}*/", s.as_str()), token::Interpolated(ref nt) => match *nt { @@ -278,12 +277,12 @@ pub fn token_to_string(tok: &Token) -> String { token::NtMeta(ref e) => meta_item_to_string(&**e), token::NtTy(ref e) => ty_to_string(&**e), token::NtPath(ref e) => path_to_string(&**e), - token::NtItem(..) => "an interpolated item".into_string(), - token::NtBlock(..) => "an interpolated block".into_string(), - token::NtStmt(..) => "an interpolated statement".into_string(), - token::NtPat(..) => "an interpolated pattern".into_string(), - token::NtIdent(..) => "an interpolated identifier".into_string(), - token::NtTT(..) => "an interpolated tt".into_string(), + token::NtItem(..) => "an interpolated item".to_string(), + token::NtBlock(..) => "an interpolated block".to_string(), + token::NtStmt(..) => "an interpolated statement".to_string(), + token::NtPat(..) => "an interpolated pattern".to_string(), + token::NtIdent(..) => "an interpolated identifier".to_string(), + token::NtTT(..) => "an interpolated tt".to_string(), } } } @@ -299,6 +298,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)) } @@ -359,11 +362,11 @@ pub fn ident_to_string(id: &ast::Ident) -> String { $to_string(|s| s.print_ident(*id)) } -pub fn fun_to_string(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Ident, +pub fn fun_to_string(decl: &ast::FnDecl, unsafety: ast::Unsafety, name: ast::Ident, opt_explicit_self: Option<&ast::ExplicitSelf_>, generics: &ast::Generics) -> String { $to_string(|s| { - try!(s.print_fn(decl, Some(fn_style), abi::Rust, + try!(s.print_fn(decl, Some(unsafety), abi::Rust, name, generics, opt_explicit_self, ast::Inherited)); try!(s.end()); // Close the head box s.end() // Close the outer box @@ -405,12 +408,12 @@ pub fn arg_to_string(arg: &ast::Arg) -> String { } pub fn mac_to_string(arg: &ast::Mac) -> String { - $to_string(|s| s.print_mac(arg)) + $to_string(|s| s.print_mac(arg, ::parse::token::Paren)) } } } -thing_to_string_impls!(to_string) +thing_to_string_impls! { to_string } // FIXME (Issue #16472): the whole `with_hygiene` mod should go away // after we revise the syntax::ext::quote::ToToken impls to go directly @@ -424,14 +427,16 @@ pub mod with_hygiene { // This function is the trick that all the rest of the routines // hang on. - pub fn to_string_hyg(f: |&mut super::State| -> IoResult<()>) -> String { - super::to_string(|s| { + pub fn to_string_hyg<F>(f: F) -> String where + F: FnOnce(&mut super::State) -> IoResult<()>, + { + super::to_string(move |s| { s.encode_idents_with_hygiene = true; f(s) }) } - thing_to_string_impls!(to_string_hyg) + thing_to_string_impls! { to_string_hyg } } pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String { @@ -444,7 +449,7 @@ pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> String { fn needs_parentheses(expr: &ast::Expr) -> bool { match expr.node { ast::ExprAssign(..) | ast::ExprBinary(..) | - ast::ExprClosure(..) | ast::ExprProc(..) | + ast::ExprClosure(..) | ast::ExprAssignOp(..) | ast::ExprCast(..) => true, _ => false, } @@ -573,14 +578,14 @@ impl<'a> State<'a> { pub fn synth_comment(&mut self, text: String) -> IoResult<()> { try!(word(&mut self.s, "/*")); try!(space(&mut self.s)); - try!(word(&mut self.s, text.as_slice())); + try!(word(&mut self.s, text[])); try!(space(&mut self.s)); word(&mut self.s, "*/") } - pub fn commasep<T>(&mut self, b: Breaks, elts: &[T], - op: |&mut State, &T| -> IoResult<()>) - -> IoResult<()> { + pub fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) -> IoResult<()> where + F: FnMut(&mut State, &T) -> IoResult<()>, + { try!(self.rbox(0u, b)); let mut first = true; for elt in elts.iter() { @@ -591,12 +596,14 @@ impl<'a> State<'a> { } - pub fn commasep_cmnt<T>( - &mut self, - b: Breaks, - elts: &[T], - op: |&mut State, &T| -> IoResult<()>, - get_span: |&T| -> codemap::Span) -> IoResult<()> { + pub fn commasep_cmnt<T, F, G>(&mut self, + b: Breaks, + elts: &[T], + mut op: F, + mut get_span: G) -> IoResult<()> where + F: FnMut(&mut State, &T) -> IoResult<()>, + G: FnMut(&T) -> codemap::Span, + { try!(self.rbox(0u, b)); let len = elts.len(); let mut i = 0u; @@ -676,7 +683,7 @@ impl<'a> State<'a> { } ast::TyTup(ref elts) => { try!(self.popen()); - try!(self.commasep(Inconsistent, elts.as_slice(), + try!(self.commasep(Inconsistent, elts[], |s, ty| s.print_type(&**ty))); if elts.len() == 1 { try!(word(&mut self.s, ",")); @@ -699,7 +706,7 @@ impl<'a> State<'a> { }; try!(self.print_ty_fn(Some(f.abi), None, - f.fn_style, + f.unsafety, ast::Many, &*f.decl, None, @@ -718,7 +725,7 @@ impl<'a> State<'a> { }; try!(self.print_ty_fn(None, Some('&'), - f.fn_style, + f.unsafety, f.onceness, &*f.decl, None, @@ -726,30 +733,15 @@ impl<'a> State<'a> { Some(&generics), None)); } - ast::TyProc(ref f) => { - let generics = ast::Generics { - lifetimes: f.lifetimes.clone(), - ty_params: OwnedSlice::empty(), - where_clause: ast::WhereClause { - id: ast::DUMMY_NODE_ID, - predicates: Vec::new(), - }, - }; - try!(self.print_ty_fn(None, - Some('~'), - f.fn_style, - f.onceness, - &*f.decl, - None, - &f.bounds, - Some(&generics), - None)); + ast::TyPath(ref path, _) => { + try!(self.print_path(path, false)); } - ast::TyPath(ref path, ref bounds, _) => { - try!(self.print_bounded_path(path, bounds)); + ast::TyObjectSum(ref ty, ref bounds) => { + try!(self.print_type(&**ty)); + try!(self.print_bounds("+", bounds[])); } ast::TyPolyTraitRef(ref bounds) => { - try!(self.print_bounds("", bounds)); + try!(self.print_bounds("", bounds[])); } ast::TyQPath(ref qpath) => { try!(word(&mut self.s, "<")); @@ -764,7 +756,7 @@ impl<'a> State<'a> { ast::TyFixedLengthVec(ref ty, ref v) => { try!(word(&mut self.s, "[")); try!(self.print_type(&**ty)); - try!(word(&mut self.s, ", ..")); + try!(word(&mut self.s, "; ")); try!(self.print_expr(&**v)); try!(word(&mut self.s, "]")); } @@ -784,7 +776,7 @@ impl<'a> State<'a> { item: &ast::ForeignItem) -> IoResult<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(item.span.lo)); - try!(self.print_outer_attributes(item.attrs.as_slice())); + try!(self.print_outer_attributes(item.attrs[])); match item.node { ast::ForeignItemFn(ref decl, ref generics) => { try!(self.print_fn(&**decl, None, abi::Rust, item.ident, generics, @@ -795,7 +787,7 @@ impl<'a> State<'a> { } ast::ForeignItemStatic(ref t, m) => { try!(self.head(visibility_qualified(item.vis, - "static").as_slice())); + "static")[])); if m { try!(self.word_space("mut")); } @@ -831,12 +823,12 @@ impl<'a> State<'a> { pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(item.span.lo)); - try!(self.print_outer_attributes(item.attrs.as_slice())); + try!(self.print_outer_attributes(item.attrs[])); try!(self.ann.pre(self, NodeItem(item))); match item.node { ast::ItemStatic(ref ty, m, ref expr) => { try!(self.head(visibility_qualified(item.vis, - "static").as_slice())); + "static")[])); if m == ast::MutMutable { try!(self.word_space("mut")); } @@ -853,7 +845,7 @@ impl<'a> State<'a> { } ast::ItemConst(ref ty, ref expr) => { try!(self.head(visibility_qualified(item.vis, - "const").as_slice())); + "const")[])); try!(self.print_ident(item.ident)); try!(self.word_space(":")); try!(self.print_type(&**ty)); @@ -865,10 +857,10 @@ impl<'a> State<'a> { try!(word(&mut self.s, ";")); try!(self.end()); // end the outer cbox } - ast::ItemFn(ref decl, fn_style, abi, ref typarams, ref body) => { + ast::ItemFn(ref decl, unsafety, abi, ref typarams, ref body) => { try!(self.print_fn( &**decl, - Some(fn_style), + Some(unsafety), abi, item.ident, typarams, @@ -876,29 +868,29 @@ impl<'a> State<'a> { item.vis )); try!(word(&mut self.s, " ")); - try!(self.print_block_with_attrs(&**body, item.attrs.as_slice())); + try!(self.print_block_with_attrs(&**body, item.attrs[])); } ast::ItemMod(ref _mod) => { try!(self.head(visibility_qualified(item.vis, - "mod").as_slice())); + "mod")[])); try!(self.print_ident(item.ident)); try!(self.nbsp()); try!(self.bopen()); - try!(self.print_mod(_mod, item.attrs.as_slice())); + try!(self.print_mod(_mod, item.attrs[])); try!(self.bclose(item.span)); } ast::ItemForeignMod(ref nmod) => { try!(self.head("extern")); - try!(self.word_nbsp(nmod.abi.to_string().as_slice())); + try!(self.word_nbsp(nmod.abi.to_string()[])); try!(self.bopen()); - try!(self.print_foreign_mod(nmod, item.attrs.as_slice())); + try!(self.print_foreign_mod(nmod, item.attrs[])); try!(self.bclose(item.span)); } ast::ItemTy(ref ty, ref params) => { try!(self.ibox(indent_unit)); try!(self.ibox(0u)); try!(self.word_nbsp(visibility_qualified(item.vis, - "type").as_slice())); + "type")[])); try!(self.print_ident(item.ident)); try!(self.print_generics(params)); try!(self.end()); // end the inner ibox @@ -920,16 +912,20 @@ impl<'a> State<'a> { )); } ast::ItemStruct(ref struct_def, ref generics) => { - try!(self.head(visibility_qualified(item.vis,"struct").as_slice())); + try!(self.head(visibility_qualified(item.vis,"struct")[])); try!(self.print_struct(&**struct_def, generics, item.ident, item.span)); } - ast::ItemImpl(ref generics, + ast::ItemImpl(unsafety, + ref generics, ref opt_trait, ref ty, ref impl_items) => { - try!(self.head(visibility_qualified(item.vis, - "impl").as_slice())); + try!(self.head("")); + try!(self.print_visibility(item.vis)); + try!(self.print_unsafety(unsafety)); + try!(self.word_nbsp("impl")); + if generics.is_parameterized() { try!(self.print_generics(generics)); try!(space(&mut self.s)); @@ -949,7 +945,7 @@ impl<'a> State<'a> { try!(space(&mut self.s)); try!(self.bopen()); - try!(self.print_inner_attributes(item.attrs.as_slice())); + try!(self.print_inner_attributes(item.attrs[])); for impl_item in impl_items.iter() { match *impl_item { ast::MethodImplItem(ref meth) => { @@ -962,21 +958,20 @@ impl<'a> State<'a> { } try!(self.bclose(item.span)); } - ast::ItemTrait(ref generics, ref unbound, ref bounds, ref methods) => { - try!(self.head(visibility_qualified(item.vis, - "trait").as_slice())); + ast::ItemTrait(unsafety, ref generics, ref unbound, ref bounds, ref methods) => { + try!(self.head("")); + try!(self.print_visibility(item.vis)); + try!(self.print_unsafety(unsafety)); + try!(self.word_nbsp("trait")); try!(self.print_ident(item.ident)); try!(self.print_generics(generics)); - match unbound { - &Some(ref tref) => { - try!(space(&mut self.s)); - try!(self.word_space("for")); - try!(self.print_trait_ref(tref)); - try!(word(&mut self.s, "?")); - } - _ => {} + if let &Some(ref tref) = unbound { + try!(space(&mut self.s)); + try!(self.word_space("for")); + try!(self.print_trait_ref(tref)); + try!(word(&mut self.s, "?")); } - try!(self.print_bounds(":", bounds)); + try!(self.print_bounds(":", bounds[])); try!(self.print_where_clause(generics)); try!(word(&mut self.s, " ")); try!(self.bopen()); @@ -994,8 +989,9 @@ impl<'a> State<'a> { try!(self.print_ident(item.ident)); try!(self.cbox(indent_unit)); try!(self.popen()); - try!(self.print_tts(tts.as_slice())); + try!(self.print_tts(tts[])); try!(self.pclose()); + try!(word(&mut self.s, ";")); try!(self.end()); } } @@ -1009,8 +1005,13 @@ impl<'a> State<'a> { fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> IoResult<()> { if !t.bound_lifetimes.is_empty() { try!(word(&mut self.s, "for<")); + let mut comma = false; for lifetime_def in t.bound_lifetimes.iter() { + if comma { + try!(self.word_space(",")) + } try!(self.print_lifetime_def(lifetime_def)); + comma = true; } try!(word(&mut self.s, ">")); } @@ -1022,12 +1023,12 @@ impl<'a> State<'a> { generics: &ast::Generics, ident: ast::Ident, span: codemap::Span, visibility: ast::Visibility) -> IoResult<()> { - try!(self.head(visibility_qualified(visibility, "enum").as_slice())); + try!(self.head(visibility_qualified(visibility, "enum")[])); try!(self.print_ident(ident)); try!(self.print_generics(generics)); try!(self.print_where_clause(generics)); try!(space(&mut self.s)); - self.print_variants(enum_definition.variants.as_slice(), span) + self.print_variants(enum_definition.variants[], span) } pub fn print_variants(&mut self, @@ -1037,7 +1038,7 @@ impl<'a> State<'a> { for v in variants.iter() { try!(self.space_if_not_bol()); try!(self.maybe_print_comment(v.span.lo)); - try!(self.print_outer_attributes(v.node.attrs.as_slice())); + try!(self.print_outer_attributes(v.node.attrs[])); try!(self.ibox(indent_unit)); try!(self.print_variant(&**v)); try!(word(&mut self.s, ",")); @@ -1061,11 +1062,12 @@ impl<'a> State<'a> { span: codemap::Span) -> IoResult<()> { try!(self.print_ident(ident)); try!(self.print_generics(generics)); + try!(self.print_where_clause(generics)); if ast_util::struct_def_is_tuple_like(struct_def) { if !struct_def.fields.is_empty() { try!(self.popen()); try!(self.commasep( - Inconsistent, struct_def.fields.as_slice(), + Inconsistent, struct_def.fields[], |s, field| { match field.node.kind { ast::NamedField(..) => panic!("unexpected named field"), @@ -1093,7 +1095,7 @@ impl<'a> State<'a> { ast::NamedField(ident, visibility) => { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(field.span.lo)); - try!(self.print_outer_attributes(field.node.attrs.as_slice())); + try!(self.print_outer_attributes(field.node.attrs[])); try!(self.print_visibility(visibility)); try!(self.print_ident(ident)); try!(self.word_nbsp(":")); @@ -1117,7 +1119,7 @@ impl<'a> State<'a> { pub fn print_tt(&mut self, tt: &ast::TokenTree) -> IoResult<()> { match *tt { ast::TtToken(_, ref tk) => { - try!(word(&mut self.s, token_to_string(tk).as_slice())); + try!(word(&mut self.s, token_to_string(tk)[])); match *tk { parse::token::DocComment(..) => { hardbreak(&mut self.s) @@ -1126,11 +1128,11 @@ impl<'a> State<'a> { } } ast::TtDelimited(_, ref delimed) => { - try!(word(&mut self.s, token_to_string(&delimed.open_token()).as_slice())); + try!(word(&mut self.s, token_to_string(&delimed.open_token())[])); try!(space(&mut self.s)); - try!(self.print_tts(delimed.tts.as_slice())); + try!(self.print_tts(delimed.tts[])); try!(space(&mut self.s)); - word(&mut self.s, token_to_string(&delimed.close_token()).as_slice()) + word(&mut self.s, token_to_string(&delimed.close_token())[]) }, ast::TtSequence(_, ref seq) => { try!(word(&mut self.s, "$(")); @@ -1140,7 +1142,7 @@ impl<'a> State<'a> { try!(word(&mut self.s, ")")); match seq.separator { Some(ref tk) => { - try!(word(&mut self.s, token_to_string(tk).as_slice())); + try!(word(&mut self.s, token_to_string(tk)[])); } None => {}, } @@ -1171,7 +1173,7 @@ impl<'a> State<'a> { if !args.is_empty() { try!(self.popen()); try!(self.commasep(Consistent, - args.as_slice(), + args[], |s, arg| s.print_type(&*arg.ty))); try!(self.pclose()); } @@ -1195,10 +1197,10 @@ impl<'a> State<'a> { pub fn print_ty_method(&mut self, m: &ast::TypeMethod) -> IoResult<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(m.span.lo)); - try!(self.print_outer_attributes(m.attrs.as_slice())); + try!(self.print_outer_attributes(m.attrs[])); try!(self.print_ty_fn(None, None, - m.fn_style, + m.unsafety, ast::Many, &*m.decl, Some(m.ident), @@ -1227,25 +1229,25 @@ impl<'a> State<'a> { pub fn print_method(&mut self, meth: &ast::Method) -> IoResult<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(meth.span.lo)); - try!(self.print_outer_attributes(meth.attrs.as_slice())); + try!(self.print_outer_attributes(meth.attrs[])); match meth.node { ast::MethDecl(ident, ref generics, abi, ref explicit_self, - fn_style, + unsafety, ref decl, ref body, vis) => { try!(self.print_fn(&**decl, - Some(fn_style), + Some(unsafety), abi, ident, generics, Some(&explicit_self.node), vis)); try!(word(&mut self.s, " ")); - self.print_block_with_attrs(&**body, meth.attrs.as_slice()) + self.print_block_with_attrs(&**body, meth.attrs[]) }, ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _), ..}) => { @@ -1254,8 +1256,9 @@ impl<'a> State<'a> { try!(word(&mut self.s, "! ")); try!(self.cbox(indent_unit)); try!(self.popen()); - try!(self.print_tts(tts.as_slice())); + try!(self.print_tts(tts[])); try!(self.pclose()); + try!(word(&mut self.s, ";")); self.end() } } @@ -1328,11 +1331,16 @@ impl<'a> State<'a> { try!(self.print_expr(&**expr)); try!(word(&mut self.s, ";")); } - ast::StmtMac(ref mac, semi) => { + ast::StmtMac(ref mac, style) => { try!(self.space_if_not_bol()); - try!(self.print_mac(mac)); - if semi { - try!(word(&mut self.s, ";")); + let delim = match style { + ast::MacStmtWithBraces => token::Brace, + _ => token::Paren + }; + try!(self.print_mac(mac, delim)); + match style { + ast::MacStmtWithBraces => {} + _ => try!(word(&mut self.s, ";")), } } } @@ -1459,15 +1467,24 @@ impl<'a> State<'a> { self.print_else(elseopt) } - pub fn print_mac(&mut self, m: &ast::Mac) -> IoResult<()> { + pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken) + -> IoResult<()> { match m.node { // I think it's reasonable to hide the ctxt here: ast::MacInvocTT(ref pth, ref tts, _) => { try!(self.print_path(pth, false)); try!(word(&mut self.s, "!")); - try!(self.popen()); + match delim { + token::Paren => try!(self.popen()), + token::Bracket => try!(word(&mut self.s, "[")), + token::Brace => try!(self.bopen()), + } try!(self.print_tts(tts.as_slice())); - self.pclose() + match delim { + token::Paren => self.pclose(), + token::Bracket => word(&mut self.s, "]"), + token::Brace => self.bclose(m.span), + } } } } @@ -1499,14 +1516,14 @@ impl<'a> State<'a> { ast::ExprBox(ref p, ref e) => { try!(word(&mut self.s, "box")); try!(word(&mut self.s, "(")); - try!(self.print_expr(&**p)); + try!(p.as_ref().map_or(Ok(()), |e|self.print_expr(&**e))); try!(self.word_space(")")); try!(self.print_expr(&**e)); } ast::ExprVec(ref exprs) => { try!(self.ibox(indent_unit)); try!(word(&mut self.s, "[")); - try!(self.commasep_exprs(Inconsistent, exprs.as_slice())); + try!(self.commasep_exprs(Inconsistent, exprs[])); try!(word(&mut self.s, "]")); try!(self.end()); } @@ -1515,8 +1532,7 @@ impl<'a> State<'a> { try!(self.ibox(indent_unit)); try!(word(&mut self.s, "[")); try!(self.print_expr(&**element)); - try!(word(&mut self.s, ",")); - try!(word(&mut self.s, "..")); + try!(self.word_space(";")); try!(self.print_expr(&**count)); try!(word(&mut self.s, "]")); try!(self.end()); @@ -1527,7 +1543,7 @@ impl<'a> State<'a> { try!(word(&mut self.s, "{")); try!(self.commasep_cmnt( Consistent, - fields.as_slice(), + fields[], |s, field| { try!(s.ibox(indent_unit)); try!(s.print_ident(field.ident.node)); @@ -1553,7 +1569,7 @@ impl<'a> State<'a> { } ast::ExprTup(ref exprs) => { try!(self.popen()); - try!(self.commasep_exprs(Inconsistent, exprs.as_slice())); + try!(self.commasep_exprs(Inconsistent, exprs[])); if exprs.len() == 1 { try!(word(&mut self.s, ",")); } @@ -1561,7 +1577,7 @@ impl<'a> State<'a> { } ast::ExprCall(ref func, ref args) => { try!(self.print_expr_maybe_paren(&**func)); - try!(self.print_call_post(args.as_slice())); + try!(self.print_call_post(args[])); } ast::ExprMethodCall(ident, ref tys, ref args) => { let base_args = args.slice_from(1); @@ -1570,7 +1586,7 @@ impl<'a> State<'a> { try!(self.print_ident(ident.node)); if tys.len() > 0u { try!(word(&mut self.s, "::<")); - try!(self.commasep(Inconsistent, tys.as_slice(), + try!(self.commasep(Inconsistent, tys[], |s, ty| s.print_type(&**ty))); try!(word(&mut self.s, ">")); } @@ -1687,33 +1703,6 @@ impl<'a> State<'a> { // empty box to satisfy the close. try!(self.ibox(0)); } - ast::ExprProc(ref decl, ref body) => { - // in do/for blocks we don't want to show an empty - // argument list, but at this point we don't know which - // we are inside. - // - // if !decl.inputs.is_empty() { - try!(self.print_proc_args(&**decl)); - try!(space(&mut self.s)); - // } - assert!(body.stmts.is_empty()); - assert!(body.expr.is_some()); - // we extract the block, so as not to create another set of boxes - match body.expr.as_ref().unwrap().node { - ast::ExprBlock(ref blk) => { - try!(self.print_block_unclosed(&**blk)); - } - _ => { - // this is a bare expression - try!(self.print_expr(body.expr.as_ref().map(|e| &**e).unwrap())); - try!(self.end()); // need to close a box - } - } - // a box will be closed by print_expr, but we didn't want an overall - // wrapper so we closed the corresponding opening. so create an - // empty box to satisfy the close. - try!(self.ibox(0)); - } ast::ExprBlock(ref blk) => { // containing cbox, will be closed by print-block at } try!(self.cbox(indent_unit)); @@ -1734,29 +1723,15 @@ impl<'a> State<'a> { try!(self.word_space("=")); try!(self.print_expr(&**rhs)); } - ast::ExprField(ref expr, id, ref tys) => { + ast::ExprField(ref expr, id) => { try!(self.print_expr(&**expr)); try!(word(&mut self.s, ".")); try!(self.print_ident(id.node)); - if tys.len() > 0u { - try!(word(&mut self.s, "::<")); - try!(self.commasep( - Inconsistent, tys.as_slice(), - |s, ty| s.print_type(&**ty))); - try!(word(&mut self.s, ">")); - } } - ast::ExprTupField(ref expr, id, ref tys) => { + ast::ExprTupField(ref expr, id) => { try!(self.print_expr(&**expr)); try!(word(&mut self.s, ".")); try!(self.print_uint(id.node)); - if tys.len() > 0u { - try!(word(&mut self.s, "::<")); - try!(self.commasep( - Inconsistent, tys.as_slice(), - |s, ty| s.print_type(&**ty))); - try!(word(&mut self.s, ">")); - } } ast::ExprIndex(ref expr, ref index) => { try!(self.print_expr(&**expr)); @@ -1773,19 +1748,24 @@ impl<'a> State<'a> { try!(space(&mut self.s)); } } - match start { - &Some(ref e) => try!(self.print_expr(&**e)), - _ => {} + if let &Some(ref e) = start { + try!(self.print_expr(&**e)); } if start.is_some() || end.is_some() { try!(word(&mut self.s, "..")); } - match end { - &Some(ref e) => try!(self.print_expr(&**e)), - _ => {} + if let &Some(ref e) = end { + try!(self.print_expr(&**e)); } try!(word(&mut self.s, "]")); } + ast::ExprRange(ref start, ref end) => { + try!(self.print_expr(&**start)); + try!(word(&mut self.s, "..")); + if let &Some(ref e) = end { + try!(self.print_expr(&**e)); + } + } ast::ExprPath(ref path) => try!(self.print_path(path, true)), ast::ExprBreak(opt_ident) => { try!(word(&mut self.s, "break")); @@ -1814,20 +1794,16 @@ impl<'a> State<'a> { } } ast::ExprInlineAsm(ref a) => { - if a.volatile { - try!(word(&mut self.s, "__volatile__ asm!")); - } else { - try!(word(&mut self.s, "asm!")); - } + try!(word(&mut self.s, "asm!")); try!(self.popen()); try!(self.print_string(a.asm.get(), a.asm_str_style)); try!(self.word_space(":")); - try!(self.commasep(Inconsistent, a.outputs.as_slice(), + try!(self.commasep(Inconsistent, a.outputs[], |s, &(ref co, ref o, is_rw)| { match co.get().slice_shift_char() { Some(('=', operand)) if is_rw => { - try!(s.print_string(format!("+{}", operand).as_slice(), + try!(s.print_string(format!("+{}", operand)[], ast::CookedStr)) } _ => try!(s.print_string(co.get(), ast::CookedStr)) @@ -1840,7 +1816,7 @@ impl<'a> State<'a> { try!(space(&mut self.s)); try!(self.word_space(":")); - try!(self.commasep(Inconsistent, a.inputs.as_slice(), + try!(self.commasep(Inconsistent, a.inputs[], |s, &(ref co, ref o)| { try!(s.print_string(co.get(), ast::CookedStr)); try!(s.popen()); @@ -1851,10 +1827,36 @@ impl<'a> State<'a> { try!(space(&mut self.s)); try!(self.word_space(":")); - try!(self.print_string(a.clobbers.get(), ast::CookedStr)); + try!(self.commasep(Inconsistent, a.clobbers[], + |s, co| { + try!(s.print_string(co.get(), ast::CookedStr)); + Ok(()) + })); + + let mut options = vec!(); + if a.volatile { + options.push("volatile"); + } + if a.alignstack { + options.push("alignstack"); + } + if a.dialect == ast::AsmDialect::AsmIntel { + options.push("intel"); + } + + if options.len() > 0 { + try!(space(&mut self.s)); + try!(self.word_space(":")); + try!(self.commasep(Inconsistent, &*options, + |s, &co| { + try!(s.print_string(co, ast::CookedStr)); + Ok(()) + })); + } + try!(self.pclose()); } - ast::ExprMac(ref m) => try!(self.print_mac(m)), + ast::ExprMac(ref m) => try!(self.print_mac(m, token::Paren)), ast::ExprParen(ref e) => { try!(self.popen()); try!(self.print_expr(&**e)); @@ -1887,13 +1889,10 @@ impl<'a> State<'a> { try!(self.ibox(indent_unit)); try!(self.print_local_decl(&**loc)); try!(self.end()); - match loc.init { - Some(ref init) => { - try!(self.nbsp()); - try!(self.word_space("=")); - try!(self.print_expr(&**init)); - } - _ => {} + if let Some(ref init) = loc.init { + try!(self.nbsp()); + try!(self.word_space("=")); + try!(self.print_expr(&**init)); } self.end() } @@ -1904,7 +1903,7 @@ impl<'a> State<'a> { pub fn print_ident(&mut self, ident: ast::Ident) -> IoResult<()> { if self.encode_idents_with_hygiene { let encoded = ident.encode_with_hygiene(); - try!(word(&mut self.s, encoded.as_slice())) + try!(word(&mut self.s, encoded[])) } else { try!(word(&mut self.s, token::get_ident(ident).get())) } @@ -1912,7 +1911,7 @@ impl<'a> State<'a> { } pub fn print_uint(&mut self, i: uint) -> IoResult<()> { - word(&mut self.s, i.to_string().as_slice()) + word(&mut self.s, i.to_string()[]) } pub fn print_name(&mut self, name: ast::Name) -> IoResult<()> { @@ -1928,11 +1927,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, "::")); @@ -1951,10 +1950,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, @@ -1989,8 +1985,20 @@ impl<'a> State<'a> { } try!(self.commasep( Inconsistent, - data.types.as_slice(), + data.types[], |s, ty| s.print_type(&**ty))); + comma = true; + } + + for binding in data.bindings.iter() { + if comma { + try!(self.word_space(",")) + } + try!(self.print_ident(binding.ident)); + try!(space(&mut self.s)); + try!(self.word_space("=")); + try!(self.print_type(&*binding.ty)); + comma = true; } try!(word(&mut self.s, ">")) @@ -2000,13 +2008,14 @@ impl<'a> State<'a> { try!(word(&mut self.s, "(")); try!(self.commasep( Inconsistent, - data.inputs.as_slice(), + data.inputs[], |s, ty| s.print_type(&**ty))); try!(word(&mut self.s, ")")); match data.output { None => { } Some(ref ty) => { + try!(self.space_if_not_bol()); try!(self.word_space("->")); try!(self.print_type(&**ty)); } @@ -2017,17 +2026,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))); @@ -2063,7 +2061,7 @@ impl<'a> State<'a> { Some(ref args) => { if !args.is_empty() { try!(self.popen()); - try!(self.commasep(Inconsistent, args.as_slice(), + try!(self.commasep(Inconsistent, args[], |s, p| s.print_pat(&**p))); try!(self.pclose()); } @@ -2075,7 +2073,7 @@ impl<'a> State<'a> { try!(self.nbsp()); try!(self.word_space("{")); try!(self.commasep_cmnt( - Consistent, fields.as_slice(), + Consistent, fields[], |s, f| { try!(s.cbox(indent_unit)); if !f.node.is_shorthand { @@ -2096,7 +2094,7 @@ impl<'a> State<'a> { ast::PatTup(ref elts) => { try!(self.popen()); try!(self.commasep(Inconsistent, - elts.as_slice(), + elts[], |s, p| s.print_pat(&**p))); if elts.len() == 1 { try!(word(&mut self.s, ",")); @@ -2121,7 +2119,7 @@ impl<'a> State<'a> { ast::PatVec(ref before, ref slice, ref after) => { try!(word(&mut self.s, "[")); try!(self.commasep(Inconsistent, - before.as_slice(), + before[], |s, p| s.print_pat(&**p))); for p in slice.iter() { if !before.is_empty() { try!(self.word_space(",")); } @@ -2135,11 +2133,11 @@ impl<'a> State<'a> { if !after.is_empty() { try!(self.word_space(",")); } } try!(self.commasep(Inconsistent, - after.as_slice(), + after[], |s, p| s.print_pat(&**p))); try!(word(&mut self.s, "]")); } - ast::PatMac(ref m) => try!(self.print_mac(m)), + ast::PatMac(ref m) => try!(self.print_mac(m, token::Paren)), } self.ann.post(self, NodePat(pat)) } @@ -2152,7 +2150,7 @@ impl<'a> State<'a> { } try!(self.cbox(indent_unit)); try!(self.ibox(0u)); - try!(self.print_outer_attributes(arm.attrs.as_slice())); + try!(self.print_outer_attributes(arm.attrs[])); let mut first = true; for p in arm.pats.iter() { if first { @@ -2164,21 +2162,22 @@ impl<'a> State<'a> { try!(self.print_pat(&**p)); } try!(space(&mut self.s)); - match arm.guard { - Some(ref e) => { - try!(self.word_space("if")); - try!(self.print_expr(&**e)); - try!(space(&mut self.s)); - } - None => () + if let Some(ref e) = arm.guard { + try!(self.word_space("if")); + try!(self.print_expr(&**e)); + try!(space(&mut self.s)); } try!(self.word_space("=>")); match arm.body.node { ast::ExprBlock(ref blk) => { // the block will close the pattern's ibox - try!(self.print_block_unclosed_indent(&**blk, - indent_unit)); + try!(self.print_block_unclosed_indent(&**blk, indent_unit)); + + // If it is a user-provided unsafe block, print a comma after it + if let ast::UnsafeBlock(ast::UserProvided) = blk.rules { + try!(word(&mut self.s, ",")); + } } _ => { try!(self.end()); // close the ibox for the pattern @@ -2216,18 +2215,18 @@ impl<'a> State<'a> { pub fn print_fn(&mut self, decl: &ast::FnDecl, - fn_style: Option<ast::FnStyle>, + unsafety: Option<ast::Unsafety>, abi: abi::Abi, name: ast::Ident, generics: &ast::Generics, opt_explicit_self: Option<&ast::ExplicitSelf_>, vis: ast::Visibility) -> IoResult<()> { try!(self.head("")); - try!(self.print_fn_header_info(opt_explicit_self, fn_style, abi, vis)); + try!(self.print_fn_header_info(opt_explicit_self, unsafety, abi, vis)); try!(self.nbsp()); try!(self.print_ident(name)); try!(self.print_generics(generics)); - try!(self.print_fn_args_and_ret(decl, opt_explicit_self)) + try!(self.print_fn_args_and_ret(decl, opt_explicit_self)); self.print_where_clause(generics) } @@ -2251,7 +2250,7 @@ impl<'a> State<'a> { // HACK(eddyb) ignore the separately printed self argument. let args = if first { - decl.inputs.as_slice() + decl.inputs[] } else { decl.inputs.slice_from(1) }; @@ -2348,7 +2347,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)); @@ -2413,13 +2412,13 @@ impl<'a> State<'a> { ints.push(i); } - try!(self.commasep(Inconsistent, ints.as_slice(), |s, &idx| { + try!(self.commasep(Inconsistent, ints[], |s, &idx| { if idx < generics.lifetimes.len() { let lifetime = &generics.lifetimes[idx]; 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) } })); @@ -2429,15 +2428,12 @@ impl<'a> State<'a> { } pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> { - match param.unbound { - Some(ref tref) => { - try!(self.print_trait_ref(tref)); - try!(self.word_space("?")); - } - _ => {} + if let Some(ref tref) = param.unbound { + try!(self.print_trait_ref(tref)); + try!(self.word_space("?")); } try!(self.print_ident(param.ident)); - try!(self.print_bounds(":", ¶m.bounds)); + try!(self.print_bounds(":", param.bounds[])); match param.default { Some(ref default) => { try!(space(&mut self.s)); @@ -2465,8 +2461,34 @@ impl<'a> State<'a> { try!(self.word_space(",")); } - try!(self.print_ident(predicate.ident)); - try!(self.print_bounds(":", &predicate.bounds)); + match predicate { + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounded_ty, + ref bounds, + ..}) => { + try!(self.print_type(&**bounded_ty)); + try!(self.print_bounds(":", bounds.as_slice())); + } + &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, + ref bounds, + ..}) => { + try!(self.print_lifetime(lifetime)); + try!(word(&mut self.s, ":")); + + for (i, bound) in bounds.iter().enumerate() { + try!(self.print_lifetime(bound)); + + if i != 0 { + try!(word(&mut self.s, ":")); + } + } + } + &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => { + try!(self.print_path(path, false)); + try!(space(&mut self.s)); + try!(self.word_space("=")); + try!(self.print_type(&**ty)); + } + } } Ok(()) @@ -2487,7 +2509,7 @@ impl<'a> State<'a> { try!(word(&mut self.s, name.get())); try!(self.popen()); try!(self.commasep(Consistent, - items.as_slice(), + items[], |s, i| s.print_meta_item(&**i))); try!(self.pclose()); } @@ -2523,7 +2545,7 @@ impl<'a> State<'a> { try!(self.print_path(path, false)); try!(word(&mut self.s, "::{")); } - try!(self.commasep(Inconsistent, idents.as_slice(), |s, w| { + try!(self.commasep(Inconsistent, idents[], |s, w| { match w.node { ast::PathListIdent { name, .. } => { s.print_ident(name) @@ -2541,7 +2563,7 @@ impl<'a> State<'a> { pub fn print_view_item(&mut self, item: &ast::ViewItem) -> IoResult<()> { try!(self.hardbreak_if_not_bol()); try!(self.maybe_print_comment(item.span.lo)); - try!(self.print_outer_attributes(item.attrs.as_slice())); + try!(self.print_outer_attributes(item.attrs[])); try!(self.print_visibility(item.vis)); match item.node { ast::ViewItemExternCrate(id, ref optional_path, _) => { @@ -2631,7 +2653,7 @@ impl<'a> State<'a> { pub fn print_ty_fn(&mut self, opt_abi: Option<abi::Abi>, opt_sigil: Option<char>, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, onceness: ast::Onceness, decl: &ast::FnDecl, id: Option<ast::Ident>, @@ -2646,11 +2668,11 @@ impl<'a> State<'a> { if opt_sigil == Some('~') && onceness == ast::Once { try!(word(&mut self.s, "proc")); } else if opt_sigil == Some('&') { - try!(self.print_fn_style(fn_style)); + try!(self.print_unsafety(unsafety)); try!(self.print_extern_opt_abi(opt_abi)); } else { assert!(opt_sigil.is_none()); - try!(self.print_fn_style(fn_style)); + try!(self.print_unsafety(unsafety)); try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi)); try!(word(&mut self.s, "fn")); } @@ -2683,7 +2705,7 @@ impl<'a> State<'a> { try!(self.pclose()); } - try!(self.print_bounds(":", bounds)); + try!(self.print_bounds(":", bounds[])); try!(self.print_fn_output(decl)); @@ -2742,7 +2764,7 @@ impl<'a> State<'a> { try!(self.maybe_print_comment(lit.span.lo)); match self.next_lit(lit.span.lo) { Some(ref ltrl) => { - return word(&mut self.s, (*ltrl).lit.as_slice()); + return word(&mut self.s, (*ltrl).lit[]); } _ => () } @@ -2752,7 +2774,7 @@ impl<'a> State<'a> { let mut res = String::from_str("b'"); ascii::escape_default(byte, |c| res.push(c as char)); res.push('\''); - word(&mut self.s, res.as_slice()) + word(&mut self.s, res[]) } ast::LitChar(ch) => { let mut res = String::from_str("'"); @@ -2760,27 +2782,27 @@ impl<'a> State<'a> { res.push(c); } res.push('\''); - word(&mut self.s, res.as_slice()) + word(&mut self.s, res[]) } ast::LitInt(i, t) => { match t { ast::SignedIntLit(st, ast::Plus) => { word(&mut self.s, - ast_util::int_ty_to_string(st, Some(i as i64)).as_slice()) + ast_util::int_ty_to_string(st, Some(i as i64))[]) } ast::SignedIntLit(st, ast::Minus) => { let istr = ast_util::int_ty_to_string(st, Some(-(i as i64))); word(&mut self.s, - format!("-{}", istr).as_slice()) + format!("-{}", istr)[]) } ast::UnsignedIntLit(ut) => { - word(&mut self.s, ast_util::uint_ty_to_string(ut, Some(i)).as_slice()) + word(&mut self.s, ast_util::uint_ty_to_string(ut, Some(i))[]) } ast::UnsuffixedIntLit(ast::Plus) => { - word(&mut self.s, format!("{}", i).as_slice()) + word(&mut self.s, format!("{}", i)[]) } ast::UnsuffixedIntLit(ast::Minus) => { - word(&mut self.s, format!("-{}", i).as_slice()) + word(&mut self.s, format!("-{}", i)[]) } } } @@ -2789,7 +2811,7 @@ impl<'a> State<'a> { format!( "{}{}", f.get(), - ast_util::float_ty_to_string(t).as_slice()).as_slice()) + ast_util::float_ty_to_string(t)[])[]) } ast::LitFloatUnsuffixed(ref f) => word(&mut self.s, f.get()), ast::LitBool(val) => { @@ -2801,7 +2823,7 @@ impl<'a> State<'a> { ascii::escape_default(ch as u8, |ch| escaped.push(ch as char)); } - word(&mut self.s, format!("b\"{}\"", escaped).as_slice()) + word(&mut self.s, format!("b\"{}\"", escaped)[]) } } } @@ -2842,7 +2864,7 @@ impl<'a> State<'a> { comments::Mixed => { assert_eq!(cmnt.lines.len(), 1u); try!(zerobreak(&mut self.s)); - try!(word(&mut self.s, cmnt.lines[0].as_slice())); + try!(word(&mut self.s, cmnt.lines[0][])); zerobreak(&mut self.s) } comments::Isolated => { @@ -2851,7 +2873,7 @@ impl<'a> State<'a> { // Don't print empty lines because they will end up as trailing // whitespace if !line.is_empty() { - try!(word(&mut self.s, line.as_slice())); + try!(word(&mut self.s, line[])); } try!(hardbreak(&mut self.s)); } @@ -2860,13 +2882,13 @@ impl<'a> State<'a> { comments::Trailing => { try!(word(&mut self.s, " ")); if cmnt.lines.len() == 1u { - try!(word(&mut self.s, cmnt.lines[0].as_slice())); + try!(word(&mut self.s, cmnt.lines[0][])); hardbreak(&mut self.s) } else { try!(self.ibox(0u)); for line in cmnt.lines.iter() { if !line.is_empty() { - try!(word(&mut self.s, line.as_slice())); + try!(word(&mut self.s, line[])); } try!(hardbreak(&mut self.s)); } @@ -2876,7 +2898,7 @@ impl<'a> State<'a> { comments::BlankLine => { // We need to do at least one, possibly two hardbreaks. let is_semi = match self.s.last_token() { - pp::String(s, _) => ";" == s.as_slice(), + pp::String(s, _) => ";" == s, _ => false }; if is_semi || self.is_begin() || self.is_end() { @@ -2895,11 +2917,11 @@ impl<'a> State<'a> { } ast::RawStr(n) => { (format!("r{delim}\"{string}\"{delim}", - delim="#".repeat(n), + delim=repeat("#", n), string=st)) } }; - word(&mut self.s, st.as_slice()) + word(&mut self.s, st[]) } pub fn next_comment(&mut self) -> Option<comments::Comment> { @@ -2915,10 +2937,10 @@ impl<'a> State<'a> { } } - pub fn print_opt_fn_style(&mut self, - opt_fn_style: Option<ast::FnStyle>) -> IoResult<()> { - match opt_fn_style { - Some(fn_style) => self.print_fn_style(fn_style), + pub fn print_opt_unsafety(&mut self, + opt_unsafety: Option<ast::Unsafety>) -> IoResult<()> { + match opt_unsafety { + Some(unsafety) => self.print_unsafety(unsafety), None => Ok(()) } } @@ -2930,7 +2952,7 @@ impl<'a> State<'a> { Some(abi::Rust) => Ok(()), Some(abi) => { try!(self.word_nbsp("extern")); - self.word_nbsp(abi.to_string().as_slice()) + self.word_nbsp(abi.to_string()[]) } None => Ok(()) } @@ -2941,7 +2963,7 @@ impl<'a> State<'a> { match opt_abi { Some(abi) => { try!(self.word_nbsp("extern")); - self.word_nbsp(abi.to_string().as_slice()) + self.word_nbsp(abi.to_string()[]) } None => Ok(()) } @@ -2949,28 +2971,30 @@ impl<'a> State<'a> { pub fn print_fn_header_info(&mut self, _opt_explicit_self: Option<&ast::ExplicitSelf_>, - opt_fn_style: Option<ast::FnStyle>, + opt_unsafety: Option<ast::Unsafety>, abi: abi::Abi, vis: ast::Visibility) -> IoResult<()> { try!(word(&mut self.s, visibility_qualified(vis, "").as_slice())); - try!(self.print_opt_fn_style(opt_fn_style)); + try!(self.print_opt_unsafety(opt_unsafety)); if abi != abi::Rust { try!(self.word_nbsp("extern")); - try!(self.word_nbsp(abi.to_string().as_slice())); + try!(self.word_nbsp(abi.to_string()[])); } word(&mut self.s, "fn") } - pub fn print_fn_style(&mut self, s: ast::FnStyle) -> IoResult<()> { + pub fn print_unsafety(&mut self, s: ast::Unsafety) -> IoResult<()> { match s { - ast::NormalFn => Ok(()), - ast::UnsafeFn => self.word_nbsp("unsafe"), + ast::Unsafety::Normal => Ok(()), + ast::Unsafety::Unsafe => self.word_nbsp("unsafe"), } } } +fn repeat(s: &str, n: uint) -> String { iter::repeat(s).take(n).collect() } + #[cfg(test)] mod test { use super::*; @@ -2993,9 +3017,9 @@ mod test { variadic: false }; let generics = ast_util::empty_generics(); - assert_eq!(&fun_to_string(&decl, ast::NormalFn, abba_ident, + assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal, abba_ident, None, &generics), - &"fn abba()".to_string()); + "fn abba()"); } #[test] @@ -3013,7 +3037,7 @@ mod test { }); let varstr = variant_to_string(&var); - assert_eq!(&varstr,&"pub principal_skinner".to_string()); + assert_eq!(varstr, "pub principal_skinner"); } #[test] diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 1b231ed861b..1b3ebde2461 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -56,12 +56,16 @@ pub fn P<T: 'static>(value: T) -> P<T> { impl<T: 'static> P<T> { /// Move out of the pointer. /// Intended for chaining transformations not covered by `map`. - pub fn and_then<U>(self, f: |T| -> U) -> U { + pub fn and_then<U, F>(self, f: F) -> U where + F: FnOnce(T) -> U, + { f(*self.ptr) } /// Transform the inner value, consuming `self` and producing a new `P<T>`. - pub fn map(mut self, f: |T| -> T) -> P<T> { + pub fn map<F>(mut self, f: F) -> P<T> where + F: FnOnce(T) -> T, + { unsafe { let p = &mut *self.ptr; // FIXME(#5016) this shouldn't need to zero to be safe. diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index e98be046586..e1c8ff5011b 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -40,7 +40,7 @@ pub fn maybe_inject_prelude(krate: ast::Crate) -> ast::Crate { } fn use_std(krate: &ast::Crate) -> bool { - !attr::contains_name(krate.attrs.as_slice(), "no_std") + !attr::contains_name(krate.attrs[], "no_std") } fn no_prelude(attrs: &[ast::Attribute]) -> bool { @@ -56,7 +56,7 @@ impl<'a> fold::Folder for StandardLibraryInjector<'a> { // The name to use in `extern crate "name" as std;` let actual_crate_name = match self.alt_std_name { - Some(ref s) => token::intern_and_get_ident(s.as_slice()), + Some(ref s) => token::intern_and_get_ident(s[]), None => token::intern_and_get_ident("std"), }; @@ -118,7 +118,7 @@ impl<'a> fold::Folder for PreludeInjector<'a> { attr::mark_used(&no_std_attr); krate.attrs.push(no_std_attr); - if !no_prelude(krate.attrs.as_slice()) { + if !no_prelude(krate.attrs[]) { // only add `use std::prelude::*;` if there wasn't a // `#![no_implicit_prelude]` at the crate level. // fold_mod() will insert glob path. @@ -138,7 +138,7 @@ impl<'a> fold::Folder for PreludeInjector<'a> { } fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> { - if !no_prelude(item.attrs.as_slice()) { + if !no_prelude(item.attrs[]) { // only recur if there wasn't `#![no_implicit_prelude]` // on this item, i.e. this means that the prelude is not // implicitly imported though the whole subtree diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index f21a3185d6d..bc7dda8c44a 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -37,12 +37,17 @@ use {ast, ast_util}; use ptr::P; use util::small_vector::SmallVector; +enum ShouldFail { + No, + Yes(Option<InternedString>), +} + struct Test { span: Span, path: Vec<ast::Ident> , bench: bool, ignore: bool, - should_fail: bool + should_fail: ShouldFail } struct TestCtxt<'a> { @@ -68,14 +73,14 @@ pub fn modify_for_testing(sess: &ParseSess, // We generate the test harness when building in the 'test' // configuration, either with the '--test' or '--cfg test' // command line options. - let should_test = attr::contains_name(krate.config.as_slice(), "test"); + let should_test = attr::contains_name(krate.config[], "test"); // Check for #[reexport_test_harness_main = "some_name"] which // creates a `use some_name = __test::main;`. This needs to be // unconditional, so that the attribute is still marked as used in // non-test builds. let reexport_test_harness_main = - attr::first_attr_value_str_by_name(krate.attrs.as_slice(), + attr::first_attr_value_str_by_name(krate.attrs[], "reexport_test_harness_main"); if should_test { @@ -114,11 +119,11 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> { self.cx.path.push(ident); } debug!("current path: {}", - ast_util::path_name_i(self.cx.path.as_slice())); + ast_util::path_name_i(self.cx.path[])); if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) { match i.node { - ast::ItemFn(_, ast::UnsafeFn, _, _, _) => { + ast::ItemFn(_, ast::Unsafety::Unsafe, _, _, _) => { let diag = self.cx.span_diagnostic; diag.span_fatal(i.span, "unsafe functions cannot be used for \ @@ -272,8 +277,8 @@ fn strip_test_functions(krate: ast::Crate) -> ast::Crate { // When not compiling with --test we should not compile the // #[test] functions config::strip_items(krate, |attrs| { - !attr::contains_name(attrs.as_slice(), "test") && - !attr::contains_name(attrs.as_slice(), "bench") + !attr::contains_name(attrs[], "test") && + !attr::contains_name(attrs[], "bench") }) } @@ -286,7 +291,7 @@ enum HasTestSignature { fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { - let has_test_attr = attr::contains_name(i.attrs.as_slice(), "test"); + let has_test_attr = attr::contains_name(i.attrs[], "test"); fn has_test_signature(i: &ast::Item) -> HasTestSignature { match &i.node { @@ -324,7 +329,7 @@ fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool { } fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool { - let has_bench_attr = attr::contains_name(i.attrs.as_slice(), "bench"); + let has_bench_attr = attr::contains_name(i.attrs[], "bench"); fn has_test_signature(i: &ast::Item) -> bool { match i.node { @@ -360,8 +365,16 @@ fn is_ignored(i: &ast::Item) -> bool { i.attrs.iter().any(|attr| attr.check_name("ignore")) } -fn should_fail(i: &ast::Item) -> bool { - attr::contains_name(i.attrs.as_slice(), "should_fail") +fn should_fail(i: &ast::Item) -> ShouldFail { + match i.attrs.iter().find(|attr| attr.check_name("should_fail")) { + Some(attr) => { + let msg = attr.meta_item_list() + .and_then(|list| list.iter().find(|mi| mi.check_name("expected"))) + .and_then(|mi| mi.value_str()); + ShouldFail::Yes(msg) + } + None => ShouldFail::No, + } } /* @@ -371,7 +384,7 @@ We're going to be building a module that looks more or less like: mod __test { extern crate test (name = "test", vers = "..."); fn main() { - test::test_main_static(::os::args().as_slice(), tests) + test::test_main_static(::os::args()[], tests) } static tests : &'static [test::TestDescAndFn] = &[ @@ -482,8 +495,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, @@ -498,8 +510,8 @@ fn mk_tests(cx: &TestCtxt) -> P<ast::Item> { } fn is_test_crate(krate: &ast::Crate) -> bool { - match attr::find_crate_name(krate.attrs.as_slice()) { - Some(ref s) if "test" == s.get().as_slice() => true, + match attr::find_crate_name(krate.attrs[]) { + Some(ref s) if "test" == s.get()[] => true, _ => false } } @@ -539,11 +551,11 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> { // creates $name: $expr let field = |name, expr| ecx.field_imm(span, ecx.ident_of(name), expr); - debug!("encoding {}", ast_util::path_name_i(path.as_slice())); + debug!("encoding {}", ast_util::path_name_i(path[])); // path to the #[test] function: "foo::bar::baz" - let path_string = ast_util::path_name_i(path.as_slice()); - let name_expr = ecx.expr_str(span, token::intern_and_get_ident(path_string.as_slice())); + let path_string = ast_util::path_name_i(path[]); + let name_expr = ecx.expr_str(span, token::intern_and_get_ident(path_string[])); // self::test::StaticTestName($name_expr) let name_expr = ecx.expr_call(span, @@ -551,7 +563,20 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> { vec![name_expr]); let ignore_expr = ecx.expr_bool(span, test.ignore); - let fail_expr = ecx.expr_bool(span, test.should_fail); + let should_fail_path = |name| { + ecx.path(span, vec![self_id, test_id, ecx.ident_of("ShouldFail"), ecx.ident_of(name)]) + }; + let fail_expr = match test.should_fail { + ShouldFail::No => ecx.expr_path(should_fail_path("No")), + ShouldFail::Yes(ref msg) => { + let path = should_fail_path("Yes"); + let arg = match *msg { + Some(ref msg) => ecx.expr_some(span, ecx.expr_str(span, msg.clone())), + None => ecx.expr_none(span), + }; + ecx.expr_call(span, ecx.expr_path(path), vec![arg]) + } + }; // self::test::TestDesc { ... } let desc_expr = ecx.expr_struct( diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index ede967bba25..97eb4316583 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -95,41 +95,37 @@ pub struct RcStr { string: Rc<String>, } +impl RcStr { + pub fn new(string: &str) -> RcStr { + RcStr { + string: Rc::new(string.to_string()), + } + } +} + impl Eq for RcStr {} impl Ord for RcStr { fn cmp(&self, other: &RcStr) -> Ordering { - self.as_slice().cmp(other.as_slice()) - } -} - -impl Str for RcStr { - #[inline] - fn as_slice<'a>(&'a self) -> &'a str { - let s: &'a str = self.string.as_slice(); - s + self[].cmp(other[]) } } impl fmt::Show for RcStr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use std::fmt::Show; - self.as_slice().fmt(f) + self[].fmt(f) } } impl BorrowFrom<RcStr> for str { fn borrow_from(owned: &RcStr) -> &str { - owned.string.as_slice() + owned.string[] } } -impl RcStr { - pub fn new(string: &str) -> RcStr { - RcStr { - string: Rc::new(string.into_string()), - } - } +impl Deref<str> for RcStr { + fn deref(&self) -> &str { self.string[] } } /// A StrInterner differs from Interner<String> in that it accepts @@ -214,6 +210,11 @@ impl StrInterner { *self.map.borrow_mut() = HashMap::new(); *self.vect.borrow_mut() = Vec::new(); } + + pub fn reset(&self, other: StrInterner) { + *self.map.borrow_mut() = other.map.into_inner(); + *self.vect.borrow_mut() = other.vect.into_inner(); + } } #[cfg(test)] diff --git a/src/libsyntax/util/parser_testing.rs b/src/libsyntax/util/parser_testing.rs index c1ea8f60b82..83bbff8473d 100644 --- a/src/libsyntax/util/parser_testing.rs +++ b/src/libsyntax/util/parser_testing.rs @@ -31,7 +31,9 @@ pub fn string_to_parser<'a>(ps: &'a ParseSess, source_str: String) -> Parser<'a> source_str) } -fn with_error_checking_parse<T>(s: String, f: |&mut Parser| -> T) -> T { +fn with_error_checking_parse<T, F>(s: String, f: F) -> T where + F: FnOnce(&mut Parser) -> T, +{ let ps = new_parse_sess(); let mut p = string_to_parser(&ps, s); let x = f(&mut p); diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index c4b3288d44d..946181770c8 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. use self::SmallVectorRepr::*; -use self::MoveItemsRepr::*; +use self::IntoIterRepr::*; use std::mem; use std::slice; @@ -111,17 +111,17 @@ impl<T> SmallVector<T> { /// Deprecated: use `into_iter`. #[deprecated = "use into_iter"] - pub fn move_iter(self) -> MoveItems<T> { + pub fn move_iter(self) -> IntoIter<T> { self.into_iter() } - pub fn into_iter(self) -> MoveItems<T> { + pub fn into_iter(self) -> IntoIter<T> { let repr = match self.repr { Zero => ZeroIterator, One(v) => OneIterator(v), Many(vs) => ManyIterator(vs.into_iter()) }; - MoveItems { repr: repr } + IntoIter { repr: repr } } pub fn len(&self) -> uint { @@ -135,17 +135,17 @@ impl<T> SmallVector<T> { pub fn is_empty(&self) -> bool { self.len() == 0 } } -pub struct MoveItems<T> { - repr: MoveItemsRepr<T>, +pub struct IntoIter<T> { + repr: IntoIterRepr<T>, } -enum MoveItemsRepr<T> { +enum IntoIterRepr<T> { ZeroIterator, OneIterator(T), - ManyIterator(vec::MoveItems<T>), + ManyIterator(vec::IntoIter<T>), } -impl<T> Iterator<T> for MoveItems<T> { +impl<T> Iterator<T> for IntoIter<T> { fn next(&mut self) -> Option<T> { match self.repr { ZeroIterator => None, @@ -171,7 +171,7 @@ impl<T> Iterator<T> for MoveItems<T> { } impl<T> MoveMap<T> for SmallVector<T> { - fn move_map(self, f: |T| -> T) -> SmallVector<T> { + fn move_map<F>(self, mut f: F) -> SmallVector<T> where F: FnMut(T) -> T { let repr = match self.repr { Zero => Zero, One(v) => One(f(v)), @@ -224,10 +224,10 @@ mod test { assert_eq!(Vec::new(), v); let v = SmallVector::one(1i); - assert_eq!(vec!(1i), v.into_iter().collect()); + assert_eq!(vec!(1i), v.into_iter().collect::<Vec<_>>()); let v = SmallVector::many(vec!(1i, 2i, 3i)); - assert_eq!(vec!(1i, 2i, 3i), v.into_iter().collect()); + assert_eq!(vec!(1i, 2i, 3i), v.into_iter().collect::<Vec<_>>()); } #[test] diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index a0bdd739113..4cc93467a7c 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -32,9 +32,10 @@ use codemap::Span; use ptr::P; use owned_slice::OwnedSlice; +#[deriving(Copy)] pub enum FnKind<'a> { /// fn foo() or extern "Abi" fn foo() - FkItemFn(Ident, &'a Generics, FnStyle, Abi), + FkItemFn(Ident, &'a Generics, Unsafety, Abi), /// fn foo(&self) FkMethod(Ident, &'a Generics, &'a Method), @@ -92,21 +93,22 @@ 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 => () } } + fn visit_lifetime_bound(&mut self, lifetime: &'v Lifetime) { + walk_lifetime_bound(self, lifetime) + } fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) { - self.visit_name(lifetime.span, lifetime.name) + walk_lifetime_ref(self, lifetime) } fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) { walk_lifetime_def(self, lifetime) @@ -214,10 +216,20 @@ pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V, lifetime_def: &'v LifetimeDef) { visitor.visit_name(lifetime_def.lifetime.span, lifetime_def.lifetime.name); for bound in lifetime_def.bounds.iter() { - visitor.visit_lifetime_ref(bound); + visitor.visit_lifetime_bound(bound); } } +pub fn walk_lifetime_bound<'v, V: Visitor<'v>>(visitor: &mut V, + lifetime_ref: &'v Lifetime) { + visitor.visit_lifetime_ref(lifetime_ref) +} + +pub fn walk_lifetime_ref<'v, V: Visitor<'v>>(visitor: &mut V, + lifetime_ref: &'v Lifetime) { + visitor.visit_name(lifetime_ref.span, lifetime_ref.name) +} + pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V, explicit_self: &'v ExplicitSelf) { match explicit_self.node { @@ -282,7 +294,8 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_generics(type_parameters); walk_enum_def(visitor, enum_definition, type_parameters) } - ItemImpl(ref type_parameters, + ItemImpl(_, + ref type_parameters, ref trait_reference, ref typ, ref impl_items) => { @@ -311,7 +324,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { generics, item.id) } - ItemTrait(ref generics, _, ref bounds, ref methods) => { + ItemTrait(_, ref generics, _, ref bounds, ref methods) => { visitor.visit_generics(generics); walk_ty_param_bounds_helper(visitor, bounds); for method in methods.iter() { @@ -389,14 +402,6 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) { walk_ty_param_bounds_helper(visitor, &function_declaration.bounds); walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); } - TyProc(ref function_declaration) => { - for argument in function_declaration.decl.inputs.iter() { - visitor.visit_ty(&*argument.ty) - } - walk_fn_ret_ty(visitor, &function_declaration.decl.output); - walk_ty_param_bounds_helper(visitor, &function_declaration.bounds); - walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes); - } TyBareFn(ref function_declaration) => { for argument in function_declaration.decl.inputs.iter() { visitor.visit_ty(&*argument.ty) @@ -404,14 +409,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); @@ -559,24 +562,50 @@ pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, visitor.visit_poly_trait_ref(typ); } RegionTyParamBound(ref lifetime) => { - visitor.visit_lifetime_ref(lifetime); + visitor.visit_lifetime_bound(lifetime); } } } +pub fn walk_ty_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v TyParam) { + visitor.visit_ident(param.span, param.ident); + walk_ty_param_bounds_helper(visitor, ¶m.bounds); + match param.default { + Some(ref ty) => visitor.visit_ty(&**ty), + None => {} + } +} + pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics) { for type_parameter in generics.ty_params.iter() { - visitor.visit_ident(type_parameter.span, type_parameter.ident); - walk_ty_param_bounds_helper(visitor, &type_parameter.bounds); - match type_parameter.default { - Some(ref ty) => visitor.visit_ty(&**ty), - None => {} - } + walk_ty_param(visitor, type_parameter); } walk_lifetime_decls_helper(visitor, &generics.lifetimes); for predicate in generics.where_clause.predicates.iter() { - visitor.visit_ident(predicate.span, predicate.ident); - walk_ty_param_bounds_helper(visitor, &predicate.bounds); + match predicate { + &ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bounded_ty, + ref bounds, + ..}) => { + visitor.visit_ty(&**bounded_ty); + walk_ty_param_bounds_helper(visitor, bounds); + } + &ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime, + ref bounds, + ..}) => { + visitor.visit_lifetime_ref(lifetime); + + for bound in bounds.iter() { + visitor.visit_lifetime_ref(bound); + } + } + &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, + ref path, + ref ty, + ..}) => { + visitor.visit_path(path, id); + visitor.visit_ty(&**ty); + } + } } } @@ -660,8 +689,7 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_method: &'v Tr RequiredMethod(ref method_type) => visitor.visit_ty_method(method_type), ProvidedMethod(ref method) => walk_method_helper(visitor, &**method), TypeTraitItem(ref associated_type) => { - visitor.visit_ident(associated_type.ty_param.span, - associated_type.ty_param.ident) + walk_ty_param(visitor, &associated_type.ty_param); } } } @@ -675,11 +703,8 @@ pub fn walk_struct_def<'v, V: Visitor<'v>>(visitor: &mut V, pub fn walk_struct_field<'v, V: Visitor<'v>>(visitor: &mut V, struct_field: &'v StructField) { - match struct_field.node.kind { - NamedField(name, _) => { - visitor.visit_ident(struct_field.span, name) - } - _ => {} + if let NamedField(name, _) = struct_field.node.kind { + visitor.visit_ident(struct_field.span, name); } visitor.visit_ty(&*struct_field.node.ty); @@ -737,7 +762,7 @@ pub fn walk_mac<'v, V: Visitor<'v>>(_: &mut V, _: &'v Mac) { pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { match expression.node { ExprBox(ref place, ref subexpression) => { - visitor.visit_expr(&**place); + place.as_ref().map(|e|visitor.visit_expr(&**e)); visitor.visit_expr(&**subexpression) } ExprVec(ref subexpressions) => { @@ -822,13 +847,6 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { expression.span, expression.id) } - ExprProc(ref function_declaration, ref body) => { - visitor.visit_fn(FkFnBlock, - &**function_declaration, - &**body, - expression.span, - expression.id) - } ExprBlock(ref block) => visitor.visit_block(&**block), ExprAssign(ref left_hand_expression, ref right_hand_expression) => { visitor.visit_expr(&**right_hand_expression); @@ -838,17 +856,11 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_expr(&**right_expression); visitor.visit_expr(&**left_expression) } - ExprField(ref subexpression, _, ref types) => { + ExprField(ref subexpression, _) => { visitor.visit_expr(&**subexpression); - for typ in types.iter() { - visitor.visit_ty(&**typ) - } } - ExprTupField(ref subexpression, _, ref types) => { + ExprTupField(ref subexpression, _) => { visitor.visit_expr(&**subexpression); - for typ in types.iter() { - visitor.visit_ty(&**typ) - } } ExprIndex(ref main_expression, ref index_expression) => { visitor.visit_expr(&**main_expression); @@ -859,6 +871,10 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { walk_expr_opt(visitor, start); walk_expr_opt(visitor, end) } + ExprRange(ref start, ref end) => { + visitor.visit_expr(&**start); + walk_expr_opt(visitor, end) + } ExprPath(ref path) => { visitor.visit_path(path, expression.id) } |
