Skip to content

Commit 5dfb006

Browse files
committed
Do not const pop unions
as they can made to produce values whose types don't match their underlying layout types which can lead to ICEs on eval
1 parent 0250ef2 commit 5dfb006

File tree

2 files changed

+48
-14
lines changed

2 files changed

+48
-14
lines changed

compiler/rustc_mir_transform/src/known_panics_lint.rs

+27-14
Original file line numberDiff line numberDiff line change
@@ -585,20 +585,33 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
585585
val.into()
586586
}
587587

588-
Aggregate(ref kind, ref fields) => Value::Aggregate {
589-
fields: fields
590-
.iter()
591-
.map(|field| self.eval_operand(field).map_or(Value::Uninit, Value::Immediate))
592-
.collect(),
593-
variant: match **kind {
594-
AggregateKind::Adt(_, variant, _, _, _) => variant,
595-
AggregateKind::Array(_)
596-
| AggregateKind::Tuple
597-
| AggregateKind::Closure(_, _)
598-
| AggregateKind::Coroutine(_, _)
599-
| AggregateKind::CoroutineClosure(_, _) => VariantIdx::new(0),
600-
},
601-
},
588+
Aggregate(ref kind, ref fields) => {
589+
// Do not const pop union fields as they can be
590+
// made to produce values that don't match their
591+
// underlying layout's type (see ICE #121534).
592+
// If `field_idx` is `Some` it indicates the ADT is a union
593+
if let AggregateKind::Adt(_, _, _, _, field_idx) = **kind
594+
&& field_idx.is_some()
595+
{
596+
return None;
597+
};
598+
Value::Aggregate {
599+
fields: fields
600+
.iter()
601+
.map(|field| {
602+
self.eval_operand(field).map_or(Value::Uninit, Value::Immediate)
603+
})
604+
.collect(),
605+
variant: match **kind {
606+
AggregateKind::Adt(_, variant, _, _, _) => variant,
607+
AggregateKind::Array(_)
608+
| AggregateKind::Tuple
609+
| AggregateKind::Closure(_, _)
610+
| AggregateKind::Coroutine(_, _)
611+
| AggregateKind::CoroutineClosure(_, _) => VariantIdx::new(0),
612+
},
613+
}
614+
}
602615

603616
Repeat(ref op, n) => {
604617
trace!(?op, ?n);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Regression test for #121534
2+
// Tests that no ICE occurs in KnownPanicsLint when it
3+
// evaluates an operation whose operands have different
4+
// layout types even though they have the same type.
5+
// This situation can be contrived through the use of
6+
// unions as in this test
7+
8+
//@ build-pass
9+
union Union {
10+
u32_field: u32,
11+
i32_field: i32,
12+
}
13+
14+
pub fn main() {
15+
let u32_variant = Union { u32_field: 2 };
16+
let i32_variant = Union { i32_field: 3 };
17+
let a = unsafe { u32_variant.u32_field };
18+
let b = unsafe { i32_variant.u32_field };
19+
20+
let _diff = a - b;
21+
}

0 commit comments

Comments
 (0)