Skip to content

"Early" attrs crate_name, recursion_limit & crate_type can be set to #[attribute] "string literal" causing them to misbehave in various ways #163330

Description

@fmease

A sequel to #122001 of sorts.

Briefly: When faced with #![name = #[attr] expr] (name in crate_name, recursion_limit & crate_type) we mostly ignore #[attr] but it's more nuanced & slightly differs by attribute.

Meta note: While I've marked this issue with F-stmt_expr_attributes `#![feature(stmt_expr_attributes)]` which usually implies requires-nightly This issue requires a nightly compiler in some way. When possible, use a F-* label instead. if the feature is unstable, strictly speaking this bug can be observed on stable toolchains if you use print requests like --print=crate-name and --print=file-names since they don't trigger feature gates.

All subsequent examples assume that the following build step has happened:

rustc replacer.rs --crate-type=proc-macro --extern proc_macro --edition 2024 where replacer.rs:

use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn replace_with(arg: TokenStream, _: TokenStream) -> TokenStream { arg }

Moreover, they assume that they're placed inside file file.rs and get compiled with rustc file.rs --extern replacer -L. --edition 2024 (plus --print=crate-name etc. when it says so).


#![crate_name = #[attribute] "literal"]

Under normal execution, the compiler resolves+expands attribute & checks that the expansion is a string literal. However, the code responsible for validating & registering the crate name literally only looks at "literal" and ignores the presence of #[attribute]. It's expected that this part of the code doesn't perform macro expansion (namely, since PR #117584). However, I expected the code to reject any attributes found on the string literal (this of course includes non-normal executions caused by print requests) to honor lang FCP #122001 (comment).

Examples

#![feature(stmt_expr_attributes, proc_macro_hygiene)]
#![crate_name = #[replacer::replace_with("fake")] "real"]
fn main() {}

Compiles while it shouldn't. The crate name is actually set to real not to fake.

#![crate_name = #[replacer::replace_with("fake")] "real"]
fn main() {}

Additionally pass --print=crate-name or --print=file-names. Compiles while it shouldn't (use of unstable features, attribute on string literal). Outputs real for the former & libreal.rlib for the latter.

#![feature(stmt_expr_attributes, proc_macro_hygiene)]
#![crate_name = #[replacer::replace_with("???")] "real"]
fn main() {}

Compiles while it shouldn't. The crate name is actually set to real.

#![feature(stmt_expr_attributes, proc_macro_hygiene)]
#![crate_name = #[replacer::replace_with()] "real"]
fn main() {}

(Correctly errors with expected expression, found end of macro arguments.)

#![feature(stmt_expr_attributes, proc_macro_hygiene)]
#![crate_name = #[replacer::replace_with(0)] "real"]
fn main() {}

(Correctly errors with malformed `crate_name` attribute input.)

#![crate_type = #[attribute] "literal"]

META: TODO: Summary?

Examples

#![feature(stmt_expr_attributes, proc_macro_hygiene)]
#![crate_type = #[replacer::replace_with("bin")] "lib"]

Compiles while it shouldn't. The set of crate types is actually set to {lib} not to {bin}.

#![feature(stmt_expr_attributes, proc_macro_hygiene)]
#![crate_type = #[replacer::replace_with("???")] "lib"]

Actually rejects the ??? this with invalid `crate_type` value!

#![feature(stmt_expr_attributes, proc_macro_hygiene)]
#![crate_type = #[replacer::replace_with("lib")] "???"]

Actually ignores both ??? and lib & thus fails with `main` function not found in crate `file`.

#![crate_type = #[replacer::replace_with("???")] "!!!"]

Additionally pass --print=file-names. Compiles while it probably shouldn't. Ignores the attribute entirely meaning it doesn't complain about either ??? or !!!. Outputs file meaning it assumes the default set of crate types, that being {bin}.

#![recursion_limit = #[attribute] expression]

META: TODO.

Examples

META: TODO.

Activity

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-attributesArea: Attributes (`#[…]`, `#![…]`)C-bugCategory: This is a bug.F-stmt_expr_attributes`#![feature(stmt_expr_attributes)]`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions