Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do crate-level macro attributes deal with standard library prelude? #110082

Open
petrochenkov opened this issue Apr 8, 2023 · 4 comments
Open
Labels
A-linkage Area: linking into static, shared libraries and binaries A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) A-resolve Area: Name resolution

Comments

@petrochenkov
Copy link
Contributor

petrochenkov commented Apr 8, 2023

Here I'll talk about hightly unstable crate-level macro attributes first, but this issue is relevant even on stable because crate level #![cfg(...)] is also such a macro (sort of), and it is supported since Rust 1.0.
This case caused issues in #108221.

We assume that macros work with token streams.
Implicitly injected extern prelude does not have any token representation, so I conclude that crate-level macro attributes should only receive explicitly written user code as input (collected during token collection as usual).

Now the question is how and when standard library prelude is added to output of a crate level attribute (including #![cfg(FALSE)]) because eventually it should be added there.

Note: #104633 is a similar issue discussing the fate of #![feature] attributes on a fully unconfigured crate.

@petrochenkov petrochenkov added A-resolve Area: Name resolution A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) A-linkage Area: linking into static, shared libraries and binaries labels Apr 8, 2023
@petrochenkov
Copy link
Contributor Author

Right now the behavior on stable is that #![cfg(FALSE)] keeps the standard library prelude in place, and the fully unconfigured crate is not a no_std crate, and it links to standard library.
Moreover, nominally no_std crate with explicitly written #![no_std] attribute starts linking to standard library if fully unconfigured.

#108221 accidentally broke this behavior causing regressions in some no_std crates targeting embedded platforms.

I think we can break this behavior intentionally as well, because the crater regression were obtained in a very unnatural setup - crater compiles those crates for x86 host instead of their expected embedded targets making them fully unconfigured.

@petrochenkov
Copy link
Contributor Author

What is injected right now (edition 2021):

#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std; // this std is hygienic
// no_std
#[prelude_import]
use core::prelude::rust_2021::*;
#[macro_use]
extern crate core; // this core is hygienic
#[macro_use]
extern crate compiler_builtins;  // this compiler_builtins is hygienic
// no_core

@petrochenkov
Copy link
Contributor Author

I think a reasonable behavior would be to inject the standard library prelude once after all the crate-level attributes are expanded and the root AST is fixed.


Alternative 1: what exactly is injected would be determined by crate attributes at that point (remaining on the expanded root).
That would remove at least one attribute from the "very early" list at #108221 (comment).

For fully unconfigured crates that would mean that they always link std, even if they are explicitly #![no_std] before configuration.


Alternative 2: what exactly is injected would be determined by the "pre-configured attribute list" determined before any macro expansion (see #108221 for details).
All the relevant attributes would stay on the "very early" list in that case.

This would give a choice to fully unconfigured crates to control their no_std status, if we do the thing that #104633 wants.
#[no_std] #![cfg(FALSE)] - no-std crate, #![cfg(FALSE)] #[no_std] - std crate.

@petrochenkov
Copy link
Contributor Author

Another possibility - change how #![cfg(FALSE)] works when applied to crate root specifically (both during pre-configuration and regular expansion) - make it remove everything below itself, but not above itself.

Crate-level cfg is already special - it cannot remove the node entirely, unlike with all other locations, it can only cleanup it contents. So this change wouldn't make it significantly more special.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Jun 9, 2023
…pkin

expand: Change how `#![cfg(FALSE)]` behaves on crate root

Previously it removed all other attributes from the crate root.
Now it removes only attributes below itself (during both regular expansion and pre-configuration).

So it becomes possible to configure some global crate properties even for fully unconfigured crates.

Fixes rust-lang#104633
Part of rust-lang#110082
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Jun 9, 2023
…pkin

expand: Change how `#![cfg(FALSE)]` behaves on crate root

Previously it removed all other attributes from the crate root.
Now it removes only attributes below itself (during both regular expansion and pre-configuration).

So it becomes possible to configure some global crate properties even for fully unconfigured crates.

Fixes rust-lang#104633
Part of rust-lang#110082
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue Jun 9, 2023
…pkin

expand: Change how `#![cfg(FALSE)]` behaves on crate root

Previously it removed all other attributes from the crate root.
Now it removes only attributes below itself (during both regular expansion and pre-configuration).

So it becomes possible to configure some global crate properties even for fully unconfigured crates.

Fixes rust-lang#104633
Part of rust-lang#110082
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Jun 10, 2023
…pkin

expand: Change how `#![cfg(FALSE)]` behaves on crate root

Previously it removed all other attributes from the crate root.
Now it removes only attributes below itself (during both regular expansion and pre-configuration).

So it becomes possible to configure some global crate properties even for fully unconfigured crates.

Fixes rust-lang#104633
Part of rust-lang#110082
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries A-macros Area: All kinds of macros (custom derive, macro_rules!, proc macros, ..) A-resolve Area: Name resolution
Projects
None yet
Development

No branches or pull requests

1 participant