diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 39bf0da5cf957..e1318396e317d 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -213,7 +213,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { let extra_args = &args[sig.inputs.len()..]; let extra_args = extra_args.iter().map(|op_arg| { - self.mir.operand_ty(bcx.tcx(), op_arg) + let op_ty = self.mir.operand_ty(bcx.tcx(), op_arg); + bcx.monomorphize(&op_ty) }).collect::>(); let fn_ty = callee.direct_fn_type(bcx.ccx(), &extra_args); diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs index e57a5cbc5b8b9..b39a6ac1ce381 100644 --- a/src/librustc_trans/mir/lvalue.rs +++ b/src/librustc_trans/mir/lvalue.rs @@ -16,11 +16,11 @@ use abi; use adt; use base; use builder::Builder; -use common::{self, BlockAndBuilder, CrateContext, C_uint}; +use common::{self, BlockAndBuilder, CrateContext, C_uint, C_undef}; use consts; use machine; +use type_of::type_of; use mir::drop; -use llvm; use Disr; use std::ptr; @@ -116,10 +116,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { // Ergo, we return an undef ValueRef, so we do not have to special-case every // place using lvalues, and could use it the same way you use a regular // ReturnPointer LValue (i.e. store into it, load from it etc). - let llty = fcx.fn_ty.ret.original_ty.ptr_to(); - unsafe { - llvm::LLVMGetUndef(llty.to_ref()) - } + C_undef(fcx.fn_ty.ret.original_ty.ptr_to()) }; let fn_return_ty = bcx.monomorphize(&self.mir.return_ty); let return_ty = fn_return_ty.unwrap(); @@ -228,7 +225,19 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { ret } TempRef::Operand(Some(_)) => { - bug!("Lvalue temp already set"); + let lvalue_ty = self.mir.lvalue_ty(bcx.tcx(), lvalue); + let lvalue_ty = bcx.monomorphize(&lvalue_ty); + + // See comments in TempRef::new_operand as to why + // we always have Some in a ZST TempRef::Operand. + let ty = lvalue_ty.to_ty(bcx.tcx()); + if common::type_is_zero_size(bcx.ccx(), ty) { + // Pass an undef pointer as no stores can actually occur. + let llptr = C_undef(type_of(bcx.ccx(), ty).ptr_to()); + f(self, LvalueRef::new_sized(llptr, lvalue_ty)) + } else { + bug!("Lvalue temp already set"); + } } } } diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 1236100a4d51c..45b6bcd920fdf 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -55,6 +55,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> { } mir::Rvalue::Cast(mir::CastKind::Unsize, ref source, cast_ty) => { + let cast_ty = bcx.monomorphize(&cast_ty); + if common::type_is_fat_ptr(bcx.tcx(), cast_ty) { // into-coerce of a thin pointer to a fat pointer - just // use the operand path. diff --git a/src/test/run-pass/mir_coercions.rs b/src/test/run-pass/mir_coercions.rs index c1897f79f22c6..09dd52e30bef9 100644 --- a/src/test/run-pass/mir_coercions.rs +++ b/src/test/run-pass/mir_coercions.rs @@ -55,6 +55,13 @@ fn coerce_fat_ptr_wrapper(p: PtrWrapper u32+Send>) p } +#[rustc_mir] +fn coerce_ptr_wrapper_poly<'a, T, Trait: ?Sized>(p: PtrWrapper<'a, T>) + -> PtrWrapper<'a, Trait> + where PtrWrapper<'a, T>: CoerceUnsized> +{ + p +} fn main() { let a = [0,1,2]; @@ -73,4 +80,8 @@ fn main() { let z = coerce_fat_ptr_wrapper(PtrWrapper(2,3,(),&square_local)); assert_eq!((z.3)(6), 36); + + let z: PtrWrapper u32> = + coerce_ptr_wrapper_poly(PtrWrapper(2,3,(),&square_local)); + assert_eq!((z.3)(6), 36); } diff --git a/src/test/run-pass/mir_trans_calls.rs b/src/test/run-pass/mir_trans_calls.rs index b8b7ecbf03cd6..31e2c8925711c 100644 --- a/src/test/run-pass/mir_trans_calls.rs +++ b/src/test/run-pass/mir_trans_calls.rs @@ -138,6 +138,15 @@ fn test_fn_nil_call(f: &F) -> i32 f() } +#[rustc_mir] +fn test_fn_transmute_zst(x: ()) -> [(); 1] { + fn id(x: T) -> T {x} + + id(unsafe { + std::mem::transmute(x) + }) +} + fn main() { assert_eq!(test1(1, (2, 3), &[4, 5, 6]), (1, (2, 3), &[4, 5, 6][..])); assert_eq!(test2(98), 98); @@ -159,4 +168,5 @@ fn main() { assert_eq!(test_fn_direct_call(&closure, 100, 4), 324); assert_eq!(test_fn_nil_call(&(|| 42)), 42); + assert_eq!(test_fn_transmute_zst(()), [()]); } diff --git a/src/test/run-pass/mir_trans_calls_variadic.rs b/src/test/run-pass/mir_trans_calls_variadic.rs index ff66daace3852..7f711b2758dc7 100644 --- a/src/test/run-pass/mir_trans_calls_variadic.rs +++ b/src/test/run-pass/mir_trans_calls_variadic.rs @@ -16,17 +16,17 @@ extern { } #[rustc_mir] -fn test(a: i64, b: i64, c: i64, d: i64, e: i64, f: i64) -> i64 { +fn test(a: i64, b: i64, c: i64, d: i64, e: i64, f: T, g: U) -> i64 { unsafe { rust_interesting_average(6, a, a as f64, b, b as f64, c, c as f64, d, d as f64, e, e as f64, - f, f as f64) as i64 + f, g) as i64 } } fn main(){ - assert_eq!(test(10, 20, 30, 40, 50, 60), 70); + assert_eq!(test(10, 20, 30, 40, 50, 60_i64, 60.0_f64), 70); }