Skip to content

Commit

Permalink
Rollup merge of rust-lang#64035 - petrochenkov:stabmacgen, r=eddyb
Browse files Browse the repository at this point in the history
Stabilize proc macros generating `macro_rules` items

Fn-like and attribute proc macros can now generate `macro_rules` items.

cc rust-lang#54727
  • Loading branch information
Centril authored Oct 15, 2019
2 parents e369d87 + d80be3b commit 19d4e2f
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 157 deletions.
2 changes: 1 addition & 1 deletion src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
#![feature(test)]
#![feature(in_band_lifetimes)]
#![feature(crate_visibility_modifier)]
#![feature(proc_macro_hygiene)]
#![cfg_attr(bootstrap, feature(proc_macro_hygiene))]
#![feature(log_syntax)]
#![feature(associated_type_bounds)]
#![feature(rustc_attrs)]
Expand Down
49 changes: 4 additions & 45 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ use crate::ext::mbe::macro_rules::annotate_err_with_kind;
use crate::ext::placeholders::{placeholder, PlaceholderExpander};
use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
use crate::mut_visit::*;
use crate::parse::{DirectoryOwnership, PResult, ParseSess};
use crate::parse::{DirectoryOwnership, PResult};
use crate::parse::token;
use crate::parse::parser::Parser;
use crate::print::pprust;
use crate::ptr::P;
use crate::symbol::{sym, Symbol};
use crate::tokenstream::{TokenStream, TokenTree};
use crate::visit::{self, Visitor};
use crate::visit::Visitor;
use crate::util::map_in_place::MapInPlace;

use errors::{Applicability, FatalError};
Expand Down Expand Up @@ -577,10 +577,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
SyntaxExtensionKind::Bang(expander) => {
self.gate_proc_macro_expansion_kind(span, fragment_kind);
let tok_result = expander.expand(self.cx, span, mac.stream());
let result =
self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span);
self.gate_proc_macro_expansion(span, &result);
result
self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span)
}
SyntaxExtensionKind::LegacyBang(expander) => {
let prev = self.cx.current_expansion.prior_type_ascription;
Expand Down Expand Up @@ -624,10 +621,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
})), DUMMY_SP).into();
let input = self.extract_proc_macro_attr_input(attr.item.tokens, span);
let tok_result = expander.expand(self.cx, span, input, item_tok);
let res =
self.parse_ast_fragment(tok_result, fragment_kind, &attr.item.path, span);
self.gate_proc_macro_expansion(span, &res);
res
self.parse_ast_fragment(tok_result, fragment_kind, &attr.item.path, span)
}
SyntaxExtensionKind::LegacyAttr(expander) => {
match attr.parse_meta(self.cx.parse_sess) {
Expand Down Expand Up @@ -718,41 +712,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
);
}

fn gate_proc_macro_expansion(&self, span: Span, fragment: &AstFragment) {
if self.cx.ecfg.proc_macro_hygiene() {
return
}

fragment.visit_with(&mut DisallowMacros {
span,
parse_sess: self.cx.parse_sess,
});

struct DisallowMacros<'a> {
span: Span,
parse_sess: &'a ParseSess,
}

impl<'ast, 'a> Visitor<'ast> for DisallowMacros<'a> {
fn visit_item(&mut self, i: &'ast ast::Item) {
if let ast::ItemKind::MacroDef(_) = i.kind {
emit_feature_err(
self.parse_sess,
sym::proc_macro_hygiene,
self.span,
GateIssue::Language,
"procedural macros cannot expand to macro definitions",
);
}
visit::walk_item(self, i);
}

fn visit_mac(&mut self, _mac: &'ast ast::Mac) {
// ...
}
}
}

fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
let kind = match kind {
AstFragmentKind::Expr |
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax_pos/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#![feature(non_exhaustive)]
#![feature(optin_builtin_traits)]
#![feature(rustc_attrs)]
#![feature(proc_macro_hygiene)]
#![cfg_attr(bootstrap, feature(proc_macro_hygiene))]
#![feature(specialization)]
#![feature(step_trait)]

Expand Down
1 change: 0 additions & 1 deletion src/test/ui/macros/same-sequence-span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// left-hand side of a macro definition behave as if they had unique spans, and in particular that
// they don't crash the compiler.

#![feature(proc_macro_hygiene)]
#![allow(unused_macros)]

extern crate proc_macro_sequence;
Expand Down
8 changes: 4 additions & 4 deletions src/test/ui/macros/same-sequence-span.stderr
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments
--> $DIR/same-sequence-span.rs:15:18
--> $DIR/same-sequence-span.rs:14:18
|
LL | (1 $x:expr $($y:tt,)*
| ^^^^^ not allowed after `expr` fragments
|
= note: allowed there are: `=>`, `,` or `;`

error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragments
--> $DIR/same-sequence-span.rs:16:18
--> $DIR/same-sequence-span.rs:15:18
|
LL | $(= $z:tt)*
| ^ not allowed after `expr` fragments
|
= note: allowed there are: `=>`, `,` or `;`

error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments
--> $DIR/same-sequence-span.rs:20:1
--> $DIR/same-sequence-span.rs:19:1
|
LL | proc_macro_sequence::make_foo!();
| ^--------------------------------
Expand All @@ -30,7 +30,7 @@ LL | | fn main() {}
= note: allowed there are: `=>`, `,` or `;`

error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragments
--> $DIR/same-sequence-span.rs:20:1
--> $DIR/same-sequence-span.rs:19:1
|
LL | proc_macro_sequence::make_foo!();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
23 changes: 23 additions & 0 deletions src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// force-host
// no-prefer-dynamic

#![crate_type = "proc-macro"]

extern crate proc_macro;
use proc_macro::*;

#[proc_macro]
pub fn gen_macro_rules(_: TokenStream) -> TokenStream {
"
macro_rules! generated {() => {
struct ItemDef;
let local_def = 0;
ItemUse; // OK
local_use; // ERROR
break 'label_use; // ERROR
type DollarCrate = $crate::ItemUse; // OK
}}
".parse().unwrap()
}
35 changes: 0 additions & 35 deletions src/test/ui/proc-macro/auxiliary/more-gates.rs

This file was deleted.

23 changes: 23 additions & 0 deletions src/test/ui/proc-macro/gen-macro-rules-hygiene.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// `macro_rules` items produced by transparent macros have correct hygiene in basic cases.
// Local variables and labels are hygienic, items are not hygienic.
// `$crate` refers to the crate that defines `macro_rules` and not the outer transparent macro.

// aux-build:gen-macro-rules-hygiene.rs

#[macro_use]
extern crate gen_macro_rules_hygiene;

struct ItemUse;

gen_macro_rules!();
//~^ ERROR use of undeclared label `'label_use`
//~| ERROR cannot find value `local_use` in this scope

fn main() {
'label_use: loop {
let local_use = 1;
generated!();
ItemDef; // OK
local_def; //~ ERROR cannot find value `local_def` in this scope
}
}
28 changes: 28 additions & 0 deletions src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
error[E0426]: use of undeclared label `'label_use`
--> $DIR/gen-macro-rules-hygiene.rs:12:1
|
LL | gen_macro_rules!();
| ^^^^^^^^^^^^^^^^^^^ undeclared label `'label_use`
...
LL | generated!();
| ------------- in this macro invocation

error[E0425]: cannot find value `local_use` in this scope
--> $DIR/gen-macro-rules-hygiene.rs:12:1
|
LL | gen_macro_rules!();
| ^^^^^^^^^^^^^^^^^^^ not found in this scope
...
LL | generated!();
| ------------- in this macro invocation

error[E0425]: cannot find value `local_def` in this scope
--> $DIR/gen-macro-rules-hygiene.rs:21:9
|
LL | local_def;
| ^^^^^^^^^ not found in this scope

error: aborting due to 3 previous errors

Some errors have detailed explanations: E0425, E0426.
For more information about an error, try `rustc --explain E0425`.
22 changes: 0 additions & 22 deletions src/test/ui/proc-macro/more-gates.rs

This file was deleted.

48 changes: 0 additions & 48 deletions src/test/ui/proc-macro/more-gates.stderr

This file was deleted.

0 comments on commit 19d4e2f

Please sign in to comment.