This commit alters the expansion order of custom macros-1.1 style `#[derive]`
modes. Instead of left-to-right the expansion now happens in three categories,
each of which is internally left-to-right:
* Old-style custom derive (`#[derive_Foo]`) is expanded
* New-style custom derive (macros 1.1) is expanded
* Built in derive modes are expanded
This gives built in derive modes maximal knowledge about the struct that's being
expanded and also avoids pesky issues like exposing `#[structural_match]` or
`#[rustc_copy_clone_marker]`.
cc #35900
Adds a `ProcMacro` form of syntax extension
This commit adds syntax extension forms matching the types for procedural macros 2.0 (RFC #1566), these still require the usual syntax extension boiler plate, but this is a first step towards proper implementation and should be useful for macros 1.1 stuff too.
Supports both attribute-like and function-like macros.
Note that RFC #1566 has not been accepted yet, but I think there is consensus that we want to head in vaguely that direction and so this PR will be useful in any case. It is also fairly easy to undo and does not break any existing programs.
This is related to #35957 in that I hope it can be used in the implementation of macros 1.1, however, there is no direct overlap and is more of a complement than a competing proposal. There is still a fair bit of work to do before the two can be combined.
r? @jseyfried
cc @alexcrichton, @cgswords, @eddyb, @aturon
Assign node ids during macro expansion
After this PR,
- The `ExtCtxt` can access `resolve`'s `Resolver` through the trait object `ext::base::Resolver`.
- The `Resolver` trait object can load macros and replaces today's `MacroLoader` trait object.
- The macro expander uses the `Resolver` trait object to resolve macro invocations.
- The macro expander assigns node ids and builds the `Resolver`'s `macros_at_scope` map.
- This is groundwork for merging import resolution and expansion.
- Performance of expansion together with node id assignment improves by ~5%.
**EDIT:** Since Github is reordering the commits, here is `git log`:
- b54e1e3997: Differentiate between monotonic and non-monotonic expansion and only assign node ids during monotonic expansion.
- 78c0039878: Expand generated test harnesses and macro registries.
- f3c2dca353: Remove scope placeholders from the crate root.
- c86c8d41a2: Perform node id assignment and `macros_at_scope` construction during the `InvocationCollector` and `PlaceholderExpander` folds.
- 72a636975f: Move macro resolution into `librustc_resolve`.
- 20b43b2323: Rewrite the unit tests in `ext/expand.rs` as a `compile-fail` test.
- a9821e1658: Refactor `ExtCtxt` to use a `Resolver` instead of a `MacroLoader`.
- 60440b226d: Refactor `noop_fold_stmt_kind` out of `noop_fold_stmt`.
- 50f94f6c95: Avoid needless reexpansions.
r? @nrc
Improve shallow `Clone` deriving
`Copy` unions now support `#[derive(Clone)]`.
Less code is generated for `#[derive(Clone, Copy)]`.
+
Unions now support `#[derive(Eq)]`.
Less code is generated for `#[derive(Eq)]`.
---
Example of code reduction:
```
enum E {
A { a: u8, b: u16 },
B { c: [u8; 100] },
}
```
Before:
```
fn clone(&self) -> E {
match (&*self,) {
(&E::A { a: ref __self_0, b: ref __self_1 },) => {
::std::clone::assert_receiver_is_clone(&(*__self_0));
::std::clone::assert_receiver_is_clone(&(*__self_1));
*self
}
(&E::B { c: ref __self_0 },) => {
::std::clone::assert_receiver_is_clone(&(*__self_0));
*self
}
}
}
```
After:
```
fn clone(&self) -> E {
{
let _: ::std::clone::AssertParamIsClone<u8>;
let _: ::std::clone::AssertParamIsClone<u16>;
let _: ::std::clone::AssertParamIsClone<[u8; 100]>;
*self
}
}
```
All the matches are removed, bound assertions are more lightweight.
`let _: Checker<CheckMe>;`, unlike `checker(&check_me);`, doesn't have to be translated by rustc_trans and then inlined by LLVM, it doesn't even exist in MIR, this means faster compilation.
---
Union impls are generated like this:
```
union U {
a: u8,
b: u16,
c: [u8; 100],
}
```
```
fn clone(&self) -> U {
{
let _: ::std::clone::AssertParamIsCopy<Self>;
*self
}
}
```
Fixes https://github.com/rust-lang/rust/issues/36043
cc @durka
r? @alexcrichton
Point macros 1.1 errors to the input item
Moved from https://github.com/alexcrichton/rust/pull/6 to continue discussion. Fixes#36218.
Before:
```rust
error[E0106]: missing lifetime specifier
--> src/main.rs:10:10
|
10 | #[derive(Serialize, Deserialize)]
| ^ expected lifetime parameter
error[E0038]: the trait `T` cannot be made into an object
--> src/main.rs:15:15
|
15 | #[derive(Serialize, Deserialize)]
| ^^^^^^^^^^ the trait `T` cannot be made into an object
```
After:
```rust
error[E0106]: missing lifetime specifier
--> src/main.rs:11:1
|
11 | struct A {
| ^ expected lifetime parameter
error[E0038]: the trait `T` cannot be made into an object
--> src/main.rs:16:1
|
16 | struct B<'a> {
| ^ the trait `T` cannot be made into an object
```
Before:
```rust
error[E0106]: missing lifetime specifier
--> src/main.rs:10:10
|
10 | #[derive(Serialize, Deserialize)]
| ^ expected lifetime parameter
error[E0038]: the trait `T` cannot be made into an object
--> src/main.rs:15:15
|
15 | #[derive(Serialize, Deserialize)]
| ^^^^^^^^^^ the trait `T` cannot be made into an object
```
After:
```rust
error[E0106]: missing lifetime specifier
--> src/main.rs:11:1
|
11 | struct A {
| ^ expected lifetime parameter
error[E0038]: the trait `T` cannot be made into an object
--> src/main.rs:16:1
|
16 | struct B<'a> {
| ^ the trait `T` cannot be made into an object
```
This commit is an implementation of [RFC 1681] which adds support to the
compiler for first-class user-define custom `#[derive]` modes with a far more
stable API than plugins have today.
[RFC 1681]: https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md
The main features added by this commit are:
* A new `rustc-macro` crate-type. This crate type represents one which will
provide custom `derive` implementations and perhaps eventually flower into the
implementation of macros 2.0 as well.
* A new `rustc_macro` crate in the standard distribution. This crate will
provide the runtime interface between macro crates and the compiler. The API
here is particularly conservative right now but has quite a bit of room to
expand into any manner of APIs required by macro authors.
* The ability to load new derive modes through the `#[macro_use]` annotations on
other crates.
All support added here is gated behind the `rustc_macro` feature gate, both for
the library support (the `rustc_macro` crate) as well as the language features.
There are a few minor differences from the implementation outlined in the RFC,
such as the `rustc_macro` crate being available as a dylib and all symbols are
`dlsym`'d directly instead of having a shim compiled. These should only affect
the implementation, however, not the public interface.
This commit also ended up touching a lot of code related to `#[derive]`, making
a few notable changes:
* Recognized derive attributes are no longer desugared to `derive_Foo`. Wasn't
sure how to keep this behavior and *not* expose it to custom derive.
* Derive attributes no longer have access to unstable features by default, they
have to opt in on a granular level.
* The `derive(Copy,Clone)` optimization is now done through another "obscure
attribute" which is just intended to ferry along in the compiler that such an
optimization is possible. The `derive(PartialEq,Eq)` optimization was also
updated to do something similar.
---
One part of this PR which needs to be improved before stabilizing are the errors
and exact interfaces here. The error messages are relatively poor quality and
there are surprising spects of this such as `#[derive(PartialEq, Eq, MyTrait)]`
not working by default. The custom attributes added by the compiler end up
becoming unstable again when going through a custom impl.
Hopefully though this is enough to start allowing experimentation on crates.io!
syntax-[breaking-change]
syntax_ext: format: fix ICE with bad named arguments
Fixes#35082 by guarding against a new case of malformed invocation not previously covered.
r? @alexcrichton
This commit removed the restriction of only allowing one type per argument.
This is achieved by adding mappings between macro arguments and format
placeholders, then taking the mapping into consideration when emitting
the Arguments expression.
syntax_ext: format: fix implicit positional arguments
syntax_ext: format: don't panic if no args given for implicit positional args
Check the list lengths before use.
Fixes regression of `compile-fail/macro-backtrace-println.rs`.
syntax_ext: format: also map CountIsParam indices to expanded args
syntax_ext: format: fix ICE in case of malformed format args
Converts named argument references into indices, right after
verification as suggested by @alexcrichton. This drastically simplifies
the whole process!
format: beautifully get rid of ArgumentNext and CountIsNextParam
Now that CountIsNextParam and ArgumentNext are resolved during parse,
the need for handling them outside of libfmt_macros is obviated.
Note: *one* instance of implicit reference handling still remains, and
that's for implementing `all_args_simple`. It's trivial enough though,
so in this case it may be tolerable.
Fixes the formatting for inline assembly clobbers used in the book.
As this causes llvm to silently ignore the clobber an error is also
added to catch cases in which the wrong formatting was used.
Additionally a test case is added to confirm that this error works.
This is a spiritual succesor to #34268/8531d581, in which we replaced a
number of matches of None to the unit value with `if let` conditionals
where it was judged that this made for clearer/simpler code (as would be
recommended by Manishearth/rust-clippy's `single_match` lint). The same
rationale applies to matches of None to the empty block.