]> git.lizzy.rs Git - rust.git/commitdiff
Add missing cast for retslots in case of "subtyping" due to trait bounds
authorBjörn Steinbrink <bsteinbr@gmail.com>
Sun, 22 Feb 2015 11:47:27 +0000 (12:47 +0100)
committerBjörn Steinbrink <bsteinbr@gmail.com>
Sun, 22 Feb 2015 11:47:27 +0000 (12:47 +0100)
We already do this for the function arguments, but miss it for the
retslot pointer, which can lead to LLVM assertions because the retslot
has the wrong type.

Fixes #22663

src/librustc_trans/trans/callee.rs
src/test/compile-fail/retslot-cast.rs [new file with mode: 0644]

index 1cc8f62045df8dac6ed2f5d9416035c7dba0872f..25568db814824da35738eaa01acc4b99b2e61cd6 100644 (file)
@@ -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 (file)
index 0000000..fafae0c
--- /dev/null
@@ -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 <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.
+
+#![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