Skip to content

Derive macros that emit unsafe code can't rely on mentioning the field type twice #148793

@theemathas

Description

@theemathas

This is a different issue from #148423.

Some derive macros need to reason about the properties of the types of a struct's fields, in order to emit correct unsafe code. This is usually done by emitting code that mentions the type name, and asserts that those types implement certain traits.

This relies on the assumption that, by repeating the same tokens twice, those repeated tokens will refer to the same type. This assumption is false in the face of nondeterministic proc macros that expand to types.

#[derive(SomeTrait)]
struct Thing {
    field: make_type!(),
}

In code such as above, the derive macro might expand to code that checks whether the type make_type!() has certain properties or not. However, if make_type!() is nondeterministic, it might cause the macro to check one type, while the struct actually contains a different types. This causes the macro to make assumptions that are false. If the macro emits unsafe code, this can lead to unsoundness.

This issue affects bytemuck, zerocopy, and probably many other crates. See those two links for working reproducers that demonstrate UB.

See also #147103, for a similar issue in std, although that case didn't cause unsoundness.

Meta

Affects rust 1.91.0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-macrosArea: All kinds of macros (custom derive, macro_rules!, proc macros, ..)A-proc-macrosArea: Procedural macrosC-bugCategory: This is a bug.I-lang-nominatedNominated for discussion during a lang team meeting.T-langRelevant to the language teamneeds-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions