Skip to content

Commit 5e7fd65

Browse files
committed
Auto merge of #47794 - etaoins:fix-ice-on-const-eval-of-union-field, r=eddyb
Fix ICE on const eval of union field MIR's `Const::get_field()` attempts to retrieve the value for a given field in a constant. In the case of a union constant it was falling through to a generic `const_get_elt` based on the field index. As union fields don't have an index this caused an ICE in `llvm_field_index`. Fix by simply returning the current value when accessing any field in a union. This works because all union fields start at byte offset 0. The added test uses `const_fn` it ensure the field is extracted using MIR's const evaluation. The crash is reproducible without it, however. Fixes #47788 r? @eddyb
2 parents 0119b44 + ed7e4e1 commit 5e7fd65

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

src/librustc_trans/mir/constant.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,10 @@ impl<'a, 'tcx> Const<'tcx> {
140140
}
141141
}
142142
_ => {
143-
const_get_elt(self.llval, layout.llvm_field_index(i))
143+
match layout.fields {
144+
layout::FieldPlacement::Union(_) => self.llval,
145+
_ => const_get_elt(self.llval, layout.llvm_field_index(i)),
146+
}
144147
}
145148
}
146149
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(const_fn)]
12+
13+
type Field1 = i32;
14+
type Field2 = f32;
15+
type Field3 = i64;
16+
17+
union DummyUnion {
18+
field1: Field1,
19+
field2: Field2,
20+
field3: Field3,
21+
}
22+
23+
const FLOAT1_AS_I32: i32 = 1065353216;
24+
const UNION: DummyUnion = DummyUnion { field1: FLOAT1_AS_I32 };
25+
26+
const fn read_field1() -> Field1 {
27+
const FIELD1: Field1 = unsafe { UNION.field1 };
28+
FIELD1
29+
}
30+
31+
const fn read_field2() -> Field2 {
32+
const FIELD2: Field2 = unsafe { UNION.field2 };
33+
FIELD2
34+
}
35+
36+
const fn read_field3() -> Field3 {
37+
const FIELD3: Field3 = unsafe { UNION.field3 };
38+
FIELD3
39+
}
40+
41+
fn main() {
42+
assert_eq!(read_field1(), FLOAT1_AS_I32);
43+
assert_eq!(read_field2(), 1.0);
44+
assert_eq!(read_field3(), unsafe { UNION.field3 });
45+
}

0 commit comments

Comments
 (0)