]> git.lizzy.rs Git - rust.git/commitdiff
syntax: Unsupport `foo! bar { ... }` macros in the parser
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Sun, 30 Jun 2019 22:08:49 +0000 (01:08 +0300)
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>
Mon, 1 Jul 2019 09:20:54 +0000 (12:20 +0300)
Unreserve `macro_rules` as a macro name

src/librustc_plugin/registry.rs
src/librustc_resolve/macros.rs
src/libsyntax/ext/expand.rs
src/libsyntax/parse/parser.rs
src/test/run-pass/rfcs/rfc-2151-raw-identifiers/macros.rs
src/test/ui/issues/issue-10536.rs
src/test/ui/issues/issue-10536.stderr
src/test/ui/parser/macro-bad-delimiter-ident.rs
src/test/ui/parser/macro-bad-delimiter-ident.stderr
src/test/ui/user-defined-macro-rules.rs
src/test/ui/user-defined-macro-rules.stderr [deleted file]

index 16d484e2a98f2e699edc0078c41c61bdd1972544..640662d7733e78aaaac97ef7d226a2ce0677579f 100644 (file)
@@ -6,7 +6,7 @@
 
 use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension};
 use syntax::ext::base::MacroExpanderFn;
-use syntax::symbol::{Symbol, sym};
+use syntax::symbol::Symbol;
 use syntax::ast;
 use syntax::feature_gate::AttributeType;
 use syntax_pos::Span;
@@ -85,9 +85,6 @@ pub fn args<'b>(&'b self) -> &'b [ast::NestedMetaItem] {
     ///
     /// This is the most general hook into `libsyntax`'s expansion behavior.
     pub fn register_syntax_extension(&mut self, name: ast::Name, mut extension: SyntaxExtension) {
-        if name == sym::macro_rules {
-            panic!("user-defined macros may not be named `macro_rules`");
-        }
         if extension.def_info.is_none() {
             extension.def_info = Some((ast::CRATE_NODE_ID, self.krate_span));
         }
index 392a46a262f5038c2b59e0dcfebf7c1f137678ef..68e842c5e549588b47ab848f6ee0271bbac727d0 100644 (file)
@@ -1109,9 +1109,6 @@ pub fn define_macro(&mut self,
                         current_legacy_scope: &mut LegacyScope<'a>) {
         self.local_macro_def_scopes.insert(item.id, self.current_module);
         let ident = item.ident;
-        if ident.name == sym::macro_rules {
-            self.session.span_err(item.span, "user-defined macros may not be named `macro_rules`");
-        }
 
         let def_id = self.definitions.local_def_id(item.id);
         let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess,
index 5473f55aa33704053b03cdf982f7f108fc162a9a..f7a4ae98d674d1555f07aa3ecae7d819aafc7919 100644 (file)
@@ -13,8 +13,7 @@
 use crate::parse::token;
 use crate::parse::parser::Parser;
 use crate::ptr::P;
-use crate::symbol::Symbol;
-use crate::symbol::{kw, sym};
+use crate::symbol::{sym, Symbol};
 use crate::tokenstream::{TokenStream, TokenTree};
 use crate::visit::{self, Visitor};
 use crate::util::map_in_place::MapInPlace;
@@ -197,7 +196,6 @@ pub struct Invocation {
 pub enum InvocationKind {
     Bang {
         mac: ast::Mac,
-        ident: Option<Ident>,
         span: Span,
     },
     Attr {
@@ -664,13 +662,12 @@ fn expand_bang_invoc(&mut self,
                          ext: &SyntaxExtension)
                          -> Option<AstFragment> {
         let kind = invoc.fragment_kind;
-        let (mac, ident, span) = match invoc.kind {
-            InvocationKind::Bang { mac, ident, span } => (mac, ident, span),
+        let (mac, span) = match invoc.kind {
+            InvocationKind::Bang { mac, span } => (mac, span),
             _ => unreachable!(),
         };
         let path = &mac.node.path;
 
-        let ident = ident.unwrap_or_else(|| Ident::invalid());
         let validate = |this: &mut Self| {
             // feature-gate the macro invocation
             if let Some((feature, issue)) = ext.unstable_feature {
@@ -690,12 +687,6 @@ fn expand_bang_invoc(&mut self,
                 }
             }
 
-            if ident.name != kw::Invalid {
-                let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident);
-                this.cx.span_err(path.span, &msg);
-                this.cx.trace_macros_diag();
-                return Err(kind.dummy(span));
-            }
             Ok(())
         };
 
@@ -729,19 +720,11 @@ fn expand_bang_invoc(&mut self,
             }
 
             SyntaxExtensionKind::Bang(expander) => {
-                if ident.name != kw::Invalid {
-                    let msg =
-                        format!("macro {}! expects no ident argument, given '{}'", path, ident);
-                    self.cx.span_err(path.span, &msg);
-                    self.cx.trace_macros_diag();
-                    kind.dummy(span)
-                } else {
-                    self.gate_proc_macro_expansion_kind(span, kind);
-                    let tok_result = expander.expand(self.cx, span, mac.node.stream());
-                    let result = self.parse_ast_fragment(tok_result, kind, path, span);
-                    self.gate_proc_macro_expansion(span, &result);
-                    result
-                }
+                self.gate_proc_macro_expansion_kind(span, kind);
+                let tok_result = expander.expand(self.cx, span, mac.node.stream());
+                let result = self.parse_ast_fragment(tok_result, kind, path, span);
+                self.gate_proc_macro_expansion(span, &result);
+                result
             }
         };
 
@@ -944,7 +927,7 @@ fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> A
     }
 
     fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
-        self.collect(kind, InvocationKind::Bang { mac, ident: None, span })
+        self.collect(kind, InvocationKind::Bang { mac, span })
     }
 
     fn collect_attr(&mut self,
@@ -1179,13 +1162,9 @@ fn visit_block(&mut self, block: &mut P<Block>) {
             ast::ItemKind::Mac(..) => {
                 self.check_attributes(&item.attrs);
                 item.and_then(|item| match item.node {
-                    ItemKind::Mac(mac) => {
-                        self.collect(AstFragmentKind::Items, InvocationKind::Bang {
-                            mac,
-                            ident: Some(item.ident),
-                            span: item.span,
-                        }).make_items()
-                    }
+                    ItemKind::Mac(mac) => self.collect(
+                        AstFragmentKind::Items, InvocationKind::Bang { mac, span: item.span }
+                    ).make_items(),
                     _ => unreachable!(),
                 })
             }
index fc206580e3811a79c107d1598c0ef2a775e949eb..cbecdb0738b393e0e07059170b1d3d311634866d 100644 (file)
@@ -4353,8 +4353,9 @@ fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility, lo: Span)
 
                 (ident, ast::MacroDef { tokens: tokens.into(), legacy: false })
             }
-            token::Ident(name, _) if name == sym::macro_rules &&
-                                     self.look_ahead(1, |t| *t == token::Not) => {
+            token::Ident(name, false) if name == sym::macro_rules &&
+                                         self.look_ahead(1, |t| *t == token::Not) &&
+                                         self.look_ahead(2, |t| t.is_ident()) => {
                 let prev_span = self.prev_span;
                 self.complain_if_pub_macro(&vis.node, prev_span);
                 self.bump();
@@ -4434,34 +4435,6 @@ fn parse_stmt_without_recovery(&mut self,
                 }));
             }
 
-            // it's a macro invocation
-            let id = match self.token.kind {
-                token::OpenDelim(_) => Ident::invalid(), // no special identifier
-                _ => self.parse_ident()?,
-            };
-
-            // check that we're pointing at delimiters (need to check
-            // again after the `if`, because of `parse_ident`
-            // consuming more tokens).
-            match self.token.kind {
-                token::OpenDelim(_) => {}
-                _ => {
-                    // we only expect an ident if we didn't parse one
-                    // above.
-                    let ident_str = if id.name == kw::Invalid {
-                        "identifier, "
-                    } else {
-                        ""
-                    };
-                    let tok_str = self.this_token_descr();
-                    let mut err = self.fatal(&format!("expected {}`(` or `{{`, found {}",
-                                                      ident_str,
-                                                      tok_str));
-                    err.span_label(self.token.span, format!("expected {}`(` or `{{`", ident_str));
-                    return Err(err)
-                },
-            }
-
             let (delim, tts) = self.expect_delimited_token_tree()?;
             let hi = self.prev_span;
 
@@ -4471,59 +4444,38 @@ fn parse_stmt_without_recovery(&mut self,
                 MacStmtStyle::NoBraces
             };
 
-            if id.name == kw::Invalid {
-                let mac = respan(lo.to(hi), Mac_ { path: pth, tts, delim });
-                let node = if delim == MacDelimiter::Brace ||
-                              self.token == token::Semi || self.token == token::Eof {
-                    StmtKind::Mac(P((mac, style, attrs.into())))
-                }
-                // We used to incorrectly stop parsing macro-expanded statements here.
-                // If the next token will be an error anyway but could have parsed with the
-                // earlier behavior, stop parsing here and emit a warning to avoid breakage.
-                else if macro_legacy_warnings &&
-                        self.token.can_begin_expr() &&
-                        match self.token.kind {
-                    // These can continue an expression, so we can't stop parsing and warn.
-                    token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
-                    token::BinOp(token::Minus) | token::BinOp(token::Star) |
-                    token::BinOp(token::And) | token::BinOp(token::Or) |
-                    token::AndAnd | token::OrOr |
-                    token::DotDot | token::DotDotDot | token::DotDotEq => false,
-                    _ => true,
-                } {
-                    self.warn_missing_semicolon();
-                    StmtKind::Mac(P((mac, style, attrs.into())))
-                } else {
-                    let e = self.mk_expr(mac.span, ExprKind::Mac(mac), ThinVec::new());
-                    let e = self.maybe_recover_from_bad_qpath(e, true)?;
-                    let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
-                    let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
-                    StmtKind::Expr(e)
-                };
-                Stmt {
-                    id: ast::DUMMY_NODE_ID,
-                    span: lo.to(hi),
-                    node,
-                }
+            let mac = respan(lo.to(hi), Mac_ { path: pth, tts, delim });
+            let node = if delim == MacDelimiter::Brace ||
+                          self.token == token::Semi || self.token == token::Eof {
+                StmtKind::Mac(P((mac, style, attrs.into())))
+            }
+            // We used to incorrectly stop parsing macro-expanded statements here.
+            // If the next token will be an error anyway but could have parsed with the
+            // earlier behavior, stop parsing here and emit a warning to avoid breakage.
+            else if macro_legacy_warnings &&
+                    self.token.can_begin_expr() &&
+                    match self.token.kind {
+                // These can continue an expression, so we can't stop parsing and warn.
+                token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
+                token::BinOp(token::Minus) | token::BinOp(token::Star) |
+                token::BinOp(token::And) | token::BinOp(token::Or) |
+                token::AndAnd | token::OrOr |
+                token::DotDot | token::DotDotDot | token::DotDotEq => false,
+                _ => true,
+            } {
+                self.warn_missing_semicolon();
+                StmtKind::Mac(P((mac, style, attrs.into())))
             } else {
-                // if it has a special ident, it's definitely an item
-                //
-                // Require a semicolon or braces.
-                if style != MacStmtStyle::Braces && !self.eat(&token::Semi) {
-                    self.report_invalid_macro_expansion_item();
-                }
-                let span = lo.to(hi);
-                Stmt {
-                    id: ast::DUMMY_NODE_ID,
-                    span,
-                    node: StmtKind::Item({
-                        self.mk_item(
-                            span, id /*id is good here*/,
-                            ItemKind::Mac(respan(span, Mac_ { path: pth, tts, delim })),
-                            respan(lo, VisibilityKind::Inherited),
-                            attrs)
-                    }),
-                }
+                let e = self.mk_expr(mac.span, ExprKind::Mac(mac), ThinVec::new());
+                let e = self.maybe_recover_from_bad_qpath(e, true)?;
+                let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
+                let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
+                StmtKind::Expr(e)
+            };
+            Stmt {
+                id: ast::DUMMY_NODE_ID,
+                span: lo.to(hi),
+                node,
             }
         } else {
             // FIXME: Bad copy of attrs
@@ -7611,16 +7563,6 @@ fn parse_macro_use_or_failure(
             // item macro.
             let pth = self.parse_path(PathStyle::Mod)?;
             self.expect(&token::Not)?;
-
-            // a 'special' identifier (like what `macro_rules!` uses)
-            // is optional. We should eventually unify invoc syntax
-            // and remove this.
-            let id = if self.token.is_ident() {
-                self.parse_ident()?
-            } else {
-                Ident::invalid() // no special identifier
-            };
-            // eat a matched-delimiter token tree:
             let (delim, tts) = self.expect_delimited_token_tree()?;
             if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
                 self.report_invalid_macro_expansion_item();
@@ -7628,7 +7570,8 @@ fn parse_macro_use_or_failure(
 
             let hi = self.prev_span;
             let mac = respan(mac_lo.to(hi), Mac_ { path: pth, tts, delim });
-            let item = self.mk_item(lo.to(hi), id, ItemKind::Mac(mac), visibility, attrs);
+            let item =
+                self.mk_item(lo.to(hi), Ident::invalid(), ItemKind::Mac(mac), visibility, attrs);
             return Ok(Some(item));
         }
 
index 51a3b46d4619b204c12c33a94f8a31b522d62b84..0ab7e17f87b5a156a738fc3c37fa8b9f5e92b010 100644 (file)
@@ -1,7 +1,7 @@
 // run-pass
 #![feature(decl_macro)]
 
-r#macro_rules! r#struct {
+macro_rules! r#struct {
     ($r#struct:expr) => { $r#struct }
 }
 
index ceb44ecf7f58379dea230ebdf0588cfa2c724e63..111078abb37007a5a7538a71247c3c304365f864 100644 (file)
@@ -11,13 +11,9 @@ macro_rules! bar{() => (())}
 pub fn main() {
     foo!();
 
-    assert!({one! two()});
-    //~^ ERROR macros that expand to items
-    //~| ERROR cannot find macro `one!` in this scope
-    //~| ERROR mismatched types
+    assert!({one! two()}); //~ ERROR expected open delimiter
 
     // regardless of whether nested macro_rules works, the following should at
     // least throw a conventional error.
-    assert!({one! two});
-    //~^ ERROR expected `(` or `{`, found `}`
+    assert!({one! two}); //~ ERROR expected open delimiter
 }
index 584cdf43a8f4bafe862d2faab3869be92d290c04..73f948107f185fe2950ac2b4f1e6fd8beb2881ae 100644 (file)
@@ -1,38 +1,14 @@
-error: macros that expand to items must be delimited with braces or followed by a semicolon
-  --> $DIR/issue-10536.rs:14:22
+error: expected open delimiter
+  --> $DIR/issue-10536.rs:14:19
    |
 LL |     assert!({one! two()});
-   |                      ^^
-help: change the delimiters to curly braces
-   |
-LL |     assert!({one! two {}});
-   |                       ^^
-help: add a semicolon
-   |
-LL |     assert!({one! two();});
-   |                        ^
+   |                   ^^^ expected open delimiter
 
-error: expected `(` or `{`, found `}`
-  --> $DIR/issue-10536.rs:21:22
+error: expected open delimiter
+  --> $DIR/issue-10536.rs:18:19
    |
 LL |     assert!({one! two});
-   |                      ^ expected `(` or `{`
-
-error: cannot find macro `one!` in this scope
-  --> $DIR/issue-10536.rs:14:14
-   |
-LL |     assert!({one! two()});
-   |              ^^^
-
-error[E0308]: mismatched types
-  --> $DIR/issue-10536.rs:14:13
-   |
-LL |     assert!({one! two()});
-   |             ^^^^^^^^^^^^ expected bool, found ()
-   |
-   = note: expected type `bool`
-              found type `()`
+   |                   ^^^ expected open delimiter
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
index 987c955d1dc3836f4d70f3a3c3d813c55c22d448..13dec95435be0344b0683df81fac3c3f7de3b4f3 100644 (file)
@@ -1,3 +1,3 @@
 fn main() {
-    foo! bar < //~ ERROR expected `(` or `{`, found `<`
+    foo! bar < //~ ERROR expected open delimiter
 }
index 6a17d39e8bfec4751d952b5dc8438c361cbaf2b0..e97839a4f4a5232eb7622302248d3d49d6b973c4 100644 (file)
@@ -1,8 +1,8 @@
-error: expected `(` or `{`, found `<`
-  --> $DIR/macro-bad-delimiter-ident.rs:2:14
+error: expected open delimiter
+  --> $DIR/macro-bad-delimiter-ident.rs:2:10
    |
 LL |     foo! bar <
-   |              ^ expected `(` or `{`
+   |          ^^^ expected open delimiter
 
 error: aborting due to previous error
 
index 31bfdd025d99dcd733898e547a794d9f68403f0f..09e071ec45420d6500047f485892a5ba71ca9eff 100644 (file)
@@ -1,5 +1,9 @@
-#![allow(unused_macros)]
+// check-pass
 
-macro_rules! macro_rules { () => {} } //~ ERROR user-defined macros may not be named `macro_rules`
+macro_rules! macro_rules { () => { struct S; } } // OK
 
-fn main() {}
+macro_rules! {} // OK, calls the macro defined above
+
+fn main() {
+    let s = S;
+}
diff --git a/src/test/ui/user-defined-macro-rules.stderr b/src/test/ui/user-defined-macro-rules.stderr
deleted file mode 100644 (file)
index 0575152..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-error: user-defined macros may not be named `macro_rules`
-  --> $DIR/user-defined-macro-rules.rs:3:1
-   |
-LL | macro_rules! macro_rules { () => {} }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-