Skip to content

Commit 75c79bd

Browse files
committed
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
1 parent bacb5c5 commit 75c79bd

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

src/librustc_trans/mir/constant.rs

Lines changed: 4 additions & 1 deletion
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
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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+
union DummyUnion {
14+
field1: i32,
15+
field2: i32,
16+
}
17+
18+
const fn read_field() -> i32 {
19+
const UNION: DummyUnion = DummyUnion { field1: 5 };
20+
const FIELD: i32 = unsafe { UNION.field2 };
21+
FIELD
22+
}
23+
24+
fn main() {
25+
assert_eq!(read_field(), 5);
26+
}

0 commit comments

Comments
 (0)