about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2017-07-05 08:42:13 -0700
committerAlex Crichton <alex@alexcrichton.com>2017-07-05 08:42:13 -0700
commitfd95db25b367d5d61ee9bc86b928c529747b3622 (patch)
treef93755558c3f91addb568e1f5aa4f2a4799589f5 /src/libsyntax
parentd316874c87e25669895c306658e15aa3746d66ab (diff)
parent692b5722363be2de18a27b46db59950124a5101d (diff)
downloadrust-fd95db25b367d5d61ee9bc86b928c529747b3622.tar.gz
rust-fd95db25b367d5d61ee9bc86b928c529747b3622.zip
Merge remote-tracking branch 'origin/master' into proc_macro_api
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs5
-rw-r--r--src/libsyntax/ext/build.rs11
-rw-r--r--src/libsyntax/ext/tt/quoted.rs4
-rw-r--r--src/libsyntax/feature_gate.rs14
-rw-r--r--src/libsyntax/parse/lexer/mod.rs2
-rw-r--r--src/libsyntax/parse/parser.rs50
-rw-r--r--src/libsyntax/parse/token.rs30
-rw-r--r--src/libsyntax/print/pprust.rs4
-rw-r--r--src/libsyntax/test.rs14
9 files changed, 75 insertions, 59 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 325a5cdf8fc..d00e29d954f 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -97,9 +97,8 @@ impl Path {
     }
 
     pub fn default_to_global(mut self) -> Path {
-        let name = self.segments[0].identifier.name;
-        if !self.is_global() && name != "$crate" &&
-           name != keywords::SelfValue.name() && name != keywords::Super.name() {
+        if !self.is_global() &&
+           !::parse::token::Ident(self.segments[0].identifier).is_path_segment_keyword() {
             self.segments.insert(0, PathSegment::crate_root(self.span));
         }
         self
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 5168943d108..1eb749623d8 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -11,7 +11,7 @@
 use abi::Abi;
 use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind};
 use attr;
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::{Pos, Span, DUMMY_SP};
 use codemap::{dummy_spanned, respan, Spanned};
 use ext::base::ExtCtxt;
 use ptr::P;
@@ -768,14 +768,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         let loc = self.codemap().lookup_char_pos(span.lo);
         let expr_file = self.expr_str(span, Symbol::intern(&loc.file.name));
         let expr_line = self.expr_u32(span, loc.line as u32);
-        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);
+        let expr_col = self.expr_u32(span, loc.col.to_usize() as u32 + 1);
+        let expr_loc_tuple = self.expr_tuple(span, vec![expr_file, expr_line, expr_col]);
+        let expr_loc_ptr = self.expr_addr_of(span, expr_loc_tuple);
         self.expr_call_global(
             span,
-            self.std_path(&["rt", "begin_panic"]),
+            self.std_path(&["rt", "begin_panic_new"]),
             vec![
                 self.expr_str(span, msg),
-                expr_file_line_ptr])
+                expr_loc_ptr])
     }
 
     fn expr_unreachable(&self, span: Span) -> P<ast::Expr> {
diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs
index 18056f60287..4e9e30857b1 100644
--- a/src/libsyntax/ext/tt/quoted.rs
+++ b/src/libsyntax/ext/tt/quoted.rs
@@ -12,7 +12,7 @@ use ast;
 use ext::tt::macro_parser;
 use parse::{ParseSess, token};
 use print::pprust;
-use symbol::{keywords, Symbol};
+use symbol::keywords;
 use syntax_pos::{DUMMY_SP, Span, BytePos};
 use tokenstream;
 
@@ -199,7 +199,7 @@ fn parse_tree<I>(tree: tokenstream::TokenTree,
             Some(tokenstream::TokenTree::Token(ident_span, token::Ident(ident))) => {
                 let span = Span { lo: span.lo, ..ident_span };
                 if ident.name == keywords::Crate.name() {
-                    let ident = ast::Ident { name: Symbol::intern("$crate"), ..ident };
+                    let ident = ast::Ident { name: keywords::DollarCrate.name(), ..ident };
                     TokenTree::Token(span, token::Ident(ident))
                 } else {
                     TokenTree::MetaVar(span, ident)
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 3f3c94536a6..4b0ec1a20e3 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -360,6 +360,12 @@ declare_features! (
 
     // rustc internal
     (active, abi_thiscall, "1.19.0", None),
+
+    // Allows a test to fail without failing the whole suite
+    (active, allow_fail, "1.19.0", Some(42219)),
+
+    // Allows unsized tuple coercion.
+    (active, unsized_tuple_coercion, "1.20.0", Some(42877)),
 );
 
 declare_features! (
@@ -818,6 +824,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                              "used internally by rustc",
                                              cfg_fn!(rustc_attrs))),
 
+    ("allow_fail", Normal, Gated(Stability::Unstable,
+                                 "allow_fail",
+                                 "allow_fail attribute is currently unstable",
+                                 cfg_fn!(allow_fail))),
+
     // Crate level attributes
     ("crate_name", CrateLevel, Ungated),
     ("crate_type", CrateLevel, Ungated),
@@ -1039,6 +1050,9 @@ pub const EXPLAIN_VIS_MATCHER: &'static str =
 pub const EXPLAIN_PLACEMENT_IN: &'static str =
     "placement-in expression syntax is experimental and subject to change.";
 
+pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str =
+    "Unsized tuple coercion is not stable enough for use and is subject to change";
+
 struct PostExpansionVisitor<'a> {
     context: &'a Context<'a>,
 }
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 66775d8c43d..09cdf26bf1f 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -1285,7 +1285,7 @@ impl<'a> StringReader<'a> {
                     });
                     let keyword_checking_token = &token::Ident(keyword_checking_ident);
                     let last_bpos = self.pos;
-                    if keyword_checking_token.is_any_keyword() &&
+                    if keyword_checking_token.is_reserved_ident() &&
                        !keyword_checking_token.is_keyword(keywords::Static) {
                         self.err_span_(start, last_bpos, "lifetimes cannot use keyword names");
                     }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2858d49d63d..c248e20b608 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -511,14 +511,13 @@ impl<'a> Parser<'a> {
     }
 
     pub fn this_token_descr(&self) -> String {
-        let s = self.this_token_to_string();
-        if self.token.is_strict_keyword() {
-            format!("keyword `{}`", s)
-        } else if self.token.is_reserved_keyword() {
-            format!("reserved keyword `{}`", s)
-        } else {
-            format!("`{}`", s)
-        }
+        let prefix = match &self.token {
+            t if t.is_special_ident() => "reserved identifier ",
+            t if t.is_used_keyword() => "keyword ",
+            t if t.is_unused_keyword() => "reserved keyword ",
+            _ => "",
+        };
+        format!("{}`{}`", prefix, self.this_token_to_string())
     }
 
     pub fn unexpected_last<T>(&self, t: &token::Token) -> PResult<'a, T> {
@@ -637,10 +636,12 @@ impl<'a> Parser<'a> {
     }
 
     pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> {
-        self.check_strict_keywords();
-        self.check_reserved_keywords();
         match self.token {
             token::Ident(i) => {
+                if self.token.is_reserved_ident() {
+                    self.span_err(self.span, &format!("expected identifier, found {}",
+                                                      self.this_token_descr()));
+                }
                 self.bump();
                 Ok(i)
             }
@@ -713,25 +714,6 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Signal an error if the given string is a strict keyword
-    pub fn check_strict_keywords(&mut self) {
-        if self.token.is_strict_keyword() {
-            let token_str = self.this_token_to_string();
-            let span = self.span;
-            self.span_err(span,
-                          &format!("expected identifier, found keyword `{}`",
-                                  token_str));
-        }
-    }
-
-    /// Signal an error if the current token is a reserved keyword
-    pub fn check_reserved_keywords(&mut self) {
-        if self.token.is_reserved_keyword() {
-            let token_str = self.this_token_to_string();
-            self.fatal(&format!("`{}` is a reserved keyword", token_str)).emit()
-        }
-    }
-
     fn check_ident(&mut self) -> bool {
         if self.token.is_ident() {
             true
@@ -1659,8 +1641,10 @@ impl<'a> Parser<'a> {
         Ok(codemap::Spanned { node: lit, span: lo.to(self.prev_span) })
     }
 
-    /// matches '-' lit | lit
+    /// matches '-' lit | lit (cf. ast_validation::AstValidator::check_expr_within_pat)
     pub fn parse_pat_literal_maybe_minus(&mut self) -> PResult<'a, P<Expr>> {
+        maybe_whole_expr!(self);
+
         let minus_lo = self.span;
         let minus_present = self.eat(&token::BinOp(token::Minus));
         let lo = self.span;
@@ -2299,7 +2283,7 @@ impl<'a> Parser<'a> {
                     ex = ExprKind::Break(lt, e);
                     hi = self.prev_span;
                 } else if self.token.is_keyword(keywords::Let) {
-                    // Catch this syntax error here, instead of in `check_strict_keywords`, so
+                    // Catch this syntax error here, instead of in `parse_ident`, so
                     // that we can explicitly mention that let is not to be used as an expression
                     let mut db = self.fatal("expected expression, found statement (`let`)");
                     db.note("variable declaration using `let` is a statement");
@@ -3541,7 +3525,7 @@ impl<'a> Parser<'a> {
                 // Parse box pat
                 let subpat = self.parse_pat()?;
                 pat = PatKind::Box(subpat);
-            } else if self.token.is_ident() && !self.token.is_any_keyword() &&
+            } else if self.token.is_ident() && !self.token.is_reserved_ident() &&
                       self.parse_as_ident() {
                 // Parse ident @ pat
                 // This can give false positives and parse nullary enums,
@@ -3816,7 +3800,7 @@ impl<'a> Parser<'a> {
 
     fn is_union_item(&self) -> bool {
         self.token.is_keyword(keywords::Union) &&
-        self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword())
+        self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident())
     }
 
     fn is_defaultness(&self) -> bool {
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index d4198261d3f..834ac38af98 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -89,7 +89,7 @@ impl Lit {
 fn ident_can_begin_expr(ident: ast::Ident) -> bool {
     let ident_token: Token = Ident(ident);
 
-    !ident_token.is_any_keyword() ||
+    !ident_token.is_reserved_ident() ||
     ident_token.is_path_segment_keyword() ||
     [
         keywords::Do.name(),
@@ -112,7 +112,7 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool {
 fn ident_can_begin_type(ident: ast::Ident) -> bool {
     let ident_token: Token = Ident(ident);
 
-    !ident_token.is_any_keyword() ||
+    !ident_token.is_reserved_ident() ||
     ident_token.is_path_segment_keyword() ||
     [
         keywords::For.name(),
@@ -319,7 +319,7 @@ impl Token {
 
     pub fn is_path_start(&self) -> bool {
         self == &ModSep || self.is_qpath_start() || self.is_path() ||
-        self.is_path_segment_keyword() || self.is_ident() && !self.is_any_keyword()
+        self.is_path_segment_keyword() || self.is_ident() && !self.is_reserved_ident()
     }
 
     /// Returns `true` if the token is a given keyword, `kw`.
@@ -331,18 +331,23 @@ impl Token {
         match self.ident() {
             Some(id) => id.name == keywords::Super.name() ||
                         id.name == keywords::SelfValue.name() ||
-                        id.name == keywords::SelfType.name(),
+                        id.name == keywords::SelfType.name() ||
+                        id.name == keywords::DollarCrate.name(),
             None => false,
         }
     }
 
-    /// Returns `true` if the token is either a strict or reserved keyword.
-    pub fn is_any_keyword(&self) -> bool {
-        self.is_strict_keyword() || self.is_reserved_keyword()
+    // Returns true for reserved identifiers used internally for elided lifetimes,
+    // unnamed method parameters, crate root module, error recovery etc.
+    pub fn is_special_ident(&self) -> bool {
+        match self.ident() {
+            Some(id) => id.name <= keywords::DollarCrate.name(),
+            _ => false,
+        }
     }
 
-    /// Returns `true` if the token is a strict keyword.
-    pub fn is_strict_keyword(&self) -> bool {
+    /// Returns `true` if the token is a keyword used in the language.
+    pub fn is_used_keyword(&self) -> bool {
         match self.ident() {
             Some(id) => id.name >= keywords::As.name() && id.name <= keywords::While.name(),
             _ => false,
@@ -350,7 +355,7 @@ impl Token {
     }
 
     /// Returns `true` if the token is a keyword reserved for possible future use.
-    pub fn is_reserved_keyword(&self) -> bool {
+    pub fn is_unused_keyword(&self) -> bool {
         match self.ident() {
             Some(id) => id.name >= keywords::Abstract.name() && id.name <= keywords::Yield.name(),
             _ => false,
@@ -410,6 +415,11 @@ impl Token {
             Whitespace | Comment | Shebang(..) | Eof => return None,
         })
     }
+
+    /// Returns `true` if the token is either a special identifier or a keyword.
+    pub fn is_reserved_ident(&self) -> bool {
+        self.is_special_ident() || self.is_used_keyword() || self.is_unused_keyword()
+    }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash)]
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index ac5b32c828a..d449e412d6c 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -760,7 +760,7 @@ pub trait PrintState<'a> {
                         word(self.writer(), "::")?
                     }
                     if segment.identifier.name != keywords::CrateRoot.name() &&
-                       segment.identifier.name != "$crate" {
+                       segment.identifier.name != keywords::DollarCrate.name() {
                         word(self.writer(), &segment.identifier.name.as_str())?;
                     }
                 }
@@ -2374,7 +2374,7 @@ impl<'a> State<'a> {
                           -> io::Result<()>
     {
         if segment.identifier.name != keywords::CrateRoot.name() &&
-           segment.identifier.name != "$crate" {
+           segment.identifier.name != keywords::DollarCrate.name() {
             self.print_ident(segment.identifier)?;
             if let Some(ref parameters) = segment.parameters {
                 self.print_path_parameters(parameters, colons_before_params)?;
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index a0d1785c6ff..86f5f42eac7 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -52,7 +52,8 @@ struct Test {
     path: Vec<Ident> ,
     bench: bool,
     ignore: bool,
-    should_panic: ShouldPanic
+    should_panic: ShouldPanic,
+    allow_fail: bool,
 }
 
 struct TestCtxt<'a> {
@@ -133,7 +134,8 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
                         path: self.cx.path.clone(),
                         bench: is_bench_fn(&self.cx, &i),
                         ignore: is_ignored(&i),
-                        should_panic: should_panic(&i, &self.cx)
+                        should_panic: should_panic(&i, &self.cx),
+                        allow_fail: is_allowed_fail(&i),
                     };
                     self.cx.testfns.push(test);
                     self.tests.push(i.ident);
@@ -383,6 +385,10 @@ fn is_ignored(i: &ast::Item) -> bool {
     i.attrs.iter().any(|attr| attr.check_name("ignore"))
 }
 
+fn is_allowed_fail(i: &ast::Item) -> bool {
+    i.attrs.iter().any(|attr| attr.check_name("allow_fail"))
+}
+
 fn should_panic(i: &ast::Item, cx: &TestCtxt) -> ShouldPanic {
     match i.attrs.iter().find(|attr| attr.check_name("should_panic")) {
         Some(attr) => {
@@ -668,6 +674,7 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
             }
         }
     };
+    let allow_fail_expr = ecx.expr_bool(span, test.allow_fail);
 
     // self::test::TestDesc { ... }
     let desc_expr = ecx.expr_struct(
@@ -675,7 +682,8 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P<ast::Expr> {
         test_path("TestDesc"),
         vec![field("name", name_expr),
              field("ignore", ignore_expr),
-             field("should_panic", fail_expr)]);
+             field("should_panic", fail_expr),
+             field("allow_fail", allow_fail_expr)]);
 
 
     let mut visible_path = match cx.toplevel_reexport {