Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EnumSet with more variants than bits in uint silently corrupts data #13756

Closed
SimonSapin opened this issue Apr 25, 2014 · 0 comments · Fixed by #18721
Closed

EnumSet with more variants than bits in uint silently corrupts data #13756

SimonSapin opened this issue Apr 25, 2014 · 0 comments · Fixed by #18721

Comments

@SimonSapin
Copy link
Contributor

Test case:

extern crate collections;
use collections::enum_set::{EnumSet, CLike};
use std::cast;

#[repr(uint)]
enum Foo {
    V00, V01, V02, V03, V04, V05, V06, V07, V08, V09,
    V10, V11, V12, V13, V14, V15, V16, V17, V18, V19,
    V20, V21, V22, V23, V24, V25, V26, V27, V28, V29,
    V30, V31, V32, V33, V34, V35, V36, V37, V38, V39,
    V40, V41, V42, V43, V44, V45, V46, V47, V48, V49,
    V50, V51, V52, V53, V54, V55, V56, V57, V58, V59,
    V60, V61, V62, V63, V64, V65, V66, V67, V68, V69,
}

impl CLike for Foo {
    fn to_uint(&self) -> uint {
        *self as uint
    }

    fn from_uint(v: uint) -> Foo {
        unsafe { cast::transmute(v) }
    }
}

fn main() {
    let mut set: EnumSet<Foo> = EnumSet::empty();
    set.add(V63);
    set.add(V64);
    set.add(V65);
    println!("{:?}", set.iter().collect::<~[Foo]>())
}

Expected result, in decreasing order of preference: ~[V63, V64, V65], compile-time failure, or run-time failure.

Actual result with rustc eea4909 on a 64 bit system: ~[V00, V01, V63]

Use case: Servo currently handles CSS declarations in order, later ones overwriting earlier ones. I’d like instead to process declarations in reverse order, and skip those for properties for which we already have a value. "Already have a value" would be stored in an EnumSet with one variant for every CSS property. There are a few hundreds of them. (The enum is automatically generated.) (Values can not be Options, because they’re initialized to the inherited or initial value rather than None.)

Possible fixes:

  1. To at least avoid silently corrupting data, have the bit function assert (non-disablable) that e.to_uint() < (size_of<uint>() * 8)
  2. Do 1., and also add a BigEnumSet type that uses Vec<uint> or ~[uint] internally for storage rather than just a single uint.
  3. Change EnumSet to decide at run-time to use ~[uint] or a single uint for storage, like collections::bitv::Bitv does.
  4. Like 3., but decide at compile-time what kind of storage to use. (Since the generic EnumSet is being monomorphized anyway.) I don’t know if this is possible.

3 or 4 might need the CLike trait to gain a max_value associated function (or something), which would ideally be based on introspection rather than leaving the counting to the user.

SimonSapin added a commit to SimonSapin/rust that referenced this issue Nov 7, 2014
Assert at run time instead. Fixes rust-lang#13756.

I’d rather have this be detected at compile-time, but I don’t know how to do that.
bors added a commit that referenced this issue Nov 7, 2014
Assert at run time instead. Fixes #13756.

I’d rather have this be detected at compile-time, but I don’t know how to do that.
arcnmx pushed a commit to arcnmx/rust that referenced this issue Dec 17, 2022
… r=flodiebold

Make assoc_resolutions always have a Substitution
flip1995 pushed a commit to flip1995/rust that referenced this issue Dec 15, 2024
The new cases are the application of `Into::into` or `From::from`
through the following functions with no effect:
- `Option::map()`
- `Result::map()` and `Result::map_err()`
- `ControlFlow::map_break()` and `ControlFlow::map_err()`
- `Iterator::map()`

changelog: [`useless_conversion`]: detect useless calls to `Into::into`
and `From::from` application through `map*` methods
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant