]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #40129 - abonander:proc_macro_bang, r=jseyfried
authorCorey Farwell <coreyf@rwell.org>
Thu, 2 Mar 2017 19:53:46 +0000 (14:53 -0500)
committerGitHub <noreply@github.com>
Thu, 2 Mar 2017 19:53:46 +0000 (14:53 -0500)
Implement function-like procedural macros ( `#[proc_macro]`)

Adds the `#[proc_macro]` attribute, which expects bare functions of the kind `fn(TokenStream) -> TokenStream`, which can be invoked like `my_macro!()`.

cc rust-lang/rfcs#1913, #38356

r? @jseyfried
cc @nrc

1  2 
src/libproc_macro/lib.rs
src/libsyntax/feature_gate.rs

diff --combined src/libproc_macro/lib.rs
index b33caefbcd2ecbac73e3b73a7b1d88ca4af3f2a5,867fa48330de2acddc40280b31de253da7b3acbb..0516e111be3b38002bd924e6a7ada7c107082e4b
@@@ -125,6 -125,10 +125,10 @@@ pub mod __internal 
          fn register_attr_proc_macro(&mut self,
                                      name: &str,
                                      expand: fn(TokenStream, TokenStream) -> TokenStream);
+         fn register_bang_proc_macro(&mut self,
+                                     name: &str,
+                                     expand: fn(TokenStream) -> TokenStream);
      }
  
      // Emulate scoped_thread_local!() here essentially
@@@ -173,7 -177,8 +177,7 @@@ impl FromStr for TokenStream 
          __internal::with_parse_sess(|sess| {
              let src = src.to_string();
              let name = "<proc-macro source code>".to_string();
 -            let tts = try!(parse::parse_tts_from_source_str(name, src, sess)
 -                .map_err(parse_to_lex_err));
 +            let tts = parse::parse_tts_from_source_str(name, src, sess);
  
              Ok(__internal::token_stream_wrap(tts.into_iter().collect()))
          })
index e4256ff1c840745521f636f38425b8b07688b879,7de50430184f6641b5bde98cc29c669decc16ac6..6eb7d449f269287afe915646535552840b0ec16d
@@@ -77,19 -77,12 +77,19 @@@ macro_rules! declare_features 
      };
  
      ($((removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
 -        /// Represents features which has since been removed (it was once Active)
 +        /// Represents unstable features which have since been removed (it was once Active)
          const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
              $((stringify!($feature), $ver, $issue)),+
          ];
      };
  
 +    ($((stable_removed, $feature: ident, $ver: expr, $issue: expr),)+) => {
 +        /// Represents stable features which have since been removed (it was once Accepted)
 +        const STABLE_REMOVED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
 +            $((stringify!($feature), $ver, $issue)),+
 +        ];
 +    };
 +
      ($((accepted, $feature: ident, $ver: expr, $issue: expr),)+) => {
          /// Those language feature has since been Accepted (it was once Active)
          const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option<u32>)] = &[
@@@ -337,9 -330,6 +337,9 @@@ declare_features! 
      // Used to identify crates that contain sanitizer runtimes
      // rustc internal
      (active, sanitizer_runtime, "1.17.0", None),
 +
 +    // `extern "x86-interrupt" fn()`
 +    (active, abi_x86_interrupt, "1.17.0", Some(40180)),
  );
  
  declare_features! (
      (removed, pushpop_unsafe, "1.2.0", None),
  );
  
 +declare_features! (
 +    (stable_removed, no_stack_check, "1.0.0", None),
 +);
 +
  declare_features! (
      (accepted, associated_types, "1.0.0", None),
      // allow overloading augmented assignment operations like `a += b`
@@@ -519,6 -505,9 +519,6 @@@ pub const BUILTIN_ATTRIBUTES: &'static 
                                               not yet settled",
                                              cfg_fn!(structural_match))),
  
 -    // Not used any more, but we can't feature gate it
 -    ("no_stack_check", Normal, Ungated),
 -
      ("plugin", CrateLevel, Gated(Stability::Unstable,
                                   "plugin",
                                   "compiler plugins are experimental \
                                             "attribute proc macros are currently unstable",
                                             cfg_fn!(proc_macro))),
  
+     ("proc_macro", Normal, Gated(Stability::Unstable,
+                                  "proc_macro",
+                                  "function-like proc macros are currently unstable",
+                                  cfg_fn!(proc_macro))),
      ("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
                                               "rustc_derive_registrar",
                                               "used internally by rustc",
@@@ -920,10 -914,8 +925,10 @@@ fn find_lang_feature_issue(feature: &st
          // assert!(issue.is_some())
          issue
      } else {
 -        // search in Accepted or Removed features
 -        match ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).find(|t| t.0 == feature) {
 +        // search in Accepted, Removed, or Stable Removed features
 +        let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES)
 +            .find(|t| t.0 == feature);
 +        match found {
              Some(&(_, _, issue)) => issue,
              None => panic!("Feature `{}` is not declared anywhere", feature),
          }
@@@ -1049,10 -1041,6 +1054,10 @@@ impl<'a> PostExpansionVisitor<'a> 
                  gate_feature_post!(&self, abi_msp430_interrupt, span,
                                     "msp430-interrupt ABI is experimental and subject to change");
              },
 +            Abi::X86Interrupt => {
 +                gate_feature_post!(&self, abi_x86_interrupt, span,
 +                                   "x86-interrupt ABI is experimental and subject to change");
 +            },
              // Stable
              Abi::Cdecl |
              Abi::Stdcall |
@@@ -1461,9 -1449,7 +1466,9 @@@ pub fn get_features(span_handler: &Hand
                          feature_checker.collect(&features, mi.span);
                      }
                      else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter()
 -                        .find(|& &(n, _, _)| name == n) {
 +                            .find(|& &(n, _, _)| name == n)
 +                        .or_else(|| STABLE_REMOVED_FEATURES.iter()
 +                            .find(|& &(n, _, _)| name == n)) {
                          span_err!(span_handler, mi.span, E0557, "feature has been removed");
                      }
                      else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter()