about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAnthony Ramine <n.oxyde@gmail.com>2018-04-11 17:25:18 +0200
committerAnthony Ramine <n.oxyde@gmail.com>2018-04-26 15:07:04 +0200
commitb7c8cc4b778b2fcf4193a3f7fd9cf8c323ebcf5c (patch)
tree1226d542d47a193c17c263b2bb5ac78737a2eb5b
parent3eca70a0c55e9f081ebff9a7af6fa25390d99b4c (diff)
downloadrust-b7c8cc4b778b2fcf4193a3f7fd9cf8c323ebcf5c.tar.gz
rust-b7c8cc4b778b2fcf4193a3f7fd9cf8c323ebcf5c.zip
Properly look for uninhabitedness when handling discriminants
-rw-r--r--src/librustc_mir/interpret/eval_context.rs3
-rw-r--r--src/librustc_trans/mir/place.rs5
-rw-r--r--src/librustc_trans/mir/rvalue.rs10
3 files changed, 15 insertions, 3 deletions
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index b98ab218de5..478f45e841d 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -850,6 +850,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
     ) -> EvalResult<'tcx, u128> {
         let layout = self.layout_of(ty)?;
         trace!("read_discriminant_value {:#?}", layout);
+        if layout.abi == layout::Abi::Uninhabited {
+            return Ok(0);
+        }
 
         match layout.variants {
             layout::Variants::Single { index } => {
diff --git a/src/librustc_trans/mir/place.rs b/src/librustc_trans/mir/place.rs
index b340d91b027..3cadaef47bb 100644
--- a/src/librustc_trans/mir/place.rs
+++ b/src/librustc_trans/mir/place.rs
@@ -16,7 +16,7 @@ use rustc::mir::tcx::PlaceTy;
 use rustc_data_structures::indexed_vec::Idx;
 use base;
 use builder::Builder;
-use common::{CodegenCx, C_usize, C_u8, C_u32, C_uint, C_int, C_null, C_uint_big};
+use common::{CodegenCx, C_undef, C_usize, C_u8, C_u32, C_uint, C_int, C_null, C_uint_big};
 use consts;
 use type_of::LayoutLlvmExt;
 use type_::Type;
@@ -264,6 +264,9 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
     /// Obtain the actual discriminant of a value.
     pub fn trans_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef {
         let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
+        if self.layout.abi == layout::Abi::Uninhabited {
+            return C_undef(cast_to);
+        }
         match self.layout.variants {
             layout::Variants::Single { index } => {
                 return C_uint(cast_to, index as u64);
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 93702bfbbf3..245f3ec11c9 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -22,7 +22,7 @@ use base;
 use builder::Builder;
 use callee;
 use common::{self, val_ty};
-use common::{C_bool, C_u8, C_i32, C_u32, C_u64, C_null, C_usize, C_uint, C_uint_big};
+use common::{C_bool, C_u8, C_i32, C_u32, C_u64, C_undef, C_null, C_usize, C_uint, C_uint_big};
 use consts;
 use monomorphize;
 use type_::Type;
@@ -267,11 +267,17 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                     }
                     mir::CastKind::Misc => {
                         assert!(cast.is_llvm_immediate());
+                        let ll_t_out = cast.immediate_llvm_type(bx.cx);
+                        if operand.layout.abi == layout::Abi::Uninhabited {
+                            return (bx, OperandRef {
+                                val: OperandValue::Immediate(C_undef(ll_t_out)),
+                                layout: cast,
+                            });
+                        }
                         let r_t_in = CastTy::from_ty(operand.layout.ty)
                             .expect("bad input type for cast");
                         let r_t_out = CastTy::from_ty(cast.ty).expect("bad output type for cast");
                         let ll_t_in = operand.layout.immediate_llvm_type(bx.cx);
-                        let ll_t_out = cast.immediate_llvm_type(bx.cx);
                         let llval = operand.immediate();
 
                         let mut signed = false;