let intrinsic = intrinsic.as_ref().map(|s| &s[..]);
if intrinsic == Some("transmute") {
- let &(ref dest, target) = destination.as_ref().unwrap();
- self.codegen_transmute(&bx, &args[0], dest);
- funclet_br(self, bx, target);
+ if let Some(destination_ref) = destination.as_ref() {
+ let &(ref dest, target) = destination_ref;
+ self.trans_transmute(&bx, &args[0], dest);
+ funclet_br(self, bx, target);
+ } else {
+ // If we are trying to transmute to an uninhabited type,
+ // it is likely there is no allotted destination. In fact,
+ // transmuting to an uninhabited type is UB, which means
+ // we can do what we like. Here, we declare that transmuting
+ // into an uninhabited type is impossible, so anything following
+ // it must be unreachable.
+ bx.unreachable();
+ }
return;
}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![crate_type="lib"]
+
+#![feature(never_type)]
+#![allow(dead_code)]
+#![allow(unreachable_code)]
+#![allow(unused_variables)]
+
+struct Foo;
+
+pub fn f(x: !) -> ! {
+ x
+}
+
+pub fn ub() {
+ // This is completely undefined behaviour,
+ // but we still want to make sure it compiles.
+ let x: ! = unsafe {
+ std::mem::transmute::<Foo, !>(Foo)
+ };
+ f(x)
+}