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
This commit is contained in:
parent
0250ef2571
commit
633c92cd6d
@ -585,20 +585,32 @@ fn eval_rvalue(&mut self, rvalue: &Rvalue<'tcx>, dest: &Place<'tcx>) -> Option<(
|
||||
val.into()
|
||||
}
|
||||
|
||||
Aggregate(ref kind, ref fields) => Value::Aggregate {
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|field| self.eval_operand(field).map_or(Value::Uninit, Value::Immediate))
|
||||
.collect(),
|
||||
variant: match **kind {
|
||||
AggregateKind::Adt(_, variant, _, _, _) => variant,
|
||||
AggregateKind::Array(_)
|
||||
| AggregateKind::Tuple
|
||||
| AggregateKind::Closure(_, _)
|
||||
| AggregateKind::Coroutine(_, _)
|
||||
| AggregateKind::CoroutineClosure(_, _) => VariantIdx::new(0),
|
||||
},
|
||||
},
|
||||
Aggregate(ref kind, ref fields) => {
|
||||
// Do not const pop union fields as they can be
|
||||
// made to produce values that don't match their
|
||||
// underlying layout's type (see ICE #121534).
|
||||
// If the last element of the `Adt` tuple
|
||||
// is `Some` it indicates the ADT is a union
|
||||
if let AggregateKind::Adt(_, _, _, _, Some(_)) = **kind {
|
||||
return None;
|
||||
};
|
||||
Value::Aggregate {
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|field| {
|
||||
self.eval_operand(field).map_or(Value::Uninit, Value::Immediate)
|
||||
})
|
||||
.collect(),
|
||||
variant: match **kind {
|
||||
AggregateKind::Adt(_, variant, _, _, _) => variant,
|
||||
AggregateKind::Array(_)
|
||||
| AggregateKind::Tuple
|
||||
| AggregateKind::Closure(_, _)
|
||||
| AggregateKind::Coroutine(_, _)
|
||||
| AggregateKind::CoroutineClosure(_, _) => VariantIdx::new(0),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Repeat(ref op, n) => {
|
||||
trace!(?op, ?n);
|
||||
|
21
tests/ui/lint/ice-unions-known-panics-lint-issue-121534.rs
Normal file
21
tests/ui/lint/ice-unions-known-panics-lint-issue-121534.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// Regression test for #121534
|
||||
// Tests that no ICE occurs in KnownPanicsLint when it
|
||||
// evaluates an operation whose operands have different
|
||||
// layout types even though they have the same type.
|
||||
// This situation can be contrived through the use of
|
||||
// unions as in this test
|
||||
|
||||
//@ build-pass
|
||||
union Union {
|
||||
u32_field: u32,
|
||||
i32_field: i32,
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let u32_variant = Union { u32_field: 2 };
|
||||
let i32_variant = Union { i32_field: 3 };
|
||||
let a = unsafe { u32_variant.u32_field };
|
||||
let b = unsafe { i32_variant.u32_field };
|
||||
|
||||
let _diff = a - b;
|
||||
}
|
Loading…
Reference in New Issue
Block a user