MIR building generates mistyped assignments for opaques in dead code
Open
Nobody has claimed this yet.
A-MIR
C-bug
T-compiler
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
enum Never {}
fn foo() -> impl Sized {
let ret = 'block: {
break 'block foo();
};
let _: Never = ret;
ret
}
results in the following MIR:
// MIR for `foo` after built
| User Type Annotations
| 0: user_ty: Canonical { value: Ty(Never), max_universe: U0, variables: [], defining_opaque_types: [DefId(0:6 ~ main[7eb4]::foo::{opaque#0})] }, span: src/main.rs:6:12: 6:17, inferred_ty: Never
| 1: user_ty: Canonical { value: Ty(Never), max_universe: U0, variables: [], defining_opaque_types: [DefId(0:6 ~ main[7eb4]::foo::{opaque#0})] }, span: src/main.rs:6:12: 6:17, inferred_ty: Never
|
fn foo() -> impl Sized {
let mut _0: impl Sized;
let _1: impl Sized;
scope 1 {
debug ret => _1;
scope 2 {
}
}
bb0: {
StorageLive(_1);
_1 = foo() -> [return: bb1, unwind: bb6];
}
bb1: {
goto -> bb3;
}
bb2: {
_1 = const ();
goto -> bb4;
}
bb3: {
goto -> bb4;
}
bb4: {
FakeRead(ForLet(None), _1);
PlaceMention(_1);
AscribeUserType((_1 as Never), +, UserTypeProjection { base: UserType(1), projs: [] });
_0 = move _1;
StorageDead(_1);
return;
}
bb5: {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}
bb6 (cleanup): {
resume;
}
}
notice the _1 = const (); which assigns unit to impl Sized even though its type is Never.
This should result in a type error and therefore an ICE, but apparently we never even get to test that as the block is entirely dead code 🤔 cc @oli-obk
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the reproducer and the MIR output in the issue, then inspect compiler/rustc_mir_build/src/build/block.rs around lines 342-354. Run the example to confirm how the dead block produces _1 = const (); for an opaque value. Done means the invalid assignment is no longer generated, with the resulting type-checking behavior verified.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100