Skip to content

Generating Rust enums for C++ enums causes NonZero-optimization footguns #225

Closed
@bholley

Description

@bholley

Finally got to the bottom of what was making my incremental restyle stuff crash.

Gecko has nsChangeHint, which is a bitmask declared as an enum [1]. Bindgen currently generates a compatible rust enum as shown in [2] ([3] in case the former goes away).

The problem is that Rust makes very strong assumptions about enums, and in particular assumes that enums will never have representations other than the ones listed in the declaration. And if there is no zero value declared, then [4] causes the NonZero optimization to kick in, which means that Option will use the inner enum as the discriminant. And so if somebody happens to pass nsChangeHint(0), Rust will think the entire outer struct is None.

Gecko is arguably abusing |enum| here, but people do this all the time in C++. So we should either find a safer representation, or, barring that, at least generate checked conversion routines (like bitflags! has) that callers can use instead of transmute.

Thoughts?

CC @Manishearth @emilio @nox @fitzgen @vlad @heycam @upsuper

[1] http://searchfox.org/mozilla-central/rev/f5c9e9a249637c9abd88754c8963ecb3838475cb/layout/base/nsChangeHint.h#19
[2] https://github.com/bholley/gecko-dev/blob/59bfa64706f8dc5743fbf7c7fdcd8c1478af4864/servo/components/style/gecko_bindings/structs_debug.rs#L5067
[3] https://pastebin.mozilla.org/8926070
[4] rust-lang/rust#37224

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions