Skip to content

Commit 05067cf

Browse files
committed
Fix an ICE when attempting to transmute an uninhabited type
1 parent dbd10f8 commit 05067cf

File tree

2 files changed

+46
-3
lines changed

2 files changed

+46
-3
lines changed

src/librustc_codegen_llvm/mir/block.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -428,9 +428,19 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
428428
let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
429429

430430
if intrinsic == Some("transmute") {
431-
let &(ref dest, target) = destination.as_ref().unwrap();
432-
self.codegen_transmute(&bx, &args[0], dest);
433-
funclet_br(self, bx, target);
431+
if let Some(destination_ref) = destination.as_ref() {
432+
let &(ref dest, target) = destination_ref;
433+
self.trans_transmute(&bx, &args[0], dest);
434+
funclet_br(self, bx, target);
435+
} else {
436+
// If we are trying to transmute to an uninhabited type,
437+
// it is likely there is no allotted destination. In fact,
438+
// transmuting to an uninhabited type is UB, which means
439+
// we can do what we like. Here, we declare that transmuting
440+
// into an uninhabited type is impossible, so anything following
441+
// it must be unreachable.
442+
bx.unreachable();
443+
}
434444
return;
435445
}
436446

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
// compile-pass
12+
13+
#![crate_type="lib"]
14+
15+
#![feature(never_type)]
16+
#![allow(dead_code)]
17+
#![allow(unreachable_code)]
18+
#![allow(unused_variables)]
19+
20+
struct Foo;
21+
22+
pub fn f(x: !) -> ! {
23+
x
24+
}
25+
26+
pub fn ub() {
27+
// This is completely undefined behaviour,
28+
// but we still want to make sure it compiles.
29+
let x: ! = unsafe {
30+
std::mem::transmute::<Foo, !>(Foo)
31+
};
32+
f(x)
33+
}

0 commit comments

Comments
 (0)