Skip to content

Commit 633c92c

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 633c92c

File tree

2 files changed

+47
-14
lines changed

2 files changed

+47
-14
lines changed

compiler/rustc_mir_transform/src/known_panics_lint.rs

+26-14
Original file line numberDiff line numberDiff line change
@@ -585,20 +585,32 @@ 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 the last element of the `Adt` tuple
593+
// is `Some` it indicates the ADT is a union
594+
if let AggregateKind::Adt(_, _, _, _, Some(_)) = **kind {
595+
return None;
596+
};
597+
Value::Aggregate {
598+
fields: fields
599+
.iter()
600+
.map(|field| {
601+
self.eval_operand(field).map_or(Value::Uninit, Value::Immediate)
602+
})
603+
.collect(),
604+
variant: match **kind {
605+
AggregateKind::Adt(_, variant, _, _, _) => variant,
606+
AggregateKind::Array(_)
607+
| AggregateKind::Tuple
608+
| AggregateKind::Closure(_, _)
609+
| AggregateKind::Coroutine(_, _)
610+
| AggregateKind::CoroutineClosure(_, _) => VariantIdx::new(0),
611+
},
612+
}
613+
}
602614

603615
Repeat(ref op, n) => {
604616
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)