about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2017-04-07 07:19:44 -0700
committerEsteban Küber <esteban@kuber.com.ar>2017-04-07 14:55:45 -0700
commit8c31412c2f84c7d76602b2598c5c1352da61d022 (patch)
treecbc08b79f16f1533e27d84dee16e90f9f319a679 /src/libsyntax
parentb83352e44c36e81db7f00eb60e78ff3828c51c9e (diff)
parent4c59c92bc4d4d6e5b2b66c4cc08dd1a058283a0d (diff)
downloadrust-8c31412c2f84c7d76602b2598c5c1352da61d022.tar.gz
rust-8c31412c2f84c7d76602b2598c5c1352da61d022.zip
Merge branch 'master' into ty-placeholder
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ext/derive.rs3
-rw-r--r--src/libsyntax/feature_gate.rs20
-rw-r--r--src/libsyntax/parse/parser.rs116
-rw-r--r--src/libsyntax/ptr.rs12
-rw-r--r--src/libsyntax/util/rc_slice.rs13
5 files changed, 126 insertions, 38 deletions
diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs
index c79040424f6..e7c5d8278d9 100644
--- a/src/libsyntax/ext/derive.rs
+++ b/src/libsyntax/ext/derive.rs
@@ -26,7 +26,8 @@ pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec<ast::Attribute>) -> Vec
             return true;
         }
 
-        match attr.parse_list(cx.parse_sess, |parser| parser.parse_path(PathStyle::Mod)) {
+        match attr.parse_list(cx.parse_sess,
+                              |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) {
             Ok(ref traits) if traits.is_empty() => {
                 cx.span_warn(attr.span, "empty trait list in `derive`");
                 false
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 12d25ca4274..550f1160bed 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -292,9 +292,6 @@ declare_features! (
     // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
     (active, generic_param_attrs, "1.11.0", Some(34761)),
 
-    // The #![windows_subsystem] attribute
-    (active, windows_subsystem, "1.14.0", Some(37499)),
-
     // Allows #[link(..., cfg(..))]
     (active, link_cfg, "1.14.0", Some(37406)),
 
@@ -337,11 +334,15 @@ declare_features! (
     // `extern "x86-interrupt" fn()`
     (active, abi_x86_interrupt, "1.17.0", Some(40180)),
 
+
     // Allows the `catch {...}` expression
     (active, catch_expr, "1.17.0", Some(31436)),
 
     // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work.
     (active, rvalue_static_promotion, "1.15.1", Some(38865)),
+
+    // Used to preserve symbols (see llvm.used)
+    (active, used, "1.18.0", Some(40289)),
 );
 
 declare_features! (
@@ -408,7 +409,8 @@ declare_features! (
     (accepted, static_recursion, "1.17.0", Some(29719)),
     // pub(restricted) visibilities (RFC 1422)
     (accepted, pub_restricted, "1.17.0", Some(32409)),
-
+    // The #![windows_subsystem] attribute
+    (accepted, windows_subsystem, "1.18.0", Some(37499)),
 );
 // If you change this, please modify src/doc/unstable-book as well. You must
 // move that documentation into the relevant place in the other docs, and
@@ -748,6 +750,10 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                   "unwind_attributes",
                                   "#[unwind] is experimental",
                                   cfg_fn!(unwind_attributes))),
+    ("used", Whitelisted, Gated(
+        Stability::Unstable, "used",
+        "the `#[used]` attribute is an experimental feature",
+        cfg_fn!(used))),
 
     // used in resolve
     ("prelude_import", Whitelisted, Gated(Stability::Unstable,
@@ -768,11 +774,7 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                         "unboxed_closures are still evolving",
                                         cfg_fn!(unboxed_closures))),
 
-    ("windows_subsystem", Whitelisted, Gated(Stability::Unstable,
-                                             "windows_subsystem",
-                                             "the windows subsystem attribute \
-                                              is currently unstable",
-                                             cfg_fn!(windows_subsystem))),
+    ("windows_subsystem", Whitelisted, Ungated),
 
     ("proc_macro_attribute", Normal, Gated(Stability::Unstable,
                                            "proc_macro",
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 23fc1351426..43d21015a4f 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -570,20 +570,33 @@ impl<'a> Parser<'a> {
             expected.dedup();
             let expect = tokens_to_string(&expected[..]);
             let actual = self.this_token_to_string();
-            Err(self.fatal(
-                &(if expected.len() > 1 {
-                    (format!("expected one of {}, found `{}`",
-                             expect,
-                             actual))
-                } else if expected.is_empty() {
-                    (format!("unexpected token: `{}`",
-                             actual))
+            let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 {
+                let short_expect = if expected.len() > 6 {
+                    format!("{} possible tokens", expected.len())
                 } else {
-                    (format!("expected {}, found `{}`",
-                             expect,
-                             actual))
-                })[..]
-            ))
+                    expect.clone()
+                };
+                (format!("expected one of {}, found `{}`", expect, actual),
+                 (self.prev_span.next_point(), format!("expected one of {} here", short_expect)))
+            } else if expected.is_empty() {
+                (format!("unexpected token: `{}`", actual),
+                 (self.prev_span, "unexpected token after this".to_string()))
+            } else {
+                (format!("expected {}, found `{}`", expect, actual),
+                 (self.prev_span.next_point(), format!("expected {} here", expect)))
+            };
+            let mut err = self.fatal(&msg_exp);
+            let sp = if self.token == token::Token::Eof {
+                // This is EOF, don't want to point at the following char, but rather the last token
+                self.prev_span
+            } else {
+                label_sp
+            };
+            err.span_label(sp, &label_exp);
+            if !sp.source_equal(&self.span) {
+                err.span_label(self.span, &"unexpected token");
+            }
+            Err(err)
         }
     }
 
@@ -1773,6 +1786,26 @@ impl<'a> Parser<'a> {
         })
     }
 
+    /// Like `parse_path`, but also supports parsing `Word` meta items into paths for back-compat.
+    /// This is used when parsing derive macro paths in `#[derive]` attributes.
+    pub fn parse_path_allowing_meta(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
+        let meta_ident = match self.token {
+            token::Interpolated(ref nt) => match **nt {
+                token::NtMeta(ref meta) => match meta.node {
+                    ast::MetaItemKind::Word => Some(ast::Ident::with_empty_ctxt(meta.name)),
+                    _ => None,
+                },
+                _ => None,
+            },
+            _ => None,
+        };
+        if let Some(ident) = meta_ident {
+            self.bump();
+            return Ok(ast::Path::from_ident(self.prev_span, ident));
+        }
+        self.parse_path(mode)
+    }
+
     /// Examples:
     /// - `a::b<T,U>::c<V,W>`
     /// - `a::b<T,U>::c(V) -> W`
@@ -4667,25 +4700,30 @@ impl<'a> Parser<'a> {
         })
     }
 
-    fn complain_if_pub_macro(&mut self, visa: &Visibility, span: Span) {
-        match *visa {
-            Visibility::Inherited => (),
+    fn complain_if_pub_macro(&mut self, vis: &Visibility, sp: Span) {
+        if let Err(mut err) = self.complain_if_pub_macro_diag(vis, sp) {
+            err.emit();
+        }
+    }
+
+    fn complain_if_pub_macro_diag(&mut self, vis: &Visibility, sp: Span) -> PResult<'a, ()> {
+        match *vis {
+            Visibility::Inherited => Ok(()),
             _ => {
                 let is_macro_rules: bool = match self.token {
                     token::Ident(sid) => sid.name == Symbol::intern("macro_rules"),
                     _ => false,
                 };
                 if is_macro_rules {
-                    self.diagnostic().struct_span_err(span, "can't qualify macro_rules \
-                                                             invocation with `pub`")
-                                     .help("did you mean #[macro_export]?")
-                                     .emit();
+                    let mut err = self.diagnostic()
+                        .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`");
+                    err.help("did you mean #[macro_export]?");
+                    Err(err)
                 } else {
-                    self.diagnostic().struct_span_err(span, "can't qualify macro \
-                                                             invocation with `pub`")
-                                     .help("try adjusting the macro to put `pub` \
-                                            inside the invocation")
-                                     .emit();
+                    let mut err = self.diagnostic()
+                        .struct_span_err(sp, "can't qualify macro invocation with `pub`");
+                    err.help("try adjusting the macro to put `pub` inside the invocation");
+                    Err(err)
                 }
             }
         }
@@ -4696,14 +4734,36 @@ impl<'a> Parser<'a> {
                          -> PResult<'a, (Ident, Vec<ast::Attribute>, ast::ImplItemKind)> {
         // code copied from parse_macro_use_or_failure... abstraction!
         if self.token.is_path_start() {
-            // method macro.
+            // Method macro.
 
             let prev_span = self.prev_span;
-            self.complain_if_pub_macro(&vis, prev_span);
+            // Before complaining about trying to set a macro as `pub`,
+            // check if `!` comes after the path.
+            let err = self.complain_if_pub_macro_diag(&vis, prev_span);
 
             let lo = self.span;
             let pth = self.parse_path(PathStyle::Mod)?;
-            self.expect(&token::Not)?;
+            let bang_err = self.expect(&token::Not);
+            if let Err(mut err) = err {
+                if let Err(mut bang_err) = bang_err {
+                    // Given this code `pub path(`, it seems like this is not setting the
+                    // visibility of a macro invocation, but rather a mistyped method declaration.
+                    // Create a diagnostic pointing out that `fn` is missing.
+                    //
+                    // x |     pub path(&self) {
+                    //   |        ^ missing `fn` for method declaration
+
+                    err.cancel();
+                    bang_err.cancel();
+                    //     pub  path(
+                    //        ^^ `sp` below will point to this
+                    let sp = prev_span.between(self.prev_span);
+                    err = self.diagnostic()
+                        .struct_span_err(sp, "missing `fn` for method declaration");
+                    err.span_label(sp, &"missing `fn`");
+                }
+                return Err(err);
+            }
 
             // eat a matched-delimiter token tree:
             let (delim, tts) = self.expect_delimited_token_tree()?;
diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs
index 58750158931..15111bbba0a 100644
--- a/src/libsyntax/ptr.rs
+++ b/src/libsyntax/ptr.rs
@@ -43,6 +43,8 @@ use std::{mem, ptr, slice, vec};
 
 use serialize::{Encodable, Decodable, Encoder, Decoder};
 
+use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
+                                           HashStable};
 /// An owned smart pointer.
 #[derive(Hash, PartialEq, Eq, PartialOrd, Ord)]
 pub struct P<T: ?Sized> {
@@ -215,3 +217,13 @@ impl<T: Decodable> Decodable for P<[T]> {
         }))
     }
 }
+
+impl<CTX, T> HashStable<CTX> for P<T>
+    where T: ?Sized + HashStable<CTX>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        (**self).hash_stable(hcx, hasher);
+    }
+}
diff --git a/src/libsyntax/util/rc_slice.rs b/src/libsyntax/util/rc_slice.rs
index 195fb23f9d8..2d9fd7aa875 100644
--- a/src/libsyntax/util/rc_slice.rs
+++ b/src/libsyntax/util/rc_slice.rs
@@ -12,6 +12,9 @@ use std::fmt;
 use std::ops::Deref;
 use std::rc::Rc;
 
+use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
+                                           HashStable};
+
 #[derive(Clone)]
 pub struct RcSlice<T> {
     data: Rc<Box<[T]>>,
@@ -41,3 +44,13 @@ impl<T: fmt::Debug> fmt::Debug for RcSlice<T> {
         fmt::Debug::fmt(self.deref(), f)
     }
 }
+
+impl<CTX, T> HashStable<CTX> for RcSlice<T>
+    where T: HashStable<CTX>
+{
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        (**self).hash_stable(hcx, hasher);
+    }
+}