diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 1cc8f62045d..25568db8148 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -765,8 +765,16 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, if is_rust_fn { let mut llargs = Vec::new(); - if let (ty::FnConverging(ret_ty), Some(llretslot)) = (ret_ty, opt_llretslot) { + if let (ty::FnConverging(ret_ty), Some(mut llretslot)) = (ret_ty, opt_llretslot) { if type_of::return_uses_outptr(ccx, ret_ty) { + let llformal_ret_ty = type_of::type_of(ccx, ret_ty).ptr_to(); + let llret_ty = common::val_ty(llretslot); + if llformal_ret_ty != llret_ty { + // this could happen due to e.g. subtyping + debug!("casting actual return type ({}) to match formal ({})", + bcx.llty_str(llret_ty), bcx.llty_str(llformal_ret_ty)); + llretslot = PointerCast(bcx, llretslot, llformal_ret_ty); + } llargs.push(llretslot); } } diff --git a/src/test/compile-fail/retslot-cast.rs b/src/test/compile-fail/retslot-cast.rs new file mode 100644 index 00000000000..fafae0cb705 --- /dev/null +++ b/src/test/compile-fail/retslot-cast.rs @@ -0,0 +1,25 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] +#![allow(warnings)] + +pub fn fail(x: Option<& (Iterator+Send)>) -> Option<&Iterator> { + // This call used to trigger an LLVM assertion because the return slot had type + // "Option<&Iterator>"* instead of "Option<&(Iterator+Send)>"* + inner(x) +} + +pub fn inner(x: Option<& (Iterator+Send)>) -> Option<&(Iterator+Send)> { + x +} + +#[rustc_error] +fn main() {} //~ ERROR compilation successful