Skip to content

ty macro arguments can be used as traits in impls #46438

Closed
@petrochenkov

Description

@petrochenkov
macro_rules! m {
    ($my_type: ty) => {
        impl $my_type for u8 {} // Hmmm.

        // Not OK, this trick can't be used in any other position.
        // trait Z: $my_type {}
    }
}

trait Tr {}
m!(Tr); // OK

fn main() {}

This is a side effect of how impls are parsed - the trait in impl Trait for Type is first parsed as a type, and then reinterpreted as a type if it has appropriate syntactic form (trait syntax is a subset of type syntax).
(Same trick was used for pub(path) visibilities for some time, but then abandoned in favor of pub(in path).)

The reinterpretation trick in impl parsing can hardly be avoided, but this specific issue can be fixed because reinterpretation can be avoided if we see a ty fragment after impl.

The question is whether we should fix it or not - the issue seems benign even if it's probably unintended, an error is immediately reported if ty doesn't fit into the trait syntax.
This trick is also similar to other cases like limited use of expr fragment in range patterns (#42886), which are intended.
I would also be surprised if this was not exploited in practice.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-grammarArea: The grammar of RustA-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)C-bugCategory: This is a bug.I-needs-decisionIssue: In need of a decision.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions