Skip to content

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

Description

@petrochenkov

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.

Activity

  1. added
    A-resolveArea: Name/path resolution done by `rustc_resolve` specifically
    A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)
    A-linkageArea: linking into static, shared libraries and binaries
    on Apr 8, 2023
  2. petrochenkov commented on Apr 8, 2023

    @petrochenkov
    ContributorAuthor

    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.

  3. petrochenkov commented on Apr 8, 2023

    @petrochenkov
    ContributorAuthor

    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
  4. petrochenkov commented on Apr 8, 2023

    @petrochenkov
    ContributorAuthor

    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.

  5. petrochenkov commented on Apr 8, 2023

    @petrochenkov
    ContributorAuthor

    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.

  6. added a commit that references this issue on Jun 9, 2023
  7. added 2 commits that reference this issue on Jun 9, 2023
  8. added a commit that references this issue on Jun 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-linkageArea: linking into static, shared libraries and binariesA-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-resolveArea: Name/path resolution done by `rustc_resolve` specifically

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions