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

Broken MIR with const match #27918

Closed
diaphore opened this issue Aug 20, 2015 · 3 comments · Fixed by #46882
Closed

Broken MIR with const match #27918

diaphore opened this issue Aug 20, 2015 · 3 comments · Fixed by #46882
Labels
C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️

Comments

@diaphore
Copy link
Contributor

empty_and_catchall

fn empty_and_catchall(raw: &[u8]) {
    let mut iter = raw.split(|&b| b == b'/');
    let first = iter.next().unwrap();
    let second = iter.next();

    const EMPTY: &'static [u8] = b"";

    match (first, second) {
        (EMPTY, Some(EMPTY))  => (),
        _ => (),
    }
}

fn main() { empty_and_catchall(b"foo") }
Assertion failed!

Program: C:\Program Files\Rust nightly 1.4\bin\rustc.exe
File: C:/bot/slave/nightly-dist-rustc-win-gnu-64/build/src/llvm/include/llvm/Support/Casting.h, Line 237

Expression: isa<X>(Val) && "cast<Ty>() argument of incompatible type!"

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

empty

fn empty(raw: &[u8]) {
    let mut iter = raw.split(|&b| b == b'/');
    let first = iter.next().unwrap();
    let second = iter.next();

    const EMPTY: &'static [u8] = b"";

    match (first, second) {
        (EMPTY, Some(EMPTY))  => (),
    }
}

fn main() { empty(b"foo") }
thread 'rustc' panicked at 'assertion failed: `(left == right)` (left: `1`, right: `0`)', ../src/librustc\middle\check_match.rs:536

stack backtrace:
   1:         0x699bb42e - sys::backtrace::write::hb12aa40f2f209619ols
   2:         0x699c5115 - rt::unwind::register::h92f30f49d41046e7Qww
   3:         0x6998564f - rt::unwind::begin_unwind_inner::hbffbb4981b0d700aZtw
   4:         0x69985fdc - rt::unwind::begin_unwind_fmt::h393d9d0c019d9fa55sw
   5:         0x6925756e - middle::const_eval::const_expr_to_pat::h09de9c640f8e12dfYuj
   6:         0x692379ac - session::Session::span_note::he19d21226dfbf5ecNYv
   7:         0x6925c905 - middle::ty::TyS<'tcx>::builtin_deref::h8d5bf22a376109d3kcb
   8:         0x6925bbd4 - middle::ty::TyS<'tcx>::builtin_deref::h8d5bf22a376109d3kcb
   9:         0x6925b903 - middle::ty::TyS<'tcx>::builtin_deref::h8d5bf22a376109d3kcb
  10:         0x69237815 - session::Session::span_note::he19d21226dfbf5ecNYv
  11:         0x69230f81 - middle::check_match::MatchCheckCtxt<'a, 'tcx>.Visitor<'v>::visit_expr::h08c39dd719c14c968uh
  12:         0x692327bb - middle::check_match::MatchCheckCtxt<'a, 'tcx>.Visitor<'v>::visit_fn::ha264f9b30c751779Cvh
  13:         0x69232d11 - middle::check_match::check_crate::hf7369bd73cb3b474kwh
  14:         0x6923292b - middle::check_match::check_crate::hf7369bd73cb3b474kwh
  15:         0x67c0a4a3 - driver::assign_node_ids_and_map::habd9138624442090aEa
  16:         0x67be68c9 - driver::assign_node_ids_and_map::habd9138624442090aEa
  17:         0x67be1bb1 - driver::assign_node_ids_and_map::habd9138624442090aEa
  18:         0x67bc278c - driver::compile_input::hec03b27c99a60d9dTba
  19:         0x67d39bd8 - run_compiler::he293276e81cb97efObc
  20:         0x67d374f0 - run::hd965d7dec4214920ubc
  21:         0x67d36f69 - run::hd965d7dec4214920ubc
  22:         0x699ae9b4 - rt::unwind::try::inner_try::hfa861391a664fbdeSpw
  23:         0x67d37104 - run::hd965d7dec4214920ubc
  24:         0x699c2dee - rt::util::report_overflow::h4a1688dd50f7ee7eyaw
  25:     0x7ffdaf8413d2 - BaseThreadInitThunk

neither

Fails to compile but rustc catches the non exhaustive pattern successfully.

fn neither(raw: &[u8]) {
    let mut iter = raw.split(|&b| b == b'/');
    let first = iter.next().unwrap();
    let second = iter.next();

    match (first, second) {
        (b"", Some(b""))  => (),    
    }
}

fn main() { neither(b"foo") }

I have no idea how to include more info from LLVM.

$ rustc --version -v
rustc 1.4.0-nightly (e35fd7481 2015-08-17)
binary: rustc
commit-hash: e35fd748114c22df6d08991980c4f7e199414497
commit-date: 2015-08-17
host: x86_64-pc-windows-gnu
release: 1.4.0-nightly
@diaphore
Copy link
Contributor Author

Simpler program :

fn main() {
    match b"    " {
        b"1234" => ()
    }
}
thread 'rustc' panicked at 'assertion failed: `(left == right)` (left: `1`, right: `4`)', ../src/librustc\middle\check_match.rs:536

stack backtrace:
   1:         0x699bb42e - sys::backtrace::write::hb12aa40f2f209619ols
   2:         0x699c5115 - rt::unwind::register::h92f30f49d41046e7Qww
   3:         0x6998564f - rt::unwind::begin_unwind_inner::hbffbb4981b0d700aZtw
   4:         0x69985fdc - rt::unwind::begin_unwind_fmt::h393d9d0c019d9fa55sw
   5:         0x6925756e - middle::const_eval::const_expr_to_pat::h09de9c640f8e12dfYuj
   6:         0x692379ac - session::Session::span_note::he19d21226dfbf5ecNYv
   7:         0x69230f81 - middle::check_match::MatchCheckCtxt<'a, 'tcx>.Visitor<'v>::visit_expr::h08c39dd719c14c968uh
   8:         0x692327bb - middle::check_match::MatchCheckCtxt<'a, 'tcx>.Visitor<'v>::visit_fn::ha264f9b30c751779Cvh
   9:         0x69232d11 - middle::check_match::check_crate::hf7369bd73cb3b474kwh
  10:         0x6923292b - middle::check_match::check_crate::hf7369bd73cb3b474kwh
  11:         0x67c0a4a3 - driver::assign_node_ids_and_map::habd9138624442090aEa
  12:         0x67be68c9 - driver::assign_node_ids_and_map::habd9138624442090aEa
  13:         0x67be1bb1 - driver::assign_node_ids_and_map::habd9138624442090aEa
  14:         0x67bc278c - driver::compile_input::hec03b27c99a60d9dTba
  15:         0x67d39bd8 - run_compiler::he293276e81cb97efObc
  16:         0x67d374f0 - run::hd965d7dec4214920ubc
  17:         0x67d36f69 - run::hd965d7dec4214920ubc
  18:         0x699ae9b4 - rt::unwind::try::inner_try::hfa861391a664fbdeSpw
  19:         0x67d37104 - run::hd965d7dec4214920ubc
  20:         0x699c2dee - rt::util::report_overflow::h4a1688dd50f7ee7eyaw
  21:     0x7ffdaf8413d2 - BaseThreadInitThunk

rustc does not crash with &str :

fn main() {
    match "    " {
        "1234" => ()
    }
}

@steveklabnik steveklabnik added the I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ label Aug 21, 2015
@leoyvens
Copy link
Contributor

Triage: Only the empty_and_catchall example is still broken, the output now is:

rustc 1.14.0-nightly (6e8f92f11 2016-10-07)
warning: broken MIR ((_11.0: &'static [u8; 0])): bad field access (&[u8]: &'static [u8; 0]): Sorts(ExpectedFound { expected: [u8; 0], found: [u8] })
 --> <anon>:9:10
  |
9 |         (EMPTY, Some(EMPTY))  => (),
  |          ^^^^^

warning: broken MIR ((((_11.1: std::option::Option<&'<empty> [u8]>) as Some).0: &'static [u8; 0])): bad field access (&'<empty> [u8]: &'static [u8; 0]): Sorts(ExpectedFound { expected: [u8; 0], found: [u8] })
 --> <anon>:9:22
  |
9 |         (EMPTY, Some(EMPTY))  => (),
  |                      ^^^^^

rustc: /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/llvm/lib/IR/Instructions.cpp:2759: static llvm::CastInst* llvm::CastInst::CreatePointerCast(llvm::Value*, llvm::Type*, const llvm::Twine&, llvm::Instruction*): Assertion `S->getType()->isPtrOrPtrVectorTy() && "Invalid cast"' failed.
Aborted (core dumped)

@Mark-Simulacrum
Copy link
Member

Reduced down to the following:

fn foo() {
    let a: &[u8] = &[];
    const B: &'static [u8] = b"";
    match (a, 0) {
        (B, 0)  => {},
        _ => {},
    }
}
error: internal compiler error: broken MIR ((_5.0: &'static [u8; 0])): bad field access (&[u8]: &'static [u8; 0]): Sorts(ExpectedFound { expected: [u8; 0], found: [u8] })
 --> test.rs:5:10
  |
5 |         (B, 0)  => {},
  |          ^

note: the compiler unexpectedly panicked. this is a bug.

note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports

thread 'rustc' panicked at 'Box<Any>', src/librustc_errors/lib.rs:421
note: Run with `RUST_BACKTRACE=1` for a backtrace.

@Mark-Simulacrum Mark-Simulacrum changed the title rustc and LLVM crash when using similar matches Broken MIR with const match May 15, 2017
@Mark-Simulacrum Mark-Simulacrum added C-bug Category: This is a bug. and removed C-bug Category: This is a bug. labels Jul 22, 2017
bors added a commit that referenced this issue Jan 18, 2018
Replace all const evaluation with miri

* error reporting in constants prints a stacktrace through all called const fns
* Trivial constant propagation and folding in MIR (always active, irrelevant of the optimization level)
* can now use floating constants in patterns (previously only floating point literals were allowed)
    * the future compat lint is still produced for both cases
* can index into constant arrays during const eval (previously feature gated)
* can create a constant union value with field `a` and read from field `b`
* can dereference references into constants
* can create references inside constants (`const X: &u32 = &22`)
* Tuple struct constructors can be used in constants
* regression in const eval errors spans (some of these need improvements in mir debug info)
* can cast floats to ints and vice versa (in constants, and even nan/inf constants)
* Mir dump prints false/true instead of 0u8/1u8
* `1i8 >> [8][0]` does not lint about exceeding bitshifts anymore.
    * Needs const propagation across projections
* `foo[I]` produces a const eval lint if `foo: [T; N]` and `N < I`
    * Essentially all builtin panics produce lints if they can be statically proven to trigger at runtime. This is on a best effort basis, so there might be some complex cases that don't trigger. (The runtime panic stays there, irrelevant of whether the lint is produced or not)

fixes #34997 (stack overflow with many constants)
fixes #25574 (deref byte strings in patterns)
fixes #27918 (broken mir ICE)
fixes #46114 (ICE on struct constructors in patterns)
fixes #37448 (`SomeStruct { foo } as SomeStruct`)
fixes #43754 (`return` in const fn)
fixes #41898 (tuple struct constructors)
fixes #31364 (infinite recursion with const fn, fixed by miri's recursion limit)
closes #29947 (const indexing stabilization)

r? @eddyb
bors added a commit that referenced this issue Jan 30, 2018
Replace all const evaluation with miri

* error reporting in constants prints a stacktrace through all called const fns
* Trivial constant propagation and folding in MIR (always active, irrelevant of the optimization level)
* can now use floating constants in patterns (previously only floating point literals were allowed)
    * the future compat lint is still produced for both cases
* can index into constant arrays during const eval (previously feature gated)
* can create a constant union value with field `a` and read from field `b`
* can dereference references into constants
* can create references inside constants (`const X: &u32 = &22`)
* Tuple struct constructors can be used in constants
* regression in const eval errors spans (some of these need improvements in mir debug info)
* can cast floats to ints and vice versa (in constants, and even nan/inf constants)
* Mir dump prints false/true instead of 0u8/1u8
* `1i8 >> [8][0]` does not lint about exceeding bitshifts anymore.
    * Needs const propagation across projections
* `foo[I]` produces a const eval lint if `foo: [T; N]` and `N < I`
    * Essentially all builtin panics produce lints if they can be statically proven to trigger at runtime. This is on a best effort basis, so there might be some complex cases that don't trigger. (The runtime panic stays there, irrelevant of whether the lint is produced or not)

fixes #34997 (stack overflow with many constants)
fixes #25574 (deref byte strings in patterns)
fixes #27918 (broken mir ICE)
fixes #46114 (ICE on struct constructors in patterns)
fixes #37448 (`SomeStruct { foo } as SomeStruct`)
fixes #43754 (`return` in const fn)
fixes #41898 (tuple struct constructors)
fixes #31364 (infinite recursion with const fn, fixed by miri's recursion limit)
closes #29947 (const indexing stabilization)
fixes #45044 (pattern matching repeat expressions)

r? @eddyb
bors added a commit that referenced this issue Feb 6, 2018
Replace all const evaluation with miri

* error reporting in constants prints a stacktrace through all called const fns
* Trivial constant propagation and folding in MIR (always active, irrelevant of the optimization level)
* can now use floating constants in patterns (previously only floating point literals were allowed)
    * the future compat lint is still produced for both cases
* can index into constant arrays during const eval (previously feature gated)
* can create a constant union value with field `a` and read from field `b`
* can dereference references into constants
* can create references inside constants (`const X: &u32 = &22`)
* Tuple struct constructors can be used in constants
* regression in const eval errors spans (some of these need improvements in mir debug info)
* can cast floats to ints and vice versa (in constants, and even nan/inf constants)
* Mir dump prints false/true instead of 0u8/1u8
* `1i8 >> [8][0]` does not lint about exceeding bitshifts anymore.
    * Needs const propagation across projections
* `foo[I]` produces a const eval lint if `foo: [T; N]` and `N < I`
    * Essentially all builtin panics produce lints if they can be statically proven to trigger at runtime. This is on a best effort basis, so there might be some complex cases that don't trigger. (The runtime panic stays there, irrelevant of whether the lint is produced or not)
* can use `union`s to implement `transmute` for `Copy` types in constants without a feature gate. With all the greatness and nasal demons that come with this.

fixes #34997 (stack overflow with many constants)
fixes #25574 (deref byte strings in patterns)
fixes #27918 (broken mir ICE)
fixes #46114 (ICE on struct constructors in patterns)
fixes #37448 (`SomeStruct { foo } as SomeStruct`)
fixes #43754 (`return` in const fn)
fixes #41898 (tuple struct constructors)
fixes #31364 (infinite recursion with const fn, fixed by miri's recursion limit)
closes #29947 (const indexing stabilization)
fixes #45044 (pattern matching repeat expressions)
fixes #47971 (ICE on const fn + references)

r? @eddyb
bors added a commit that referenced this issue Mar 7, 2018
Replace all const evaluation with miri

* error reporting in constants prints a stacktrace through all called const fns
* Trivial constant propagation and folding in MIR (always active, irrelevant of the optimization level)
* can now use floating constants in patterns (previously only floating point literals were allowed)
    * the future compat lint is still produced for both cases
* can index into constant arrays during const eval (previously feature gated)
* can create a constant union value with field `a` and read from field `b`
* can dereference references into constants
* can create references inside constants (`const X: &u32 = &22`)
* Tuple struct constructors can be used in constants
* regression in const eval errors spans (some of these need improvements in mir debug info)
* can cast floats to ints and vice versa (in constants, and even nan/inf constants)
* Mir dump prints false/true instead of 0u8/1u8
* `1i8 >> [8][0]` does not lint about exceeding bitshifts anymore.
    * Needs const propagation across projections
* `foo[I]` produces a const eval lint if `foo: [T; N]` and `N < I`
    * Essentially all builtin panics produce lints if they can be statically proven to trigger at runtime. This is on a best effort basis, so there might be some complex cases that don't trigger. (The runtime panic stays there, irrelevant of whether the lint is produced or not)
* can use `union`s to implement `transmute` for `Copy` types in constants without a feature gate. With all the greatness and nasal demons that come with this.
* can convert integers to `&'static T` in constants (useful for embedded)

fixes #34997 (stack overflow with many constants)
fixes #25574 (deref byte strings in patterns)
fixes #27918 (broken mir ICE)
fixes #46114 (ICE on struct constructors in patterns)
fixes #37448 (`SomeStruct { foo } as SomeStruct`)
fixes #43754 (`return` in const fn)
fixes #41898 (tuple struct constructors)
fixes #31364 (infinite recursion with const fn, fixed by miri's recursion limit)
closes #29947 (const indexing stabilization)
fixes #45044 (pattern matching repeat expressions)
fixes #47971 (ICE on const fn + references)
fixes #48081 (ICE on cyclic assoc const error)
fixes #48746 (nonhelpful error message with unions)

r? @eddyb

even though 1k loc are added in tests, this PR reduces the loc in this repository by 700
bors added a commit that referenced this issue Mar 8, 2018
Replace all const evaluation with miri

* error reporting in constants prints a stacktrace through all called const fns
* Trivial constant propagation and folding in MIR (always active, irrelevant of the optimization level)
* can now use floating constants in patterns (previously only floating point literals were allowed)
    * the future compat lint is still produced for both cases
* can index into constant arrays during const eval (previously feature gated)
* can create a constant union value with field `a` and read from field `b`
* can dereference references into constants
* can create references inside constants (`const X: &u32 = &22`)
* Tuple struct constructors can be used in constants
* regression in const eval errors spans (some of these need improvements in mir debug info)
* can cast floats to ints and vice versa (in constants, and even nan/inf constants)
* Mir dump prints false/true instead of 0u8/1u8
* `1i8 >> [8][0]` does not lint about exceeding bitshifts anymore.
    * Needs const propagation across projections
* `foo[I]` produces a const eval lint if `foo: [T; N]` and `N < I`
    * Essentially all builtin panics produce lints if they can be statically proven to trigger at runtime. This is on a best effort basis, so there might be some complex cases that don't trigger. (The runtime panic stays there, irrelevant of whether the lint is produced or not)
* can use `union`s to implement `transmute` for `Copy` types in constants without a feature gate. With all the greatness and nasal demons that come with this.
* can convert integers to `&'static T` in constants (useful for embedded)

fixes #34997 (stack overflow with many constants)
fixes #25574 (deref byte strings in patterns)
fixes #27918 (broken mir ICE)
fixes #46114 (ICE on struct constructors in patterns)
fixes #37448 (`SomeStruct { foo } as SomeStruct`)
fixes #43754 (`return` in const fn)
fixes #41898 (tuple struct constructors)
fixes #31364 (infinite recursion with const fn, fixed by miri's recursion limit)
closes #29947 (const indexing stabilization)
fixes #45044 (pattern matching repeat expressions)
fixes #47971 (ICE on const fn + references)
fixes #48081 (ICE on cyclic assoc const error)
fixes #48746 (nonhelpful error message with unions)

r? @eddyb

even though 1k loc are added in tests, this PR reduces the loc in this repository by 700
steveklabnik added a commit to rust-lang/glacier that referenced this issue Aug 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants