about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-05-13 18:31:51 -0700
committerbors <bors@rust-lang.org>2014-05-13 18:31:51 -0700
commitb2b383cab5959b1ec331e1d77583fa944b7fd593 (patch)
tree79540b4f5f7e125a260b9ca00f25e796241425f9 /src/libsyntax
parentcb115ac2d4f57d8b590c8d46d8f9e2958ed9a527 (diff)
parentf09592a5d154177f0c9d739c9fe60742ec4cd951 (diff)
downloadrust-b2b383cab5959b1ec331e1d77583fa944b7fd593.tar.gz
rust-b2b383cab5959b1ec331e1d77583fa944b7fd593.zip
auto merge of #14187 : alexcrichton/rust/rollup, r=alexcrichton
Closes #14184 (std: Move the owned module from core to std)
Closes #14183 (Allow blocks in const expressions)
Closes #14176 (Add tests for from_bits.)
Closes #14175 (Replaced ~T by Box<T> in manual)
Closes #14173 (Implements Default trait for BigInt and BigUint)
Closes #14171 (Fix #8391)
Closes #14159 (Clean up unicode code in libstd)
Closes #14126 (docs: Add a not found page)
Closes #14123 (add a line to the example to clarify semantics)
Closes #14106 (Pretty printer improvements)
Closes #14083 (rustllvm: Add LLVMRustArrayType)
Closes #13957 (io: Implement process wait timeouts)
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs6
-rw-r--r--src/libsyntax/ast_util.rs24
-rw-r--r--src/libsyntax/ext/deriving/generic.rs36
-rw-r--r--src/libsyntax/ext/expand.rs18
-rw-r--r--src/libsyntax/parse/parser.rs63
-rw-r--r--src/libsyntax/parse/token.rs8
-rw-r--r--src/libsyntax/print/pprust.rs89
7 files changed, 179 insertions, 65 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 391116d2dbc..e5ef31a95a3 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -711,7 +711,8 @@ pub enum IntTy {
 
 impl fmt::Show for IntTy {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f.buf, "{}", ast_util::int_ty_to_str(*self, None))
+        write!(f.buf, "{}",
+               ast_util::int_ty_to_str(*self, None, ast_util::AutoSuffix))
     }
 }
 
@@ -726,7 +727,8 @@ pub enum UintTy {
 
 impl fmt::Show for UintTy {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f.buf, "{}", ast_util::uint_ty_to_str(*self, None))
+        write!(f.buf, "{}",
+               ast_util::uint_ty_to_str(*self, None, ast_util::AutoSuffix))
     }
 }
 
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 550b6603d5d..fb69e440b2f 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -132,11 +132,19 @@ pub fn is_path(e: @Expr) -> bool {
     return match e.node { ExprPath(_) => true, _ => false };
 }
 
+pub enum SuffixMode {
+    ForceSuffix,
+    AutoSuffix,
+}
+
 // Get a string representation of a signed int type, with its value.
 // We want to avoid "45int" and "-3int" in favor of "45" and "-3"
-pub fn int_ty_to_str(t: IntTy, val: Option<i64>) -> StrBuf {
+pub fn int_ty_to_str(t: IntTy, val: Option<i64>, mode: SuffixMode) -> StrBuf {
     let s = match t {
-        TyI if val.is_some() => "",
+        TyI if val.is_some() => match mode {
+            AutoSuffix => "",
+            ForceSuffix => "i",
+        },
         TyI => "int",
         TyI8 => "i8",
         TyI16 => "i16",
@@ -145,7 +153,10 @@ pub fn int_ty_to_str(t: IntTy, val: Option<i64>) -> StrBuf {
     };
 
     match val {
-        Some(n) => format!("{}{}", n, s).to_strbuf(),
+        // cast to a u64 so we can correctly print INT64_MIN. All integral types
+        // are parsed as u64, so we wouldn't want to print an extra negative
+        // sign.
+        Some(n) => format!("{}{}", n as u64, s).to_strbuf(),
         None => s.to_strbuf()
     }
 }
@@ -161,9 +172,12 @@ pub fn int_ty_max(t: IntTy) -> u64 {
 
 // Get a string representation of an unsigned int type, with its value.
 // We want to avoid "42uint" in favor of "42u"
-pub fn uint_ty_to_str(t: UintTy, val: Option<u64>) -> StrBuf {
+pub fn uint_ty_to_str(t: UintTy, val: Option<u64>, mode: SuffixMode) -> StrBuf {
     let s = match t {
-        TyU if val.is_some() => "u",
+        TyU if val.is_some() => match mode {
+            AutoSuffix => "",
+            ForceSuffix => "u",
+        },
         TyU => "uint",
         TyU8 => "u8",
         TyU16 => "u16",
diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs
index 9c967cfb4ee..6df4da89402 100644
--- a/src/libsyntax/ext/deriving/generic.rs
+++ b/src/libsyntax/ext/deriving/generic.rs
@@ -182,6 +182,7 @@ use std::cell::RefCell;
 use ast;
 use ast::{P, EnumDef, Expr, Ident, Generics, StructDef};
 use ast_util;
+use attr::AttrMetaMethods;
 use ext::base::ExtCtxt;
 use ext::build::AstBuilder;
 use codemap;
@@ -330,21 +331,34 @@ impl<'a> TraitDef<'a> {
                   _mitem: @ast::MetaItem,
                   item: @ast::Item,
                   push: |@ast::Item|) {
-        match item.node {
+        let newitem = match item.node {
             ast::ItemStruct(struct_def, ref generics) => {
-                push(self.expand_struct_def(cx,
-                                            struct_def,
-                                            item.ident,
-                                            generics));
+                self.expand_struct_def(cx,
+                                       struct_def,
+                                       item.ident,
+                                       generics)
             }
             ast::ItemEnum(ref enum_def, ref generics) => {
-                push(self.expand_enum_def(cx,
-                                          enum_def,
-                                          item.ident,
-                                          generics));
+                self.expand_enum_def(cx,
+                                     enum_def,
+                                     item.ident,
+                                     generics)
             }
-            _ => ()
-        }
+            _ => return
+        };
+        // Keep the lint attributes of the previous item to control how the
+        // generated implementations are linted
+        let mut attrs = newitem.attrs.clone();
+        attrs.extend(item.attrs.iter().filter(|a| {
+            match a.name().get() {
+                "allow" | "warn" | "deny" | "forbid" => true,
+                _ => false,
+            }
+        }).map(|a| a.clone()));
+        push(@ast::Item {
+            attrs: attrs,
+            ..(*newitem).clone()
+        })
     }
 
     /**
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 84525718bd9..1898e8bf000 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -156,7 +156,7 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
             //     }
             //   }
 
-            let local_ident = token::gensym_ident("i");
+            let local_ident = token::gensym_ident("__i"); // FIXME #13573
             let next_ident = fld.cx.ident_of("next");
             let none_ident = fld.cx.ident_of("None");
 
@@ -262,7 +262,8 @@ pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander)
     let it = expand_item_modifiers(it, fld);
 
     let mut decorator_items = SmallVector::zero();
-    for attr in it.attrs.iter().rev() {
+    let mut new_attrs = Vec::new();
+    for attr in it.attrs.iter() {
         let mname = attr.name();
 
         match fld.extsbox.find(&intern(mname.get())) {
@@ -286,7 +287,7 @@ pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander)
 
                 fld.cx.bt_pop();
             }
-            _ => {}
+            _ => new_attrs.push((*attr).clone()),
         }
     }
 
@@ -294,14 +295,21 @@ pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander)
         ast::ItemMac(..) => expand_item_mac(it, fld),
         ast::ItemMod(_) | ast::ItemForeignMod(_) => {
             fld.cx.mod_push(it.ident);
-            let macro_escape = contains_macro_escape(it.attrs.as_slice());
+            let macro_escape = contains_macro_escape(new_attrs.as_slice());
             let result = with_exts_frame!(fld.extsbox,
                                           macro_escape,
                                           noop_fold_item(it, fld));
             fld.cx.mod_pop();
             result
         },
-        _ => noop_fold_item(it, fld)
+        _ => {
+            let it = @ast::Item {
+                attrs: new_attrs,
+                ..(*it).clone()
+
+            };
+            noop_fold_item(it, fld)
+        }
     };
 
     new_items.push_all(decorator_items);
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2201b08f2ca..92e5f8da6aa 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -587,16 +587,64 @@ impl<'a> Parser<'a> {
                 self.replace_token(token::BINOP(token::OR), lo, self.span.hi)
             }
             _ => {
-                let token_str = self.this_token_to_str();
-                let found_token =
+                let found_token = self.this_token_to_str();
+                let token_str =
                     Parser::token_to_str(&token::BINOP(token::OR));
                 self.fatal(format!("expected `{}`, found `{}`",
-                                   found_token,
-                                   token_str))
+                                   token_str, found_token))
             }
         }
     }
 
+    // Attempt to consume a `<`. If `<<` is seen, replace it with a single
+    // `<` and continue. If a `<` is not seen, return false.
+    //
+    // This is meant to be used when parsing generics on a path to get the
+    // starting token. The `force` parameter is used to forcefully break up a
+    // `<<` token. If `force` is false, then `<<` is only broken when a lifetime
+    // shows up next. For example, consider the expression:
+    //
+    //      foo as bar << test
+    //
+    // The parser needs to know if `bar <<` is the start of a generic path or if
+    // it's a left-shift token. If `test` were a lifetime, then it's impossible
+    // for the token to be a left-shift, but if it's not a lifetime, then it's
+    // considered a left-shift.
+    //
+    // The reason for this is that the only current ambiguity with `<<` is when
+    // parsing closure types:
+    //
+    //      foo::<<'a> ||>();
+    //      impl Foo<<'a> ||>() { ... }
+    fn eat_lt(&mut self, force: bool) -> bool {
+        match self.token {
+            token::LT => { self.bump(); true }
+            token::BINOP(token::SHL) => {
+                let next_lifetime = self.look_ahead(1, |t| match *t {
+                    token::LIFETIME(..) => true,
+                    _ => false,
+                });
+                if force || next_lifetime {
+                    let lo = self.span.lo + BytePos(1);
+                    self.replace_token(token::LT, lo, self.span.hi);
+                    true
+                } else {
+                    false
+                }
+            }
+            _ => false,
+        }
+    }
+
+    fn expect_lt(&mut self) {
+        if !self.eat_lt(true) {
+            let found_token = self.this_token_to_str();
+            let token_str = Parser::token_to_str(&token::LT);
+            self.fatal(format!("expected `{}`, found `{}`",
+                               token_str, found_token))
+        }
+    }
+
     // Parse a sequence bracketed by `|` and `|`, stopping before the `|`.
     fn parse_seq_to_before_or<T>(
                               &mut self,
@@ -1500,7 +1548,7 @@ impl<'a> Parser<'a> {
 
             // Parse the `<` before the lifetime and types, if applicable.
             let (any_lifetime_or_types, lifetimes, types) = {
-                if mode != NoTypesAllowed && self.eat(&token::LT) {
+                if mode != NoTypesAllowed && self.eat_lt(false) {
                     let (lifetimes, types) =
                         self.parse_generic_values_after_lt();
                     (true, lifetimes, OwnedSlice::from_vec(types))
@@ -1948,7 +1996,7 @@ impl<'a> Parser<'a> {
                     hi = self.span.hi;
                     self.bump();
                     let (_, tys) = if self.eat(&token::MOD_SEP) {
-                        self.expect(&token::LT);
+                        self.expect_lt();
                         self.parse_generic_values_after_lt()
                     } else {
                         (Vec::new(), Vec::new())
@@ -2241,9 +2289,6 @@ impl<'a> Parser<'a> {
               ExprVec(..) if m == MutImmutable => {
                 ExprVstore(e, ExprVstoreSlice)
               }
-              ExprLit(lit) if lit_is_str(lit) && m == MutImmutable => {
-                ExprVstore(e, ExprVstoreSlice)
-              }
               ExprVec(..) if m == MutMutable => {
                 ExprVstore(e, ExprVstoreMutSlice)
               }
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index 3888ed6b8d1..68ce8cb2bc1 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -203,9 +203,11 @@ pub fn to_str(t: &Token) -> StrBuf {
           res.push_char('\'');
           res
       }
-      LIT_INT(i, t) => ast_util::int_ty_to_str(t, Some(i)),
-      LIT_UINT(u, t) => ast_util::uint_ty_to_str(t, Some(u)),
-      LIT_INT_UNSUFFIXED(i) => { i.to_str().to_strbuf() }
+      LIT_INT(i, t) => ast_util::int_ty_to_str(t, Some(i),
+                                               ast_util::ForceSuffix),
+      LIT_UINT(u, t) => ast_util::uint_ty_to_str(t, Some(u),
+                                                 ast_util::ForceSuffix),
+      LIT_INT_UNSUFFIXED(i) => { (i as u64).to_str().to_strbuf() }
       LIT_FLOAT(s, t) => {
         let mut body = StrBuf::from_str(get_ident(s).get());
         if body.as_slice().ends_with(".") {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 71c2f6337e0..15b931d5854 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -168,7 +168,7 @@ pub fn tt_to_str(tt: &ast::TokenTree) -> StrBuf {
 }
 
 pub fn tts_to_str(tts: &[ast::TokenTree]) -> StrBuf {
-    to_str(|s| s.print_tts(&tts))
+    to_str(|s| s.print_tts(tts))
 }
 
 pub fn stmt_to_str(stmt: &ast::Stmt) -> StrBuf {
@@ -247,6 +247,15 @@ pub fn visibility_qualified(vis: ast::Visibility, s: &str) -> StrBuf {
     }
 }
 
+fn needs_parentheses(expr: &ast::Expr) -> bool {
+    match expr.node {
+        ast::ExprAssign(..) | ast::ExprBinary(..) |
+        ast::ExprFnBlock(..) | ast::ExprProc(..) |
+        ast::ExprAssignOp(..) | ast::ExprCast(..) => true,
+        _ => false,
+    }
+}
+
 impl<'a> State<'a> {
     pub fn ibox(&mut self, u: uint) -> IoResult<()> {
         self.boxes.push(pp::Inconsistent);
@@ -714,7 +723,7 @@ 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.as_slice()));
                 try!(self.pclose());
                 try!(self.end());
             }
@@ -830,9 +839,15 @@ impl<'a> State<'a> {
     /// expression arguments as expressions). It can be done! I think.
     pub fn print_tt(&mut self, tt: &ast::TokenTree) -> IoResult<()> {
         match *tt {
-            ast::TTDelim(ref tts) => self.print_tts(&(tts.as_slice())),
+            ast::TTDelim(ref tts) => self.print_tts(tts.as_slice()),
             ast::TTTok(_, ref tk) => {
-                word(&mut self.s, parse::token::to_str(tk).as_slice())
+                try!(word(&mut self.s, parse::token::to_str(tk).as_slice()));
+                match *tk {
+                    parse::token::DOC_COMMENT(..) => {
+                        hardbreak(&mut self.s)
+                    }
+                    _ => Ok(())
+                }
             }
             ast::TTSeq(_, ref tts, ref sep, zerok) => {
                 try!(word(&mut self.s, "$("));
@@ -856,7 +871,7 @@ impl<'a> State<'a> {
         }
     }
 
-    pub fn print_tts(&mut self, tts: & &[ast::TokenTree]) -> IoResult<()> {
+    pub fn print_tts(&mut self, tts: &[ast::TokenTree]) -> IoResult<()> {
         try!(self.ibox(0));
         for (i, tt) in tts.iter().enumerate() {
             if i != 0 {
@@ -1113,7 +1128,7 @@ impl<'a> State<'a> {
                 try!(self.print_path(pth, false));
                 try!(word(&mut self.s, "!"));
                 try!(self.popen());
-                try!(self.print_tts(&tts.as_slice()));
+                try!(self.print_tts(tts.as_slice()));
                 self.pclose()
             }
         }
@@ -1136,6 +1151,18 @@ impl<'a> State<'a> {
         self.pclose()
     }
 
+    pub fn print_expr_maybe_paren(&mut self, expr: &ast::Expr) -> IoResult<()> {
+        let needs_par = needs_parentheses(expr);
+        if needs_par {
+            try!(self.popen());
+        }
+        try!(self.print_expr(expr));
+        if needs_par {
+            try!(self.pclose());
+        }
+        Ok(())
+    }
+
     pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> {
         try!(self.maybe_print_comment(expr.span.lo));
         try!(self.ibox(indent_unit));
@@ -1209,7 +1236,7 @@ impl<'a> State<'a> {
                 try!(self.pclose());
             }
             ast::ExprCall(func, ref args) => {
-                try!(self.print_expr(func));
+                try!(self.print_expr_maybe_paren(func));
                 try!(self.print_call_post(args.as_slice()));
             }
             ast::ExprMethodCall(ident, ref tys, ref args) => {
@@ -1233,17 +1260,12 @@ impl<'a> State<'a> {
             }
             ast::ExprUnary(op, expr) => {
                 try!(word(&mut self.s, ast_util::unop_to_str(op)));
-                try!(self.print_expr(expr));
+                try!(self.print_expr_maybe_paren(expr));
             }
             ast::ExprAddrOf(m, expr) => {
                 try!(word(&mut self.s, "&"));
                 try!(self.print_mutability(m));
-                // Avoid `& &e` => `&&e`.
-                match (m, &expr.node) {
-                    (ast::MutImmutable, &ast::ExprAddrOf(..)) => try!(space(&mut self.s)),
-                    _ => { }
-                }
-                try!(self.print_expr(expr));
+                try!(self.print_expr_maybe_paren(expr));
             }
             ast::ExprLit(lit) => try!(self.print_literal(lit)),
             ast::ExprCast(expr, ty) => {
@@ -1474,22 +1496,27 @@ impl<'a> State<'a> {
                 try!(self.popen());
                 try!(self.print_string(a.asm.get(), a.asm_str_style));
                 try!(self.word_space(":"));
-                for &(ref co, o) in a.outputs.iter() {
-                    try!(self.print_string(co.get(), ast::CookedStr));
-                    try!(self.popen());
-                    try!(self.print_expr(o));
-                    try!(self.pclose());
-                    try!(self.word_space(","));
-                }
+
+                try!(self.commasep(Inconsistent, a.outputs.as_slice(), |s, &(ref co, o)| {
+                    try!(s.print_string(co.get(), ast::CookedStr));
+                    try!(s.popen());
+                    try!(s.print_expr(o));
+                    try!(s.pclose());
+                    Ok(())
+                }));
+                try!(space(&mut self.s));
                 try!(self.word_space(":"));
-                for &(ref co, o) in a.inputs.iter() {
-                    try!(self.print_string(co.get(), ast::CookedStr));
-                    try!(self.popen());
-                    try!(self.print_expr(o));
-                    try!(self.pclose());
-                    try!(self.word_space(","));
-                }
+
+                try!(self.commasep(Inconsistent, a.inputs.as_slice(), |s, &(ref co, o)| {
+                    try!(s.print_string(co.get(), ast::CookedStr));
+                    try!(s.popen());
+                    try!(s.print_expr(o));
+                    try!(s.pclose());
+                    Ok(())
+                }));
+                try!(space(&mut self.s));
                 try!(self.word_space(":"));
+
                 try!(self.print_string(a.clobbers.get(), ast::CookedStr));
                 try!(self.pclose());
             }
@@ -2211,11 +2238,13 @@ impl<'a> State<'a> {
             }
             ast::LitInt(i, t) => {
                 word(&mut self.s,
-                     ast_util::int_ty_to_str(t, Some(i)).as_slice())
+                     ast_util::int_ty_to_str(t, Some(i),
+                                             ast_util::AutoSuffix).as_slice())
             }
             ast::LitUint(u, t) => {
                 word(&mut self.s,
-                     ast_util::uint_ty_to_str(t, Some(u)).as_slice())
+                     ast_util::uint_ty_to_str(t, Some(u),
+                                              ast_util::ForceSuffix).as_slice())
             }
             ast::LitIntUnsuffixed(i) => {
                 word(&mut self.s, format!("{}", i))