Skip to content

Commit 9531eb8

Browse files
committed
Auto merge of rust-lang#79078 - petrochenkov:derattr, r=Aaron1011
expand/resolve: Turn `#[derive]` into a regular macro attribute This PR turns `#[derive]` into a regular attribute macro declared in libcore and defined in `rustc_builtin_macros`, like it was previously done with other "active" attributes in rust-lang#62086, rust-lang#62735 and other PRs. This PR is also a continuation of rust-lang#65252, rust-lang#69870 and other PRs linked from them, which layed the ground for converting `#[derive]` specifically. `#[derive]` still asks `rustc_resolve` to resolve paths inside `derive(...)`, and `rustc_expand` gets those resolution results through some backdoor (which I'll try to address later), but otherwise `#[derive]` is treated as any other macro attributes, which simplifies the resolution-expansion infra pretty significantly. The change has several observable effects on language and library. Some of the language changes are **feature-gated** by [`feature(macro_attributes_in_derive_output)`](rust-lang#81119). #### Library - `derive` is now available through standard library as `{core,std}::prelude::v1::derive`. #### Language - `derive` now goes through name resolution, so it can now be renamed - `use derive as my_derive; #[my_derive(Debug)] struct S;`. - `derive` now goes through name resolution, so this resolution can fail in corner cases. Crater found one such regression, where import `use foo as derive` goes into a cycle with `#[derive(Something)]`. - **[feature-gated]** `#[derive]` is now expanded as any other attributes in left-to-right order. This allows to remove the restriction on other macro attributes following `#[derive]` (rust-lang/reference#566). The following macro attributes become a part of the derive's input (this is not a change, non-macro attributes following `#[derive]` were treated in the same way previously). - `#[derive]` is now expanded as any other attributes in left-to-right order. This means two derive attributes `#[derive(Foo)] #[derive(Bar)]` are now expanded separately rather than together. It doesn't generally make difference, except for esoteric cases. For example `#[derive(Foo)]` can now produce an import bringing `Bar` into scope, but previously both `Foo` and `Bar` were required to be resolved before expanding any of them. - **[feature-gated]** `#[derive()]` (with empty list in parentheses) actually becomes useful. For historical reasons `#[derive]` *fully configures* its input, eagerly evaluating `cfg` everywhere in its target, for example on fields. Expansion infra doesn't do that for other attributes, but now when macro attributes attributes are allowed to be written after `#[derive]`, it means that derive can *fully configure* items for them. ```rust #[derive()] #[my_attr] struct S { #[cfg(FALSE)] // this field in removed by `#[derive()]` and not observed by `#[my_attr]` field: u8 } ``` - `#[derive]` on some non-item targets is now prohibited. This was accidentally allowed as noop in the past, but was warned about since early 2018 (rust-lang#50092), despite that crater found a few such cases in unmaintained crates. - Derive helper attributes used before their introduction are now reported with a deprecation lint. This change is long overdue (since macro modularization, rust-lang#52226 (comment)), but it was hard to do without fixing expansion order for derives. The deprecation is tracked by rust-lang#79202. ```rust #[trait_helper] // warning: derive helper attribute is used before it is introduced #[derive(Trait)] struct S {} ``` Crater analysis: rust-lang#79078 (comment)
2 parents f396366 + cdb3355 commit 9531eb8

File tree

3 files changed

+18
-0
lines changed

3 files changed

+18
-0
lines changed

core/src/macros/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,14 @@ pub(crate) mod builtin {
13241324
(false) => {{ /* compiler built-in */ }};
13251325
}
13261326

1327+
/// Attribute macro used to apply derive macros.
1328+
#[cfg(not(bootstrap))]
1329+
#[stable(feature = "rust1", since = "1.0.0")]
1330+
#[rustc_builtin_macro]
1331+
pub macro derive($item:item) {
1332+
/* compiler built-in */
1333+
}
1334+
13271335
/// Attribute macro applied to a function to turn it into a unit test.
13281336
#[stable(feature = "rust1", since = "1.0.0")]
13291337
#[allow_internal_unstable(test, rustc_attrs)]

core/src/prelude/v1.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ pub use crate::macros::builtin::{
6969
bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
7070
};
7171

72+
#[cfg(not(bootstrap))]
73+
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
74+
#[doc(no_inline)]
75+
pub use crate::macros::builtin::derive;
76+
7277
#[unstable(
7378
feature = "cfg_accessible",
7479
issue = "64797",

std/src/prelude/v1.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ pub use core::prelude::v1::{
5454
bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable,
5555
};
5656

57+
#[cfg(not(bootstrap))]
58+
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
59+
#[doc(hidden)]
60+
pub use core::prelude::v1::derive;
61+
5762
#[unstable(
5863
feature = "cfg_accessible",
5964
issue = "64797",

0 commit comments

Comments
 (0)