rustc: Stabilize much of the proc_macro feature

This commit stabilizes some of the `proc_macro` language feature as well as a
number of APIs in the `proc_macro` crate as [previously discussed][1]. This
means that on stable Rust you can now define custom procedural macros which
operate as attributes attached to items or `macro_rules!`-like bang-style
invocations. This extends the suite of currently stable procedural macros,
custom derives, with custom attributes and custom bang macros.

Note though that despite the stabilization in this commit procedural macros are
still not usable on stable Rust. To stabilize that we'll need to stabilize at
least part of the `use_extern_macros` feature. Currently you can define a
procedural macro attribute but you can't import it to call it!

A summary of the changes made in this PR (as well as the various consequences)
is:

* The `proc_macro` language and library features are now stable.
* Other APIs not stabilized in the `proc_macro` crate are now named under a
  different feature, such as `proc_macro_diagnostic` or `proc_macro_span`.
* A few checks in resolution for `proc_macro` being enabled have switched over
  to `use_extern_macros` being enabled. This means that code using
  `#![feature(proc_macro)]` today will likely need to move to
  `#![feature(use_extern_macros)]`.

It's intended that this PR, once landed, will be followed up with an attempt to
stabilize a small slice of `use_extern_macros` just for procedural macros to
make this feature 100% usable on stable.

[1]: https://internals.rust-lang.org/t/help-stabilize-a-subset-of-macros-2-0/7252
This commit is contained in:
Alex Crichton 2018-07-03 15:36:31 -07:00
parent 3d5753fda1
commit 65f3007fa8
80 changed files with 241 additions and 515 deletions

View file

@ -12,7 +12,7 @@
// ignore-stage1
// compile-flags: -D crate-not-okay
#![feature(plugin, custom_attribute)] //~ ERROR crate is not marked with #![crate_okay]
#![feature(plugin)] //~ ERROR crate is not marked with #![crate_okay]
#![plugin(lint_for_crate)]
pub fn main() { }

View file

@ -13,7 +13,7 @@
//! Attributes producing expressions in invalid locations
#![feature(proc_macro, stmt_expr_attributes, proc_macro_expr)]
#![feature(use_extern_macros, stmt_expr_attributes, proc_macro_expr)]
extern crate attr_stmt_expr;
use attr_stmt_expr::{duplicate, no_output};

View file

@ -11,7 +11,7 @@
// aux-build:attr-stmt-expr.rs
// ignore-stage1
#![feature(proc_macro, proc_macro_expr)]
#![feature(use_extern_macros, proc_macro_expr)]
extern crate attr_stmt_expr;
use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr};

View file

@ -11,7 +11,7 @@
// aux-build:attribute-with-error.rs
// ignore-stage1
#![feature(proc_macro)]
#![feature(use_extern_macros)]
extern crate attribute_with_error;

View file

@ -10,23 +10,25 @@
// aux-build:attributes-included.rs
// ignore-stage1
// compile-pass
#![feature(proc_macro, rustc_attrs, proc_macro_path_invoc)]
#![feature(use_extern_macros)]
#![warn(unused)]
extern crate attributes_included;
#[attributes_included::bar]
use attributes_included::*;
#[bar]
#[inline]
/// doc
#[attributes_included::foo]
#[foo]
#[inline]
/// doc
fn foo() {
let a: i32 = "foo"; //~ WARN: unused variable
}
#[rustc_error]
fn main() { //~ ERROR: compilation successful
fn main() {
foo()
}

View file

@ -10,7 +10,6 @@
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -10,7 +10,7 @@
// force-host
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -12,7 +12,6 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;

View file

@ -11,7 +11,6 @@
// force-host
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -10,7 +10,7 @@
// force-host
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -10,7 +10,7 @@
// force-host
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -12,7 +12,6 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;
use proc_macro::TokenStream;

View file

@ -11,7 +11,6 @@
// force-host
// no-prefer-dynamic
#![feature(proc_macro, proc_macro_lib)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -11,7 +11,6 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;

View file

@ -12,7 +12,6 @@
// force-host
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;

View file

@ -11,7 +11,6 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;

View file

@ -1,23 +0,0 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:attr_proc_macro.rs
#![feature(use_extern_macros)]
extern crate attr_proc_macro;
use attr_proc_macro::attr_proc_macro;
#[attr_proc_macro]
//~^ ERROR: attribute procedural macros are experimental
struct Foo;
fn main() {
let _ = Foo;
}

View file

@ -13,7 +13,7 @@
// FIXME: https://github.com/rust-lang/rust/issues/41430
// This is a temporary regression test for the ICE reported in #41211
#![feature(proc_macro)]
#![feature(use_extern_macros)]
#![emit_unchanged]
//~^ ERROR: cannot find attribute macro `emit_unchanged` in this scope
extern crate issue_41211;

View file

@ -9,7 +9,7 @@
// except according to those terms.
// aux-build:attr_proc_macro.rs
#![feature(proc_macro)]
#![feature(use_extern_macros)]
#[macro_use] extern crate attr_proc_macro;

View file

@ -12,7 +12,7 @@
// ignore-stage1
// ignore-wasm32
#![feature(proc_macro)]
#![feature(use_extern_macros)]
extern crate test_macros;

View file

@ -10,7 +10,7 @@
// aux-build:more-gates.rs
#![feature(proc_macro)]
#![feature(use_extern_macros)]
extern crate more_gates as foo;

View file

@ -9,9 +9,10 @@
// except according to those terms.
// aux-build:attr_proc_macro.rs
// ignore-tidy-linelength
#![feature(proc_macro, custom_attribute)]
//~^ ERROR Cannot use `#![feature(proc_macro)]` and `#![feature(custom_attribute)] at the same time
#![feature(use_extern_macros, custom_attribute)]
//~^ ERROR Cannot use `#![feature(use_extern_macros)]` and `#![feature(custom_attribute)] at the same time
extern crate attr_proc_macro;
use attr_proc_macro::attr_proc_macro;

View file

@ -16,7 +16,7 @@
// gate-test-proc_macro_mod
// gate-test-proc_macro_gen
#![feature(proc_macro, stmt_expr_attributes)]
#![feature(use_extern_macros, stmt_expr_attributes)]
extern crate proc_macro_gates as foo;

View file

@ -35,7 +35,7 @@ use rustc_plugin::Registry;
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_syntax_extension(
Symbol::intern("derive_TotalSum"),
Symbol::intern("rustc_derive_TotalSum"),
MultiDecorator(box expand));
}

View file

@ -11,7 +11,7 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro, proc_macro_non_items)]
#![feature(use_extern_macros, proc_macro_non_items, proc_macro_quote)]
extern crate proc_macro;

View file

@ -57,19 +57,19 @@ declare_lint!(CRATE_NOT_GREEN, Warn, "crate not marked with #![crate_green]");
fake_lint_pass! {
PassOkay,
lint_array!(CRATE_NOT_OKAY), // Single lint
"crate_okay"
"rustc_crate_okay"
}
fake_lint_pass! {
PassRedBlue,
lint_array!(CRATE_NOT_RED, CRATE_NOT_BLUE), // Multiple lints
"crate_red", "crate_blue"
"rustc_crate_red", "rustc_crate_blue"
}
fake_lint_pass! {
PassGreyGreen,
lint_array!(CRATE_NOT_GREY, CRATE_NOT_GREEN, ), // Trailing comma
"crate_grey", "crate_green"
"rustc_crate_grey", "rustc_crate_green"
}
#[plugin_registrar]

View file

@ -37,13 +37,13 @@ pub fn plugin_registrar(reg: &mut Registry) {
reg.register_macro("make_a_1", expand_make_a_1);
reg.register_macro("identity", expand_identity);
reg.register_syntax_extension(
Symbol::intern("into_multi_foo"),
Symbol::intern("rustc_into_multi_foo"),
MultiModifier(Box::new(expand_into_foo_multi)));
reg.register_syntax_extension(
Symbol::intern("duplicate"),
Symbol::intern("rustc_duplicate"),
MultiDecorator(Box::new(expand_duplicate)));
reg.register_syntax_extension(
Symbol::intern("caller"),
Symbol::intern("rustc_caller"),
MultiDecorator(Box::new(expand_caller)));
}

View file

@ -11,7 +11,7 @@
// aux-build:custom_derive_plugin_attr.rs
// ignore-stage1
#![feature(plugin, custom_derive, custom_attribute)]
#![feature(plugin, custom_derive, rustc_attrs)]
#![plugin(custom_derive_plugin_attr)]
trait TotalSum {
@ -32,7 +32,7 @@ impl TotalSum for Seven {
}
}
#[derive(TotalSum)]
#[rustc_derive_TotalSum]
struct Foo {
seven: Seven,
bar: Bar,
@ -41,7 +41,7 @@ struct Foo {
nan: NaN,
}
#[derive(TotalSum)]
#[rustc_derive_TotalSum]
struct Bar {
quux: isize,
bleh: isize,

View file

@ -12,12 +12,12 @@
// ignore-stage1
// compile-flags: -D crate-not-okay
#![feature(plugin, custom_attribute)]
#![feature(plugin, rustc_attrs)]
#![plugin(lint_for_crate)]
#![crate_okay]
#![crate_blue]
#![crate_red]
#![crate_grey]
#![crate_green]
#![rustc_crate_okay]
#![rustc_crate_blue]
#![rustc_crate_red]
#![rustc_crate_grey]
#![rustc_crate_green]
pub fn main() { }

View file

@ -11,7 +11,7 @@
// aux-build:macro_crate_test.rs
// ignore-stage1
#![feature(plugin, custom_attribute, attr_literals)]
#![feature(plugin, rustc_attrs, attr_literals)]
#![plugin(macro_crate_test)]
#[macro_use]
@ -30,16 +30,16 @@ extern crate macro_crate_test;
// This results in a function named `simple` that calls `f(1, "hello", 3.14)`.
// As a result, the expression `simple()` evaluates to `(1, "helllo", 3.14)`.
#[caller(simple, 1, "hello", 3.14)]
#[caller(simple1, 2, "bye", 6.28)]
#[caller(simple2, 3, "hi", 1.01)]
#[rustc_caller(simple, 1, "hello", 3.14)]
#[rustc_caller(simple1, 2, "bye", 6.28)]
#[rustc_caller(simple2, 3, "hi", 1.01)]
fn f(num: isize, string: &'static str, float: f32) -> (isize, &'static str, f32) {
(num, string, float)
}
#[caller(complex, true, 10)]
#[caller(complex1, false, 15)]
#[caller(complex2, true, 20)]
#[rustc_caller(complex, true, 10)]
#[rustc_caller(complex1, false, 15)]
#[rustc_caller(complex2, true, 20)]
fn g(emit: bool, num: i32) -> Option<i32> {
match emit {
true => Some(num),

View file

@ -11,7 +11,7 @@
// aux-build:macro_crate_test.rs
// ignore-stage1
#![feature(plugin, custom_attribute)]
#![feature(plugin, rustc_attrs)]
#![plugin(macro_crate_test)]
#[macro_use]
@ -20,27 +20,27 @@ extern crate macro_crate_test;
// The duplicate macro will create a copy of the item with the given identifier.
#[duplicate(MyCopy)]
#[rustc_duplicate(MyCopy)]
struct MyStruct {
number: i32
}
trait TestTrait {
#[duplicate(TestType2)]
#[rustc_duplicate(TestType2)]
type TestType;
#[duplicate(required_fn2)]
#[rustc_duplicate(required_fn2)]
fn required_fn(&self);
#[duplicate(provided_fn2)]
#[rustc_duplicate(provided_fn2)]
fn provided_fn(&self) { }
}
impl TestTrait for MyStruct {
#[duplicate(TestType2)]
#[rustc_duplicate(TestType2)]
type TestType = f64;
#[duplicate(required_fn2)]
#[rustc_duplicate(required_fn2)]
fn required_fn(&self) { }
}

View file

@ -11,26 +11,26 @@
// aux-build:macro_crate_test.rs
// ignore-stage1
#![feature(plugin, custom_attribute)]
#![feature(plugin, rustc_attrs)]
#![plugin(macro_crate_test)]
#[macro_use] #[no_link]
extern crate macro_crate_test;
#[derive(PartialEq, Clone, Debug)]
#[into_multi_foo]
#[rustc_into_multi_foo]
fn foo() -> AnotherFakeTypeThatHadBetterGoAway {}
// Check that the `#[into_multi_foo]`-generated `foo2` is configured away
fn foo2() {}
trait Qux {
#[into_multi_foo]
#[rustc_into_multi_foo]
fn bar();
}
impl Qux for i32 {
#[into_multi_foo]
#[rustc_into_multi_foo]
fn bar() {}
}

View file

@ -12,14 +12,13 @@
// ignore-stage1
#![allow(warnings)]
#![feature(proc_macro, proc_macro_path_invoc)]
#![feature(use_extern_macros)]
extern crate attr_args;
use attr_args::attr_with_args;
use attr_args::{attr_with_args, identity};
#[attr_with_args(text = "Hello, world!")]
fn foo() {}
#[::attr_args::identity(
fn main() { assert_eq!(foo(), "Hello, world!"); })]
#[identity(fn main() { assert_eq!(foo(), "Hello, world!"); })]
struct Dummy;

View file

@ -12,7 +12,7 @@
// ignore-stage1
// revisions: foo bar
#![feature(proc_macro)]
#![feature(use_extern_macros)]
extern crate attr_cfg;
use attr_cfg::attr_cfg;

View file

@ -11,12 +11,14 @@
// aux-build:attr-on-trait.rs
// ignore-stage1
#![feature(proc_macro, proc_macro_path_invoc)]
#![feature(use_extern_macros)]
extern crate attr_on_trait;
use attr_on_trait::foo;
trait Foo {
#[attr_on_trait::foo]
#[foo]
fn foo() {}
}

View file

@ -11,7 +11,7 @@
// aux-build:attr-stmt-expr.rs
// ignore-stage1
#![feature(proc_macro, stmt_expr_attributes, proc_macro_stmt, proc_macro_expr)]
#![feature(use_extern_macros, stmt_expr_attributes, proc_macro_stmt, proc_macro_expr)]
extern crate attr_stmt_expr;
use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr,

View file

@ -9,7 +9,7 @@
// except according to those terms.
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -9,7 +9,7 @@
// except according to those terms.
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -10,7 +10,6 @@
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -10,7 +10,6 @@
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -9,7 +9,7 @@
// except according to those terms.
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -11,7 +11,6 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;
use proc_macro::*;

View file

@ -10,7 +10,7 @@
// no-prefer-dynamic
#![feature(proc_macro, proc_macro_non_items)]
#![feature(proc_macro_non_items, proc_macro_quote, use_extern_macros)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -11,7 +11,6 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;

View file

@ -10,7 +10,7 @@
// no-prefer-dynamic
#![feature(proc_macro, proc_macro_non_items)]
#![feature(use_extern_macros, proc_macro_quote, proc_macro_non_items)]
#![crate_type = "proc-macro"]
extern crate proc_macro as proc_macro_renamed; // This does not break `quote!`

View file

@ -7,6 +7,7 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(box_syntax, plugin, plugin_registrar, rustc_private)]
#![feature(macro_vis_matcher)]
#![feature(macro_at_most_once_rep)]

View file

@ -11,7 +11,6 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;

View file

@ -11,7 +11,6 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;
use proc_macro::TokenStream;

View file

@ -10,7 +10,6 @@
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -11,7 +11,6 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;

View file

@ -10,7 +10,6 @@
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -11,7 +11,6 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;

View file

@ -12,7 +12,7 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
#![feature(proc_macro_span)]
extern crate proc_macro;

View file

@ -11,7 +11,6 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;

View file

@ -11,7 +11,7 @@
// aux-build:call-site.rs
// ignore-stage1
#![feature(proc_macro, proc_macro_non_items)]
#![feature(proc_macro_non_items, use_extern_macros)]
extern crate call_site;
use call_site::*;

View file

@ -11,7 +11,7 @@
// aux-build:derive-b.rs
// ignore-stage1
#![feature(proc_macro, proc_macro_path_invoc)]
#![feature(use_extern_macros, proc_macro_path_invoc)]
extern crate derive_b;

View file

@ -10,7 +10,7 @@
// aux-build:gen-lifetime-token.rs
#![feature(proc_macro)]
#![feature(use_extern_macros)]
extern crate gen_lifetime_token as bar;

View file

@ -11,7 +11,7 @@
// aux-build:issue-42708.rs
// ignore-stage1
#![feature(decl_macro, proc_macro, proc_macro_path_invoc)]
#![feature(decl_macro, use_extern_macros, proc_macro_path_invoc)]
#![allow(unused)]
extern crate issue_42708;

View file

@ -11,7 +11,7 @@
// aux-build:issue-50061.rs
// ignore-stage1
#![feature(proc_macro, proc_macro_path_invoc, decl_macro)]
#![feature(use_extern_macros, proc_macro_path_invoc, decl_macro)]
extern crate issue_50061;

View file

@ -11,7 +11,7 @@
// aux-build:lifetimes.rs
// ignore-stage1
#![feature(proc_macro)]
#![feature(use_extern_macros)]
extern crate lifetimes;
use lifetimes::*;

View file

@ -12,7 +12,7 @@
// ignore-stage1
// ignore-wasm32
#![feature(proc_macro, macros_in_extern)]
#![feature(use_extern_macros, macros_in_extern)]
extern crate test_macros;

View file

@ -10,7 +10,7 @@
// aux-build:modify-ast.rs
#![feature(proc_macro)]
#![feature(use_extern_macros)]
extern crate modify_ast;

View file

@ -10,7 +10,7 @@
// aux-build:not-joint.rs
#![feature(proc_macro)]
#![feature(use_extern_macros)]
extern crate not_joint as bar;
use bar::{tokens, nothing};

View file

@ -12,7 +12,7 @@
// ignore-stage1
// ignore-cross-compile
#![feature(proc_macro, proc_macro_non_items)]
#![feature(use_extern_macros, proc_macro_non_items)]
extern crate proc_macro_def;

View file

@ -11,8 +11,8 @@
// force-host
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
#![feature(proc_macro_raw_ident)]
extern crate proc_macro;
use proc_macro::*;

View file

@ -10,7 +10,7 @@
// aux-build:lifetimes.rs
#![feature(proc_macro, proc_macro_non_items)]
#![feature(use_extern_macros, proc_macro_non_items)]
extern crate lifetimes;

View file

@ -11,7 +11,6 @@
// no-prefer-dynamic
#![crate_type = "proc-macro"]
#![feature(proc_macro)]
extern crate proc_macro;
use proc_macro::*;

View file

@ -9,7 +9,8 @@
// except according to those terms.
// no-prefer-dynamic
#![feature(proc_macro)]
#![feature(proc_macro_diagnostic, proc_macro_span)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -9,8 +9,9 @@
// except according to those terms.
// no-prefer-dynamic
#![feature(proc_macro)]
#![crate_type = "proc-macro"]
#![feature(proc_macro_diagnostic, proc_macro_span)]
extern crate proc_macro;

View file

@ -12,7 +12,7 @@
// aux-build:generate-mod.rs
#![feature(proc_macro, proc_macro_gen, proc_macro_path_invoc)]
#![feature(use_extern_macros, proc_macro_gen, proc_macro_path_invoc)]
extern crate generate_mod;

View file

@ -10,7 +10,7 @@
// aux-build:macro-brackets.rs
#![feature(proc_macro)]
#![feature(use_extern_macros)]
extern crate macro_brackets as bar;
use bar::doit;

View file

@ -10,7 +10,7 @@
// no-prefer-dynamic
#![feature(proc_macro)]
#![feature(use_extern_macros)]
#![crate_type = "proc-macro"]
extern crate proc_macro;

View file

@ -13,7 +13,7 @@
// aux-build:attr_proc_macro.rs
// aux-build:bang_proc_macro.rs
#![feature(proc_macro)]
#![feature(use_extern_macros)]
#[macro_use]
extern crate derive_foo;