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

@ -1,241 +0,0 @@
# `proc_macro`
The tracking issue for this feature is: [#38356]
[#38356]: https://github.com/rust-lang/rust/issues/38356
------------------------
This feature flag guards the new procedural macro features as laid out by [RFC 1566], which alongside the now-stable
[custom derives], provide stabilizable alternatives to the compiler plugin API (which requires the use of
perma-unstable internal APIs) for programmatically modifying Rust code at compile-time.
The two new procedural macro kinds are:
* Function-like procedural macros which are invoked like regular declarative macros, and:
* Attribute-like procedural macros which can be applied to any item which built-in attributes can
be applied to, and which can take arguments in their invocation as well.
Additionally, this feature flag implicitly enables the [`use_extern_macros`](language-features/use-extern-macros.html) feature,
which allows macros to be imported like any other item with `use` statements, as compared to
applying `#[macro_use]` to an `extern crate` declaration. It is important to note that procedural macros may
**only** be imported in this manner, and will throw an error otherwise.
You **must** declare the `proc_macro` feature in both the crate declaring these new procedural macro kinds as well as
in any crates that use them.
### Common Concepts
As with custom derives, procedural macros may only be declared in crates of the `proc-macro` type, and must be public
functions. No other public items may be declared in `proc-macro` crates, but private items are fine.
To declare your crate as a `proc-macro` crate, simply add:
```toml
[lib]
proc-macro = true
```
to your `Cargo.toml`.
Unlike custom derives, however, the name of the function implementing the procedural macro is used directly as the
procedural macro's name, so choose carefully.
Additionally, both new kinds of procedural macros return a `TokenStream` which *wholly* replaces the original
invocation and its input.
#### Importing
As referenced above, the new procedural macros are not meant to be imported via `#[macro_use]` and will throw an
error if they are. Instead, they are meant to be imported like any other item in Rust, with `use` statements:
```rust,ignore
#![feature(proc_macro)]
// Where `my_proc_macros` is some crate of type `proc_macro`
extern crate my_proc_macros;
// And declares a `#[proc_macro] pub fn my_bang_macro()` at its root.
use my_proc_macros::my_bang_macro;
fn main() {
println!("{}", my_bang_macro!());
}
```
#### Error Reporting
Any panics in a procedural macro implementation will be caught by the compiler and turned into an error message pointing
to the problematic invocation. Thus, it is important to make your panic messages as informative as possible: use
`Option::expect` instead of `Option::unwrap` and `Result::expect` instead of `Result::unwrap`, and inform the user of
the error condition as unambiguously as you can.
#### `TokenStream`
The `proc_macro::TokenStream` type is hardcoded into the signatures of procedural macro functions for both input and
output. It is a wrapper around the compiler's internal representation for a given chunk of Rust code.
### Function-like Procedural Macros
These are procedural macros that are invoked like regular declarative macros. They are declared as public functions in
crates of the `proc_macro` type and using the `#[proc_macro]` attribute. The name of the declared function becomes the
name of the macro as it is to be imported and used. The function must be of the kind `fn(TokenStream) -> TokenStream`
where the sole argument is the input to the macro and the return type is the macro's output.
This kind of macro can expand to anything that is valid for the context it is invoked in, including expressions and
statements, as well as items.
**Note**: invocations of this kind of macro require a wrapping `[]`, `{}` or `()` like regular macros, but these do not
appear in the input, only the tokens between them. The tokens between the braces do not need to be valid Rust syntax.
<span class="filename">my_macro_crate/src/lib.rs</span>
```rust,ignore
#![feature(proc_macro)]
// This is always necessary to get the `TokenStream` typedef.
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro]
pub fn say_hello(_input: TokenStream) -> TokenStream {
// This macro will accept any input because it ignores it.
// To enforce correctness in macros which don't take input,
// you may want to add `assert!(_input.to_string().is_empty());`.
"println!(\"Hello, world!\")".parse().unwrap()
}
```
<span class="filename">my_macro_user/Cargo.toml</span>
```toml
[dependencies]
my_macro_crate = { path = "<relative path to my_macro_crate>" }
```
<span class="filename">my_macro_user/src/lib.rs</span>
```rust,ignore
#![feature(proc_macro)]
extern crate my_macro_crate;
use my_macro_crate::say_hello;
fn main() {
say_hello!();
}
```
As expected, this prints `Hello, world!`.
### Attribute-like Procedural Macros
These are arguably the most powerful flavor of procedural macro as they can be applied anywhere attributes are allowed.
They are declared as public functions in crates of the `proc-macro` type, using the `#[proc_macro_attribute]` attribute.
The name of the function becomes the name of the attribute as it is to be imported and used. The function must be of the
kind `fn(TokenStream, TokenStream) -> TokenStream` where:
The first argument represents any metadata for the attribute (see [the reference chapter on attributes][refr-attr]).
Only the metadata itself will appear in this argument, for example:
* `#[my_macro]` will get an empty string.
* `#[my_macro = "string"]` will get `= "string"`.
* `#[my_macro(ident)]` will get `(ident)`.
* etc.
The second argument is the item that the attribute is applied to. It can be a function, a type definition,
an impl block, an `extern` block, or a module—attribute invocations can take the inner form (`#![my_attr]`)
or outer form (`#[my_attr]`).
The return type is the output of the macro which *wholly* replaces the item it was applied to. Thus, if your intention
is to merely modify an item, it *must* be copied to the output. The output must be an item; expressions, statements
and bare blocks are not allowed.
There is no restriction on how many items an attribute-like procedural macro can emit as long as they are valid in
the given context.
<span class="filename">my_macro_crate/src/lib.rs</span>
```rust,ignore
#![feature(proc_macro)]
extern crate proc_macro;
use proc_macro::TokenStream;
/// Adds a `/// ### Panics` docstring to the end of the input's documentation
///
/// Does not assert that its receiver is a function or method.
#[proc_macro_attribute]
pub fn panics_note(args: TokenStream, input: TokenStream) -> TokenStream {
let args = args.to_string();
let mut input = input.to_string();
assert!(args.starts_with("= \""), "`#[panics_note]` requires an argument of the form \
`#[panics_note = \"panic note here\"]`");
// Get just the bare note string
let panics_note = args.trim_matches(&['=', ' ', '"'][..]);
// The input will include all docstrings regardless of where the attribute is placed,
// so we need to find the last index before the start of the item
let insert_idx = idx_after_last_docstring(&input);
// And insert our `### Panics` note there so it always appears at the end of an item's docs
input.insert_str(insert_idx, &format!("/// # Panics \n/// {}\n", panics_note));
input.parse().unwrap()
}
// `proc-macro` crates can contain any kind of private item still
fn idx_after_last_docstring(input: &str) -> usize {
// Skip docstring lines to find the start of the item proper
input.lines().skip_while(|line| line.trim_left().starts_with("///")).next()
// Find the index of the first non-docstring line in the input
// Note: assumes this exact line is unique in the input
.and_then(|line_after| input.find(line_after))
// No docstrings in the input
.unwrap_or(0)
}
```
<span class="filename">my_macro_user/Cargo.toml</span>
```toml
[dependencies]
my_macro_crate = { path = "<relative path to my_macro_crate>" }
```
<span class="filename">my_macro_user/src/lib.rs</span>
```rust,ignore
#![feature(proc_macro)]
extern crate my_macro_crate;
use my_macro_crate::panics_note;
/// Do the `foo` thing.
#[panics_note = "Always."]
pub fn foo() {
panic!()
}
```
Then the rendered documentation for `pub fn foo` will look like this:
> `pub fn foo()`
>
> ----
> Do the `foo` thing.
> # Panics
> Always.
[RFC 1566]: https://github.com/rust-lang/rfcs/blob/master/text/1566-proc-macros.md
[custom derives]: https://doc.rust-lang.org/book/procedural-macros.html
[rust-lang/rust#41430]: https://github.com/rust-lang/rust/issues/41430
[refr-attr]: https://doc.rust-lang.org/reference/attributes.html

View File

@ -13,7 +13,7 @@ use Span;
use rustc_errors as rustc;
/// An enum representing a diagnostic level.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
#[derive(Copy, Clone, Debug)]
pub enum Level {
/// An error.
@ -30,7 +30,7 @@ pub enum Level {
/// A structure representing a diagnostic message and associated children
/// messages.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
#[derive(Clone, Debug)]
pub struct Diagnostic {
level: Level,
@ -43,7 +43,7 @@ macro_rules! diagnostic_child_methods {
($spanned:ident, $regular:ident, $level:expr) => (
/// Add a new child diagnostic message to `self` with the level
/// identified by this methods name with the given `span` and `message`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
pub fn $spanned<T: Into<String>>(mut self, span: Span, message: T) -> Diagnostic {
self.children.push(Diagnostic::spanned(span, $level, message));
self
@ -51,7 +51,7 @@ macro_rules! diagnostic_child_methods {
/// Add a new child diagnostic message to `self` with the level
/// identified by this method's name with the given `message`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
pub fn $regular<T: Into<String>>(mut self, message: T) -> Diagnostic {
self.children.push(Diagnostic::new($level, message));
self
@ -61,7 +61,7 @@ macro_rules! diagnostic_child_methods {
impl Diagnostic {
/// Create a new diagnostic with the given `level` and `message`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic {
Diagnostic {
level: level,
@ -73,7 +73,7 @@ impl Diagnostic {
/// Create a new diagnostic with the given `level` and `message` pointing to
/// the given `span`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
pub fn spanned<T: Into<String>>(span: Span, level: Level, message: T) -> Diagnostic {
Diagnostic {
level: level,
@ -89,13 +89,13 @@ impl Diagnostic {
diagnostic_child_methods!(span_help, help, Level::Help);
/// Returns the diagnostic `level` for `self`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
pub fn level(&self) -> Level {
self.level
}
/// Emit the diagnostic.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
pub fn emit(self) {
::__internal::with_sess(move |sess, _| {
let handler = &sess.span_diagnostic;

View File

@ -46,7 +46,7 @@ extern crate rustc_data_structures;
mod diagnostic;
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
pub use diagnostic::{Diagnostic, Level};
use std::{ascii, fmt, iter};
@ -94,13 +94,13 @@ impl !Sync for LexError {}
impl TokenStream {
/// Returns an empty `TokenStream` containing no token trees.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn new() -> TokenStream {
TokenStream(tokenstream::TokenStream::empty())
}
/// Checks if this `TokenStream` is empty.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
@ -146,7 +146,7 @@ impl fmt::Debug for TokenStream {
}
/// Creates a token stream containing a single token tree.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl From<TokenTree> for TokenStream {
fn from(tree: TokenTree) -> TokenStream {
TokenStream(tree.to_internal())
@ -154,7 +154,7 @@ impl From<TokenTree> for TokenStream {
}
/// Collects a number of token trees into a single stream.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl iter::FromIterator<TokenTree> for TokenStream {
fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
trees.into_iter().map(TokenStream::from).collect()
@ -175,7 +175,7 @@ impl iter::FromIterator<TokenStream> for TokenStream {
}
/// Public implementation details for the `TokenStream` type, such as iterators.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub mod token_stream {
use syntax::tokenstream;
use {TokenTree, TokenStream, Delimiter};
@ -184,13 +184,13 @@ pub mod token_stream {
/// The iteration is "shallow", e.g. the iterator doesn't recurse into delimited groups,
/// and returns whole groups as token trees.
#[derive(Clone)]
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub struct IntoIter {
cursor: tokenstream::Cursor,
stack: Vec<TokenTree>,
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl Iterator for IntoIter {
type Item = TokenTree;
@ -219,7 +219,7 @@ pub mod token_stream {
}
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl IntoIterator for TokenStream {
type Item = TokenTree;
type IntoIter = IntoIter;
@ -238,7 +238,7 @@ pub mod token_stream {
/// To quote `$` itself, use `$$`.
///
/// This is a dummy macro, the actual implementation is in quote::Quoter
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_quote", issue = "38356")]
#[macro_export]
macro_rules! quote { () => {} }
@ -248,26 +248,26 @@ mod quote;
/// Quote a `Span` into a `TokenStream`.
/// This is needed to implement a custom quoter.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_quote", issue = "38356")]
pub fn quote_span(span: Span) -> TokenStream {
quote::Quote::quote(span)
}
/// A region of source code, along with macro expansion information.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
#[derive(Copy, Clone)]
pub struct Span(syntax_pos::Span);
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Send for Span {}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Sync for Span {}
macro_rules! diagnostic_method {
($name:ident, $level:expr) => (
/// Create a new `Diagnostic` with the given `message` at the span
/// `self`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
pub fn $name<T: Into<String>>(self, message: T) -> Diagnostic {
Diagnostic::spanned(self, $level, message)
}
@ -276,7 +276,7 @@ macro_rules! diagnostic_method {
impl Span {
/// A span that resolves at the macro definition site.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub fn def_site() -> Span {
::__internal::with_sess(|_, data| data.def_site)
}
@ -285,13 +285,13 @@ impl Span {
/// Identifiers created with this span will be resolved as if they were written
/// directly at the macro call location (call-site hygiene) and other code
/// at the macro call site will be able to refer to them as well.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn call_site() -> Span {
::__internal::with_sess(|_, data| data.call_site)
}
/// The original source file into which this span points.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub fn source_file(&self) -> SourceFile {
SourceFile {
filemap: __internal::lookup_char_pos(self.0.lo()).file,
@ -300,7 +300,7 @@ impl Span {
/// The `Span` for the tokens in the previous macro expansion from which
/// `self` was generated from, if any.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub fn parent(&self) -> Option<Span> {
self.0.parent().map(Span)
}
@ -308,13 +308,13 @@ impl Span {
/// The span for the origin source code that `self` was generated from. If
/// this `Span` wasn't generated from other macro expansions then the return
/// value is the same as `*self`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub fn source(&self) -> Span {
Span(self.0.source_callsite())
}
/// Get the starting line/column in the source file for this span.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub fn start(&self) -> LineColumn {
let loc = __internal::lookup_char_pos(self.0.lo());
LineColumn {
@ -324,7 +324,7 @@ impl Span {
}
/// Get the ending line/column in the source file for this span.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub fn end(&self) -> LineColumn {
let loc = __internal::lookup_char_pos(self.0.hi());
LineColumn {
@ -336,7 +336,7 @@ impl Span {
/// Create a new span encompassing `self` and `other`.
///
/// Returns `None` if `self` and `other` are from different files.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub fn join(&self, other: Span) -> Option<Span> {
let self_loc = __internal::lookup_char_pos(self.0.lo());
let other_loc = __internal::lookup_char_pos(other.0.lo());
@ -348,20 +348,20 @@ impl Span {
/// Creates a new span with the same line/column information as `self` but
/// that resolves symbols as though it were at `other`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub fn resolved_at(&self, other: Span) -> Span {
Span(self.0.with_ctxt(other.0.ctxt()))
}
/// Creates a new span with the same name resolution behavior as `self` but
/// with the line/column information of `other`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub fn located_at(&self, other: Span) -> Span {
other.resolved_at(*self)
}
/// Compares to spans to see if they're equal.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub fn eq(&self, other: &Span) -> bool {
self.0 == other.0
}
@ -373,7 +373,7 @@ impl Span {
}
/// Prints a span in a form convenient for debugging.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl fmt::Debug for Span {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?} bytes({}..{})",
@ -384,33 +384,33 @@ impl fmt::Debug for Span {
}
/// A line-column pair representing the start or end of a `Span`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct LineColumn {
/// The 1-indexed line in the source file on which the span starts or ends (inclusive).
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub line: usize,
/// The 0-indexed column (in UTF-8 characters) in the source file on which
/// the span starts or ends (inclusive).
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub column: usize
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
impl !Send for LineColumn {}
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
impl !Sync for LineColumn {}
/// The source file of a given `Span`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
#[derive(Clone)]
pub struct SourceFile {
filemap: Lrc<FileMap>,
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
impl !Send for SourceFile {}
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
impl !Sync for SourceFile {}
impl SourceFile {
@ -424,14 +424,14 @@ impl SourceFile {
/// the command line, the path as given may not actually be valid.
///
/// [`is_real`]: #method.is_real
# [unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub fn path(&self) -> &FileName {
&self.filemap.name
}
/// Returns `true` if this source file is a real source file, and not generated by an external
/// macro's expansion.
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
pub fn is_real(&self) -> bool {
// This is a hack until intercrate spans are implemented and we can have real source files
// for spans generated in external macros.
@ -440,14 +440,14 @@ impl SourceFile {
}
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
impl AsRef<FileName> for SourceFile {
fn as_ref(&self) -> &FileName {
self.path()
}
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
impl fmt::Debug for SourceFile {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("SourceFile")
@ -457,17 +457,17 @@ impl fmt::Debug for SourceFile {
}
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
impl PartialEq for SourceFile {
fn eq(&self, other: &Self) -> bool {
Lrc::ptr_eq(&self.filemap, &other.filemap)
}
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
impl Eq for SourceFile {}
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_span", issue = "38356")]
impl PartialEq<FileName> for SourceFile {
fn eq(&self, other: &FileName) -> bool {
self.as_ref() == other
@ -475,28 +475,44 @@ impl PartialEq<FileName> for SourceFile {
}
/// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`).
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
#[derive(Clone)]
pub enum TokenTree {
/// A token stream surrounded by bracket delimiters.
Group(Group),
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Group(
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Group
),
/// An identifier.
Ident(Ident),
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Ident(
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Ident
),
/// A single punctuation character (`+`, `,`, `$`, etc.).
Punct(Punct),
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Punct(
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Punct
),
/// A literal character (`'a'`), string (`"hello"`), number (`2.3`), etc.
Literal(Literal),
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Literal(
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Literal
),
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Send for TokenTree {}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Sync for TokenTree {}
impl TokenTree {
/// Returns the span of this tree, delegating to the `span` method of
/// the contained token or a delimited stream.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn span(&self) -> Span {
match *self {
TokenTree::Group(ref t) => t.span(),
@ -511,7 +527,7 @@ impl TokenTree {
/// Note that if this token is a `Group` then this method will not configure
/// the span of each of the internal tokens, this will simply delegate to
/// the `set_span` method of each variant.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn set_span(&mut self, span: Span) {
match *self {
TokenTree::Group(ref mut t) => t.set_span(span),
@ -523,7 +539,7 @@ impl TokenTree {
}
/// Prints token treee in a form convenient for debugging.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl fmt::Debug for TokenTree {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Each of these has the name in the struct type in the derived debug,
@ -537,28 +553,28 @@ impl fmt::Debug for TokenTree {
}
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl From<Group> for TokenTree {
fn from(g: Group) -> TokenTree {
TokenTree::Group(g)
}
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl From<Ident> for TokenTree {
fn from(g: Ident) -> TokenTree {
TokenTree::Ident(g)
}
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl From<Punct> for TokenTree {
fn from(g: Punct) -> TokenTree {
TokenTree::Punct(g)
}
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl From<Literal> for TokenTree {
fn from(g: Literal) -> TokenTree {
TokenTree::Literal(g)
@ -568,7 +584,7 @@ impl From<Literal> for TokenTree {
/// Prints the token tree as a string that is supposed to be losslessly convertible back
/// into the same token tree (modulo spans), except for possibly `TokenTree::Group`s
/// with `Delimiter::None` delimiters and negative numeric literals.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl fmt::Display for TokenTree {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
@ -584,33 +600,37 @@ impl fmt::Display for TokenTree {
///
/// A `Group` internally contains a `TokenStream` which is surrounded by `Delimiter`s.
#[derive(Clone, Debug)]
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub struct Group {
delimiter: Delimiter,
stream: TokenStream,
span: Span,
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Send for Group {}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Sync for Group {}
/// Describes how a sequence of token trees is delimited.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub enum Delimiter {
/// `( ... )`
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Parenthesis,
/// `{ ... }`
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Brace,
/// `[ ... ]`
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Bracket,
/// `Ø ... Ø`
/// An implicit delimiter, that may, for example, appear around tokens coming from a
/// "macro variable" `$var`. It is important to preserve operator priorities in cases like
/// `$var * 3` where `$var` is `1 + 2`.
/// Implicit delimiters may not survive roundtrip of a token stream through a string.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
None,
}
@ -620,7 +640,7 @@ impl Group {
/// This constructor will set the span for this group to
/// `Span::call_site()`. To change the span you can use the `set_span`
/// method below.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group {
Group {
delimiter: delimiter,
@ -630,7 +650,7 @@ impl Group {
}
/// Returns the delimiter of this `Group`
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn delimiter(&self) -> Delimiter {
self.delimiter
}
@ -639,14 +659,14 @@ impl Group {
///
/// Note that the returned token stream does not include the delimiter
/// returned above.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn stream(&self) -> TokenStream {
self.stream.clone()
}
/// Returns the span for the delimiters of this token stream, spanning the
/// entire `Group`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn span(&self) -> Span {
self.span
}
@ -657,7 +677,7 @@ impl Group {
/// This method will **not** set the span of all the internal tokens spanned
/// by this group, but rather it will only set the span of the delimiter
/// tokens at the level of the `Group`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn set_span(&mut self, span: Span) {
self.span = span;
}
@ -666,7 +686,7 @@ impl Group {
/// Prints the group as a string that should be losslessly convertible back
/// into the same group (modulo spans), except for possibly `TokenTree::Group`s
/// with `Delimiter::None` delimiters.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl fmt::Display for Group {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
TokenStream::from(TokenTree::from(self.clone())).fmt(f)
@ -677,7 +697,7 @@ impl fmt::Display for Group {
///
/// Multicharacter operators like `+=` are represented as two instances of `Punct` with different
/// forms of `Spacing` returned.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
#[derive(Clone, Debug)]
pub struct Punct {
ch: char,
@ -685,20 +705,22 @@ pub struct Punct {
span: Span,
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Send for Punct {}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Sync for Punct {}
/// Whether an `Punct` is followed immediately by another `Punct` or
/// followed by another token or whitespace.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub enum Spacing {
/// E.g. `+` is `Alone` in `+ =`, `+ident` or `+()`.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Alone,
/// E.g. `+` is `Joint` in `+=` or `'#`.
/// Additionally, single quote `'` can join with identifiers to form lifetimes `'ident`.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
Joint,
}
@ -709,7 +731,7 @@ impl Punct {
///
/// The returned `Punct` will have the default span of `Span::call_site()`
/// which can be further configured with the `set_span` method below.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn new(ch: char, spacing: Spacing) -> Punct {
const LEGAL_CHARS: &[char] = &['=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^',
'&', '|', '@', '.', ',', ';', ':', '#', '$', '?', '\''];
@ -724,7 +746,7 @@ impl Punct {
}
/// Returns the value of this punctuation character as `char`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn as_char(&self) -> char {
self.ch
}
@ -733,19 +755,19 @@ impl Punct {
/// followed by another `Punct` in the token stream, so they can potentially be combined into
/// a multicharacter operator (`Joint`), or it's followed by some other token or whitespace
/// (`Alone`) so the operator has certainly ended.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn spacing(&self) -> Spacing {
self.spacing
}
/// Returns the span for this punctuation character.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn span(&self) -> Span {
self.span
}
/// Configure the span for this punctuation character.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn set_span(&mut self, span: Span) {
self.span = span;
}
@ -753,7 +775,7 @@ impl Punct {
/// Prints the punctuation character as a string that should be losslessly convertible
/// back into the same character.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl fmt::Display for Punct {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
TokenStream::from(TokenTree::from(self.clone())).fmt(f)
@ -762,16 +784,16 @@ impl fmt::Display for Punct {
/// An identifier (`ident`).
#[derive(Clone, Debug)]
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub struct Ident {
sym: Symbol,
span: Span,
is_raw: bool,
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Send for Ident {}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Sync for Ident {}
impl Ident {
@ -794,7 +816,7 @@ impl Ident {
///
/// Due to the current importance of hygiene this constructor, unlike other
/// tokens, requires a `Span` to be specified at construction.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn new(string: &str, span: Span) -> Ident {
if !lexer::is_valid_ident(string) {
panic!("`{:?}` is not a valid identifier", string)
@ -807,7 +829,7 @@ impl Ident {
}
/// Same as `Ident::new`, but creates a raw identifier (`r#ident`).
#[unstable(feature = "proc_macro", issue = "38356")]
#[unstable(feature = "proc_macro_raw_ident", issue = "38356")]
pub fn new_raw(string: &str, span: Span) -> Ident {
let mut ident = Ident::new(string, span);
if ident.sym == keywords::Underscore.name() ||
@ -820,13 +842,13 @@ impl Ident {
/// Returns the span of this `Ident`, encompassing the entire string returned
/// by `as_str`.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn span(&self) -> Span {
self.span
}
/// Configures the span of this `Ident`, possibly changing its hygiene context.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn set_span(&mut self, span: Span) {
self.span = span;
}
@ -834,7 +856,7 @@ impl Ident {
/// Prints the identifier as a string that should be losslessly convertible
/// back into the same identifier.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl fmt::Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.is_raw {
@ -849,16 +871,16 @@ impl fmt::Display for Ident {
/// with or without a suffix (`1`, `1u8`, `2.3`, `2.3f32`).
/// Boolean literals like `true` and `false` do not belong here, they are `Ident`s.
#[derive(Clone, Debug)]
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub struct Literal {
lit: token::Lit,
suffix: Option<ast::Name>,
span: Span,
}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Send for Literal {}
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Sync for Literal {}
macro_rules! suffixed_int_literals {
@ -874,7 +896,7 @@ macro_rules! suffixed_int_literals {
/// Literals created through this method have the `Span::call_site()`
/// span by default, which can be configured with the `set_span` method
/// below.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn $name(n: $kind) -> Literal {
Literal {
lit: token::Lit::Integer(Symbol::intern(&n.to_string())),
@ -900,7 +922,7 @@ macro_rules! unsuffixed_int_literals {
/// Literals created through this method have the `Span::call_site()`
/// span by default, which can be configured with the `set_span` method
/// below.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn $name(n: $kind) -> Literal {
Literal {
lit: token::Lit::Integer(Symbol::intern(&n.to_string())),
@ -954,7 +976,7 @@ impl Literal {
///
/// This function requires that the specified float is finite, for
/// example if it is infinity or NaN this function will panic.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn f32_unsuffixed(n: f32) -> Literal {
if !n.is_finite() {
panic!("Invalid float literal {}", n);
@ -979,7 +1001,7 @@ impl Literal {
///
/// This function requires that the specified float is finite, for
/// example if it is infinity or NaN this function will panic.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn f32_suffixed(n: f32) -> Literal {
if !n.is_finite() {
panic!("Invalid float literal {}", n);
@ -1003,7 +1025,7 @@ impl Literal {
///
/// This function requires that the specified float is finite, for
/// example if it is infinity or NaN this function will panic.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn f64_unsuffixed(n: f64) -> Literal {
if !n.is_finite() {
panic!("Invalid float literal {}", n);
@ -1028,7 +1050,7 @@ impl Literal {
///
/// This function requires that the specified float is finite, for
/// example if it is infinity or NaN this function will panic.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn f64_suffixed(n: f64) -> Literal {
if !n.is_finite() {
panic!("Invalid float literal {}", n);
@ -1041,7 +1063,7 @@ impl Literal {
}
/// String literal.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn string(string: &str) -> Literal {
let mut escaped = String::new();
for ch in string.chars() {
@ -1055,7 +1077,7 @@ impl Literal {
}
/// Character literal.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn character(ch: char) -> Literal {
let mut escaped = String::new();
escaped.extend(ch.escape_unicode());
@ -1067,7 +1089,7 @@ impl Literal {
}
/// Byte string literal.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn byte_string(bytes: &[u8]) -> Literal {
let string = bytes.iter().cloned().flat_map(ascii::escape_default)
.map(Into::<char>::into).collect::<String>();
@ -1079,13 +1101,13 @@ impl Literal {
}
/// Returns the span encompassing this literal.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn span(&self) -> Span {
self.span
}
/// Configures the span associated for this literal.
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn set_span(&mut self, span: Span) {
self.span = span;
}
@ -1093,7 +1115,7 @@ impl Literal {
/// Prints the literal as a string that should be losslessly convertible
/// back into the same literal (except for possible rounding for floating point literals).
#[unstable(feature = "proc_macro", issue = "38356")]
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl fmt::Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
TokenStream::from(TokenTree::from(self.clone())).fmt(f)

View File

@ -1412,9 +1412,6 @@ pub struct Resolver<'a> {
/// Avoid duplicated errors for "name already defined".
name_already_seen: FxHashMap<Name, Span>,
/// If `#![feature(proc_macro)]` is set
proc_macro_enabled: bool,
/// A set of procedural macros imported by `#[macro_use]` that have already been warned about
warned_proc_macros: FxHashSet<Name>,
@ -1713,7 +1710,7 @@ impl<'a> Resolver<'a> {
// The `proc_macro` and `decl_macro` features imply `use_extern_macros`
use_extern_macros:
features.use_extern_macros || features.proc_macro || features.decl_macro,
features.use_extern_macros || features.decl_macro,
crate_loader,
macro_names: FxHashSet(),
@ -1727,7 +1724,6 @@ impl<'a> Resolver<'a> {
local_macro_def_scopes: FxHashMap(),
name_already_seen: FxHashMap(),
whitelisted_legacy_custom_derives: Vec::new(),
proc_macro_enabled: features.proc_macro,
warned_proc_macros: FxHashSet(),
potentially_unused_imports: Vec::new(),
struct_constructors: DefIdMap(),
@ -4509,7 +4505,7 @@ impl<'a> Resolver<'a> {
}
fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) {
if self.proc_macro_enabled { return; }
if self.use_extern_macros { return; }
for attr in attrs {
if attr.path.segments.len() > 1 {

View File

@ -429,7 +429,7 @@ impl<'a> Resolver<'a> {
*item = mem::replace(item, dummy_item).map_attrs(|mut attrs| {
let inert_attr = attr.take().unwrap();
attr::mark_known(&inert_attr);
if self.proc_macro_enabled {
if self.use_extern_macros {
*attr = expand::find_attr_invoc(&mut attrs);
}
attrs.push(inert_attr);

View File

@ -1073,7 +1073,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
return attrs;
}
if self.cx.ecfg.proc_macro_enabled() {
if self.cx.ecfg.use_extern_macros_enabled() {
attr = find_attr_invoc(&mut attrs);
}
traits = collect_derives(&mut self.cx, &mut attrs);
@ -1096,7 +1096,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
return attrs;
}
if self.cx.ecfg.proc_macro_enabled() {
if self.cx.ecfg.use_extern_macros_enabled() {
attr = find_attr_invoc(&mut attrs);
}
attrs
@ -1406,7 +1406,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
foreign_item: ast::ForeignItem) -> SmallVector<ast::ForeignItem> {
let (attr, traits, foreign_item) = self.classify_item(foreign_item);
let explain = if self.cx.ecfg.proc_macro_enabled() {
let explain = if self.cx.ecfg.use_extern_macros_enabled() {
feature_gate::EXPLAIN_PROC_MACROS_IN_EXTERN
} else {
feature_gate::EXPLAIN_MACROS_IN_EXTERN
@ -1592,7 +1592,7 @@ impl<'feat> ExpansionConfig<'feat> {
fn enable_trace_macros = trace_macros,
fn enable_allow_internal_unstable = allow_internal_unstable,
fn enable_custom_derive = custom_derive,
fn proc_macro_enabled = proc_macro,
fn use_extern_macros_enabled = use_extern_macros,
fn macros_in_extern_enabled = macros_in_extern,
fn proc_macro_mod = proc_macro_mod,
fn proc_macro_gen = proc_macro_gen,

View File

@ -39,13 +39,6 @@ use symbol::{keywords, Symbol};
use std::{env, path};
macro_rules! set {
(proc_macro) => {{
fn f(features: &mut Features, span: Span) {
features.declared_lib_features.push((Symbol::intern("proc_macro"), span));
features.proc_macro = true;
}
f as fn(&mut Features, Span)
}};
($field: ident) => {{
fn f(features: &mut Features, _: Span) {
features.$field = true;
@ -303,9 +296,6 @@ declare_features! (
// rustc internal
(active, abi_unadjusted, "1.16.0", None, None),
// Procedural macros 2.0.
(active, proc_macro, "1.16.0", Some(38356), Some(Edition::Edition2018)),
// Declarative macros 2.0 (`macro`).
(active, decl_macro, "1.17.0", Some(39412), None),
@ -626,6 +616,8 @@ declare_features! (
(accepted, global_allocator, "1.28.0", Some(27389), None),
// Allows `#[repr(transparent)]` attribute on newtype structs
(accepted, repr_transparent, "1.28.0", Some(43036), None),
// Defining procedural macros in `proc-macro` crates
(accepted, proc_macro, "1.29.0", Some(38356), None),
);
// If you change this, please modify src/doc/unstable-book as well. You must
@ -1033,15 +1025,8 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
("windows_subsystem", Whitelisted, Ungated),
("proc_macro_attribute", Normal, Gated(Stability::Unstable,
"proc_macro",
"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))),
("proc_macro_attribute", Normal, Ungated),
("proc_macro", Normal, Ungated),
("rustc_derive_registrar", Normal, Gated(Stability::Unstable,
"rustc_derive_registrar",
@ -1542,7 +1527,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
}
}
if self.context.features.proc_macro && attr::is_known(attr) {
if self.context.features.use_extern_macros && attr::is_known(attr) {
return
}
@ -1990,7 +1975,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute],
/// A collector for mutually exclusive and interdependent features and their flag spans.
#[derive(Default)]
struct FeatureChecker {
proc_macro: Option<Span>,
use_extern_macros: Option<Span>,
custom_attribute: Option<Span>,
}
@ -1999,9 +1984,9 @@ impl FeatureChecker {
// the branching can be eliminated by modifying `set!()` to set these spans
// only for the features that need to be checked for mutual exclusion.
fn collect(&mut self, features: &Features, span: Span) {
if features.proc_macro {
// If self.proc_macro is None, set to Some(span)
self.proc_macro = self.proc_macro.or(Some(span));
if features.use_extern_macros {
// If self.use_extern_macros is None, set to Some(span)
self.use_extern_macros = self.use_extern_macros.or(Some(span));
}
if features.custom_attribute {
@ -2010,8 +1995,8 @@ impl FeatureChecker {
}
fn check(self, handler: &Handler) {
if let (Some(pm_span), Some(ca_span)) = (self.proc_macro, self.custom_attribute) {
handler.struct_span_err(pm_span, "Cannot use `#![feature(proc_macro)]` and \
if let (Some(pm_span), Some(ca_span)) = (self.use_extern_macros, self.custom_attribute) {
handler.struct_span_err(pm_span, "Cannot use `#![feature(use_extern_macros)]` and \
`#![feature(custom_attribute)] at the same time")
.span_note(ca_span, "`#![feature(custom_attribute)]` declared here")
.emit();

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;