Skip to content

[!; 0] incorrectly considered uninhabited #47563

Description

@dtolnay
#![feature(never_type)]

enum Helper<T, U> {
    T(T, [!; 0]),
    #[allow(dead_code)]
    U(U),
}

fn transmute<T, U>(t: T) -> U {
    let Helper::U(u) = Helper::T(t, []); // ??
    u
}

fn main() {
    println!("{:?}", transmute::<&str, (*const u8, u64)>("type safety"));
}

Output on my machine as of rustc 1.25.0-nightly (3bd4af8 2018-01-18):

(0x55fd17861801, 11)

Mentioning @eddyb and @arielb1 who were involved with #45225.
Mentioning the never_type tracking issue #35121.

Activity

  1. added
    I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness
    on Jan 19, 2018
  2. eddyb commented on Jan 19, 2018

    @eddyb
    Contributor

    #45225 always considers arrays inhabited, so it's not from there, but rather match checking.
    cc @rust-lang/compiler @canndrew

  3. canndrew commented on Jan 19, 2018

    @canndrew
    Contributor

    That's weird. The inhabitedness-checking function explicitly checks whether arrays have size zero or not: https://github.com/rust-lang/rust/blob/master/src/librustc/ty/inhabitedness/mod.rs#L265

  4. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    C-bugCategory: This is a bug.
    on Jan 19, 2018
  5. eddyb commented on Jan 19, 2018

    @eddyb
    Contributor

    @canndrew That check is incorrect, it should default to inhabited if to_const_int or to_u64 return None.

  6. dtolnay commented on Jan 19, 2018

    @dtolnay
    MemberAuthor

    That's a bug but it doesn't fix this bug right? Here it seems like len would be Some(0).

  7. eddyb commented on Jan 19, 2018

    @eddyb
    Contributor

    @dtolnay The length might be unevaluated. If it's possible to evaluate, sure, this code should trigger that, but it's incorrect to assume that the type is uninhabited if the length isn't known yet.

  8. varkor commented on Jan 19, 2018

    @varkor
    Contributor

    The issue is exactly as @eddyb suggests: the length is unevaluated in the program at the point uninhabited_from is called, so it then incorrectly looks at the inhabitedness of the array type because len.val.to_const_int() == None.

  9. canndrew commented on Jan 20, 2018

    @canndrew
    Contributor

    @varkor A problem with your fix is that @dtolnay's code now fails to compile if you make the array have length 1. eg. I would expect this to compile fine:

    #![feature(never_type)]
    
    enum Helper<T, U> {
        T(T, [!; 1]),
        #[allow(dead_code)]
        U(U),
    }
    
    fn make_the_array() -> [!; 1] {
        panic!("whoops!");
    }
    
    fn transmute<T, U>(t: T) -> U {
        let Helper::U(u) = Helper::T(t, make_the_array()); // ??
        u
    }
    
    fn main() {
        println!("{:?}", transmute::<&str, (*const u8, u64)>("type safety"));
    }

    I think we should still merge it to fix the soundness bug, but why don't we know the value of the constant expression there?

  10. varkor commented on Jan 20, 2018

    @varkor
    Contributor

    This is an issue with the constant evaluation rather than the fix itself. For some reason, the sizes do not seem to have been evaluated by the time the inhabitedness checks are called. This seems like a bug, and I want to look into when I get some time.

  11. eddyb commented on Jan 20, 2018

    @eddyb
    Contributor

    This isn't really about ordering, but rather a lack of normalization. <&! as Deref>::Target, for example, would exhibit the same problem.

  12. canndrew commented on Jan 21, 2018

    @canndrew
    Contributor

    There seems to be a lot of bugs related to things not getting normalized. I know I've encountered a few before. Are they all the same bug?

  13. eddyb commented on Jan 21, 2018

    @eddyb
    Contributor

    @canndrew Depends. I've been trying to get @nikomatsakis to upstream his lazy normalization work, which would at least make it clear who's responsibility is to normalize anything (if you are traversing types and hit a TyProjection or TyAnon, or want the length of TyArray).

  14. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    and removed
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jan 25, 2018
  15. nikomatsakis commented on Jan 25, 2018

    @nikomatsakis
    Contributor

    triage: P-high

    Regression, though only with never_type feature -- but we'd like to stabilize that!

  16. varkor commented on Jan 25, 2018

    @varkor
    Contributor

    The fix is just waiting on bors. Should be in soon!

  17. added a commit that references this issue on Jan 25, 2018
    9852b23
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-type-systemArea: Type systemC-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-highHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions