-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Rust 1.20.0-nightly ICE with never_type: Broken MIR #43061
Comments
What’s the correct fix? Compiler error with a nice error message? |
I think this should compile and UB, but a lint against this is probably a good idea. |
Reduced test case: // error: internal compiler error: broken MIR in NodeId(4) (_2 = ()):
// bad assignment (! = ()): Sorts(ExpectedFound { expected: !, found: () })
#![crate_type = "lib"]
#![feature(never_type)]
fn blah(x: !) {
x;
// () // Uncommenting this explicit unit return avoids the ICE
} |
I'm working on a fix for this. Progress on this branch. The idea is to avoid the typing issues entirely by terminating the blocks with |
Fix never-type rvalue ICE This fixes #43061. r? @nikomatsakis A small post-mortem as a follow-up to our investigations in #47291: The problem as I understand it is that when `NeverToAny` coercions are made, the expression/statement that is coerced may be enclosed in a block. In our case, the statement `x;` was being transformed to something like: `NeverToAny( {x;} )`. Then, `NeverToAny` is transformed into an expression: https://github.com/rust-lang/rust/blob/000fbbc9b8f88adc6a417f1caef41161f104250f/src/librustc_mir/build/expr/into.rs#L52-L59 Which ends up calling `ast_block_stmts` on the block `{x;}`, which triggers this condition: https://github.com/rust-lang/rust/blob/000fbbc9b8f88adc6a417f1caef41161f104250f/src/librustc_mir/build/block.rs#L141-L147 In our case, there is no return expression, so `push_assign_unit` is called. But the block has already been recorded as _diverging_, meaning the result of the block will be assigned to a location of type `!`, rather than `()`. This causes the MIR error. I'm assuming the `NeverToAny` coercion code is doing what it's supposed to (there don't seem to be any other problems), so fixing the issue simply consists of checking that the destination for the return value actually _is_ supposed to be a unit. (If no return value is given, the only other possible type for the return value is `!`, which can just be ignored, as it will be unreachable anyway.) I checked the other cases of `push_assign_unit`, and it didn't look like they could be affected by the divergence issue (blocks are kind of special-cased in this regard as far as I can tell), so this should be sufficient to fix the issue.
Eager unreachable blocks for `!` type This change optimises the generation of MIR in the presence of `!`. Blocks are now immediately marked as unreachable if: - A function argument is derived from the value of type `!`. - A match arm binds a value whose type is derived from `!`. - An rvalue is created whose type is derived from `!`. This avoids unnecessary MIR generation and also fixes #43061 and #41446. r? @nikomatsakis
The following error results from dereferencing a
*const !
as in this code: https://is.gd/SsSDiGThe text was updated successfully, but these errors were encountered: