Rollup merge of #63931 - petrochenkov:stabmac, r=Centril

Stabilize macros in some more positions

- Fn-like macros and attribute macros in `extern` blocks
- Fn-like procedural macros in type positions
- ~Attribute macros on inline modules~ (moved to https://github.com/rust-lang/rust/pull/64273)

Stabilization report: https://github.com/rust-lang/rust/pull/63931#issuecomment-526362396.

Closes https://github.com/rust-lang/rust/issues/49476
cc https://github.com/rust-lang/rust/issues/54727
This commit is contained in:
Mazdak Farrokhzad 2019-10-01 09:55:28 +02:00 committed by GitHub
commit 3bd34e04e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 60 additions and 363 deletions

View File

@ -1,4 +1,3 @@
#![feature(proc_macro_hygiene)]
#![allow(rustc::default_hash_types)]
#![recursion_limit="128"]

View File

@ -555,15 +555,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
}
fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment {
let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
if fragment_kind == AstFragmentKind::ForeignItems && !self.cx.ecfg.macros_in_extern() {
if let SyntaxExtensionKind::NonMacroAttr { .. } = ext {} else {
emit_feature_err(&self.cx.parse_sess, sym::macros_in_extern,
span, GateIssue::Language,
"macro invocations in `extern {}` blocks are experimental");
}
}
if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
let expn_data = self.cx.current_expansion.id.expn_data();
let suggested_limit = self.cx.ecfg.recursion_limit * 2;
@ -578,6 +569,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
FatalError.raise();
}
let (fragment_kind, span) = (invoc.fragment_kind, invoc.span());
match invoc.kind {
InvocationKind::Bang { mac, .. } => match ext {
SyntaxExtensionKind::Bang(expander) => {
@ -758,14 +750,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
let kind = match kind {
AstFragmentKind::Expr => "expressions",
AstFragmentKind::Expr |
AstFragmentKind::OptExpr => "expressions",
AstFragmentKind::Pat => "patterns",
AstFragmentKind::Ty => "types",
AstFragmentKind::Stmts => "statements",
AstFragmentKind::Items => return,
AstFragmentKind::TraitItems => return,
AstFragmentKind::ImplItems => return,
AstFragmentKind::Ty |
AstFragmentKind::Items |
AstFragmentKind::TraitItems |
AstFragmentKind::ImplItems |
AstFragmentKind::ForeignItems => return,
AstFragmentKind::Arms
| AstFragmentKind::Fields
@ -1578,9 +1570,6 @@ impl<'feat> ExpansionConfig<'feat> {
}
}
fn macros_in_extern(&self) -> bool {
self.features.map_or(false, |features| features.macros_in_extern)
}
fn proc_macro_hygiene(&self) -> bool {
self.features.map_or(false, |features| features.proc_macro_hygiene)
}

View File

@ -245,6 +245,8 @@ declare_features! (
(accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287), None),
/// Allows attributes in formal function parameters.
(accepted, param_attrs, "1.39.0", Some(60406), None),
// Allows macro invocations in `extern {}` blocks.
(accepted, macros_in_extern, "1.40.0", Some(49476), None),
// -------------------------------------------------------------------------
// feature-group-end: accepted features

View File

@ -402,9 +402,6 @@ declare_features! (
/// Allows infering `'static` outlives requirements (RFC 2093).
(active, infer_static_outlives_requirements, "1.26.0", Some(54185), None),
/// Allows macro invocations in `extern {}` blocks.
(active, macros_in_extern, "1.27.0", Some(49476), None),
/// Allows accessing fields of unions inside `const` functions.
(active, const_fn_union, "1.27.0", Some(51909), None),

View File

@ -1,30 +0,0 @@
error[E0658]: macro invocations in `extern {}` blocks are experimental
--> $DIR/macros-in-extern.rs:26:5
|
LL | returns_isize!(rust_get_test_int);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49476
= help: add `#![feature(macros_in_extern)]` to the crate attributes to enable
error[E0658]: macro invocations in `extern {}` blocks are experimental
--> $DIR/macros-in-extern.rs:28:5
|
LL | takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49476
= help: add `#![feature(macros_in_extern)]` to the crate attributes to enable
error[E0658]: macro invocations in `extern {}` blocks are experimental
--> $DIR/macros-in-extern.rs:30:5
|
LL | emits_nothing!();
| ^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49476
= help: add `#![feature(macros_in_extern)]` to the crate attributes to enable
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,112 +0,0 @@
// force-host
// no-prefer-dynamic
// Proc macros commonly used by tests.
// `panic`/`print` -> `panic_bang`/`print_bang` to avoid conflicts with standard macros.
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::TokenStream;
// Macro that return empty token stream.
#[proc_macro]
pub fn empty(_: TokenStream) -> TokenStream {
TokenStream::new()
}
#[proc_macro_attribute]
pub fn empty_attr(_: TokenStream, _: TokenStream) -> TokenStream {
TokenStream::new()
}
#[proc_macro_derive(Empty, attributes(empty_helper))]
pub fn empty_derive(_: TokenStream) -> TokenStream {
TokenStream::new()
}
// Macro that panics.
#[proc_macro]
pub fn panic_bang(_: TokenStream) -> TokenStream {
panic!("panic-bang");
}
#[proc_macro_attribute]
pub fn panic_attr(_: TokenStream, _: TokenStream) -> TokenStream {
panic!("panic-attr");
}
#[proc_macro_derive(Panic, attributes(panic_helper))]
pub fn panic_derive(_: TokenStream) -> TokenStream {
panic!("panic-derive");
}
// Macros that return the input stream.
#[proc_macro]
pub fn identity(input: TokenStream) -> TokenStream {
input
}
#[proc_macro_attribute]
pub fn identity_attr(_: TokenStream, input: TokenStream) -> TokenStream {
input
}
#[proc_macro_derive(Identity, attributes(identity_helper))]
pub fn identity_derive(input: TokenStream) -> TokenStream {
input
}
// Macros that iterate and re-collect the input stream.
#[proc_macro]
pub fn recollect(input: TokenStream) -> TokenStream {
input.into_iter().collect()
}
#[proc_macro_attribute]
pub fn recollect_attr(_: TokenStream, input: TokenStream) -> TokenStream {
input.into_iter().collect()
}
#[proc_macro_derive(Recollect, attributes(recollect_helper))]
pub fn recollect_derive(input: TokenStream) -> TokenStream {
input.into_iter().collect()
}
// Macros that print their input in the original and re-collected forms (if they differ).
fn print_helper(input: TokenStream, kind: &str) -> TokenStream {
let input_display = format!("{}", input);
let input_debug = format!("{:#?}", input);
let recollected = input.into_iter().collect();
let recollected_display = format!("{}", recollected);
let recollected_debug = format!("{:#?}", recollected);
println!("PRINT-{} INPUT (DISPLAY): {}", kind, input_display);
if recollected_display != input_display {
println!("PRINT-{} RE-COLLECTED (DISPLAY): {}", kind, recollected_display);
}
println!("PRINT-{} INPUT (DEBUG): {}", kind, input_debug);
if recollected_debug != input_debug {
println!("PRINT-{} RE-COLLECTED (DEBUG): {}", kind, recollected_debug);
}
recollected
}
#[proc_macro]
pub fn print_bang(input: TokenStream) -> TokenStream {
print_helper(input, "BANG")
}
#[proc_macro_attribute]
pub fn print_attr(_: TokenStream, input: TokenStream) -> TokenStream {
print_helper(input, "ATTR")
}
#[proc_macro_derive(Print, attributes(print_helper))]
pub fn print_derive(input: TokenStream) -> TokenStream {
print_helper(input, "DERIVE")
}

View File

@ -1,30 +0,0 @@
error[E0658]: macro invocations in `extern {}` blocks are experimental
--> $DIR/macros-in-extern.rs:14:5
|
LL | #[empty_attr]
| ^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49476
= help: add `#![feature(macros_in_extern)]` to the crate attributes to enable
error[E0658]: macro invocations in `extern {}` blocks are experimental
--> $DIR/macros-in-extern.rs:18:5
|
LL | #[identity_attr]
| ^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49476
= help: add `#![feature(macros_in_extern)]` to the crate attributes to enable
error[E0658]: macro invocations in `extern {}` blocks are experimental
--> $DIR/macros-in-extern.rs:22:5
|
LL | identity!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49476
= help: add `#![feature(macros_in_extern)]` to the crate attributes to enable
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,27 +0,0 @@
#![feature(decl_macro)]
macro_rules! returns_isize(
($ident:ident) => (
fn $ident() -> isize;
)
);
macro takes_u32_returns_u32($ident:ident) {
fn $ident (arg: u32) -> u32;
}
macro_rules! emits_nothing(
() => ()
);
#[link(name = "rust_test_helpers", kind = "static")]
extern {
returns_isize!(rust_get_test_int);
//~^ ERROR macro invocations in `extern {}` blocks are experimental
takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
//~^ ERROR macro invocations in `extern {}` blocks are experimental
emits_nothing!();
//~^ ERROR macro invocations in `extern {}` blocks are experimental
}
fn main() {}

View File

@ -1,30 +0,0 @@
error[E0658]: macro invocations in `extern {}` blocks are experimental
--> $DIR/feature-gate-macros_in_extern.rs:19:5
|
LL | returns_isize!(rust_get_test_int);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49476
= help: add `#![feature(macros_in_extern)]` to the crate attributes to enable
error[E0658]: macro invocations in `extern {}` blocks are experimental
--> $DIR/feature-gate-macros_in_extern.rs:21:5
|
LL | takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49476
= help: add `#![feature(macros_in_extern)]` to the crate attributes to enable
error[E0658]: macro invocations in `extern {}` blocks are experimental
--> $DIR/feature-gate-macros_in_extern.rs:23:5
|
LL | emits_nothing!();
| ^^^^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/49476
= help: add `#![feature(macros_in_extern)]` to the crate attributes to enable
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0658`.

View File

@ -1,5 +1,3 @@
#![feature(macros_in_extern)]
macro_rules! m {
() => {
let //~ ERROR expected

View File

@ -1,5 +1,5 @@
error: expected one of `crate`, `fn`, `pub`, `static`, or `type`, found `let`
--> $DIR/issue-54441.rs:5:9
--> $DIR/issue-54441.rs:3:9
|
LL | let
| ^^^ unexpected token

View File

@ -1,30 +0,0 @@
// run-pass
// ignore-wasm32
#![feature(decl_macro, macros_in_extern)]
macro_rules! returns_isize(
($ident:ident) => (
fn $ident() -> isize;
)
);
macro takes_u32_returns_u32($ident:ident) {
fn $ident (arg: u32) -> u32;
}
macro_rules! emits_nothing(
() => ()
);
fn main() {
assert_eq!(unsafe { rust_get_test_int() }, 1isize);
assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEFu32);
}
#[link(name = "rust_test_helpers", kind = "static")]
extern {
returns_isize!(rust_get_test_int);
takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
emits_nothing!();
}

View File

@ -1,3 +1,4 @@
// run-pass
// ignore-wasm32
#![feature(decl_macro)]
@ -16,17 +17,29 @@ macro_rules! emits_nothing(
() => ()
);
macro_rules! emits_multiple(
() => {
fn f1() -> u32;
fn f2() -> u32;
}
);
mod defs {
#[no_mangle] extern fn f1() -> u32 { 1 }
#[no_mangle] extern fn f2() -> u32 { 2 }
}
fn main() {
assert_eq!(unsafe { rust_get_test_int() }, 0isize);
assert_eq!(unsafe { rust_get_test_int() }, 1);
assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEFu32);
assert_eq!(unsafe { f1() }, 1);
assert_eq!(unsafe { f2() }, 2);
}
#[link(name = "rust_test_helpers", kind = "static")]
extern {
returns_isize!(rust_get_test_int);
//~^ ERROR macro invocations in `extern {}` blocks are experimental
takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
//~^ ERROR macro invocations in `extern {}` blocks are experimental
emits_nothing!();
//~^ ERROR macro invocations in `extern {}` blocks are experimental
emits_multiple!();
}

View File

@ -1,26 +0,0 @@
// force-host
// no-prefer-dynamic
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro_attribute]
pub fn nop_attr(_attr: TokenStream, input: TokenStream) -> TokenStream {
assert!(_attr.to_string().is_empty());
input
}
#[proc_macro_attribute]
pub fn no_output(_attr: TokenStream, _input: TokenStream) -> TokenStream {
assert!(_attr.to_string().is_empty());
assert!(!_input.to_string().is_empty());
"".parse().unwrap()
}
#[proc_macro]
pub fn emit_input(input: TokenStream) -> TokenStream {
input
}

View File

@ -7,8 +7,6 @@
// normalize-stdout-test "bytes\([^0]\w*\.\.(\w+)\)" -> "bytes(LO..$1)"
// normalize-stdout-test "bytes\((\w+)\.\.[^0]\w*\)" -> "bytes($1..HI)"
#![feature(proc_macro_hygiene)]
#[macro_use]
extern crate test_macros;
extern crate dollar_crate_external;

View File

@ -1,7 +1,5 @@
// aux-build:lifetimes.rs
#![feature(proc_macro_hygiene)]
extern crate lifetimes;
use lifetimes::*;

View File

@ -1,5 +1,5 @@
error: expected type, found `'`
--> $DIR/lifetimes.rs:9:10
--> $DIR/lifetimes.rs:7:10
|
LL | type A = single_quote_alone!();
| ^^^^^^^^^^^^^^^^^^^^^ this macro call doesn't expand to a type

View File

@ -0,0 +1,6 @@
extern {
#[derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
fn f();
}
fn main() {}

View File

@ -0,0 +1,8 @@
error: `derive` may only be applied to structs, enums and unions
--> $DIR/macros-in-extern-derive.rs:2:5
|
LL | #[derive(Copy)]
| ^^^^^^^^^^^^^^^
error: aborting due to previous error

View File

@ -1,25 +0,0 @@
// run-pass
// aux-build:test-macros-rpass.rs
// ignore-wasm32
#![feature(macros_in_extern)]
extern crate test_macros_rpass as test_macros;
use test_macros::{nop_attr, no_output, emit_input};
fn main() {
assert_eq!(unsafe { rust_get_test_int() }, 1isize);
assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEF);
}
#[link(name = "rust_test_helpers", kind = "static")]
extern {
#[no_output]
fn some_definitely_unknown_symbol_which_should_be_removed();
#[nop_attr]
fn rust_get_test_int() -> isize;
emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
}

View File

@ -1,3 +1,4 @@
// run-pass
// aux-build:test-macros.rs
// ignore-wasm32
@ -5,20 +6,17 @@
extern crate test_macros;
fn main() {
assert_eq!(unsafe { rust_get_test_int() }, 0isize);
assert_eq!(unsafe { rust_get_test_int() }, 1);
assert_eq!(unsafe { rust_dbg_extern_identity_u32(0xDEADBEEF) }, 0xDEADBEEF);
}
#[link(name = "rust_test_helpers", kind = "static")]
extern {
#[empty_attr]
//~^ ERROR macro invocations in `extern {}` blocks are experimental
fn some_definitely_unknown_symbol_which_should_be_removed();
#[identity_attr]
//~^ ERROR macro invocations in `extern {}` blocks are experimental
fn rust_get_test_int() -> isize;
identity!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
//~^ ERROR macro invocations in `extern {}` blocks are experimental
}

View File

@ -0,0 +1,11 @@
// check-pass
// aux-build:test-macros.rs
#[macro_use]
extern crate test_macros;
const C: identity!(u8) = 10;
fn main() {
let c: u8 = C;
}

View File

@ -50,7 +50,6 @@ fn attrs() {
}
fn main() {
let _x: identity!(u32) = 3; //~ ERROR: procedural macros cannot be expanded to types
if let identity!(Some(_x)) = Some(3) {}
//~^ ERROR: procedural macros cannot be expanded to patterns

View File

@ -94,17 +94,8 @@ LL | let _x = #[identity_attr] println!();
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
error[E0658]: procedural macros cannot be expanded to types
--> $DIR/proc-macro-gates.rs:53:13
|
LL | let _x: identity!(u32) = 3;
| ^^^^^^^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
error[E0658]: procedural macros cannot be expanded to patterns
--> $DIR/proc-macro-gates.rs:54:12
--> $DIR/proc-macro-gates.rs:53:12
|
LL | if let identity!(Some(_x)) = Some(3) {}
| ^^^^^^^^^^^^^^^^^^^
@ -113,7 +104,7 @@ LL | if let identity!(Some(_x)) = Some(3) {}
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
error[E0658]: procedural macros cannot be expanded to statements
--> $DIR/proc-macro-gates.rs:57:5
--> $DIR/proc-macro-gates.rs:56:5
|
LL | empty!(struct S;);
| ^^^^^^^^^^^^^^^^^^
@ -122,7 +113,7 @@ LL | empty!(struct S;);
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
error[E0658]: procedural macros cannot be expanded to statements
--> $DIR/proc-macro-gates.rs:58:5
--> $DIR/proc-macro-gates.rs:57:5
|
LL | empty!(let _x = 3;);
| ^^^^^^^^^^^^^^^^^^^^
@ -131,7 +122,7 @@ LL | empty!(let _x = 3;);
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
error[E0658]: procedural macros cannot be expanded to expressions
--> $DIR/proc-macro-gates.rs:60:14
--> $DIR/proc-macro-gates.rs:59:14
|
LL | let _x = identity!(3);
| ^^^^^^^^^^^^
@ -140,7 +131,7 @@ LL | let _x = identity!(3);
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
error[E0658]: procedural macros cannot be expanded to expressions
--> $DIR/proc-macro-gates.rs:61:15
--> $DIR/proc-macro-gates.rs:60:15
|
LL | let _x = [empty!(3)];
| ^^^^^^^^^
@ -148,6 +139,6 @@ LL | let _x = [empty!(3)];
= note: for more information, see https://github.com/rust-lang/rust/issues/54727
= help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable
error: aborting due to 17 previous errors
error: aborting due to 16 previous errors
For more information about this error, try `rustc --explain E0658`.