Skip to content

Commit

Permalink
Do not const pop unions
Browse files Browse the repository at this point in the history
as they can made to produce values whose types don't
match their underlying layout types which can lead to
ICEs on eval
  • Loading branch information
gurry committed Feb 26, 2024
1 parent 0250ef2 commit 633c92c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 14 deletions.
40 changes: 26 additions & 14 deletions compiler/rustc_mir_transform/src/known_panics_lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -585,20 +585,32 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
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);
Expand Down
21 changes: 21 additions & 0 deletions tests/ui/lint/ice-unions-known-panics-lint-issue-121534.rs
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit 633c92c

Please sign in to comment.