about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs32
-rw-r--r--src/test/ui/abi/issues/issue-22565-rust-call.rs8
-rw-r--r--src/test/ui/abi/issues/issue-22565-rust-call.stderr8
-rw-r--r--src/test/ui/abi/rustcall-generic.rs9
-rw-r--r--src/test/ui/feature-gates/feature-gate-abi.stderr12
5 files changed, 62 insertions, 7 deletions
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 169ad0df3a5..67592fa7840 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -108,7 +108,7 @@ use rustc_hir::def::Res;
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::intravisit::Visitor;
 use rustc_hir::itemlikevisit::ItemLikeVisitor;
-use rustc_hir::{HirIdMap, Node};
+use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::Idx;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -137,6 +137,7 @@ use crate::util::common::indenter;
 
 use self::coercion::DynamicCoerceMany;
 pub use self::Expectation::*;
+use rustc_target::spec::abi;
 
 #[macro_export]
 macro_rules! type_error_struct {
@@ -520,6 +521,35 @@ fn typeck_with_fallback<'tcx>(
 
             let fn_sig = fixup_opaque_types(tcx, &fn_sig);
 
+            if fn_sig.abi == abi::Abi::RustCall {
+                let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 };
+
+                let err = || {
+                    if let Node::Item(item) = tcx.hir().get(id) {
+                        if let hir::ItemKind::Fn(header, ..) = &item.kind {
+                            tcx.sess.span_err(header.span, "A function with the \"rust-call\" ABI must take a single non-self argument that is a tuple")
+                        }
+                    } else {
+                        bug!("Couldn't get span of FnHeader being checked")
+                    }
+                };
+
+                if fn_sig.inputs().len() != expected_args {
+                    err()
+                } else {
+                    match fn_sig.inputs()[expected_args - 1].kind() {
+                        ty::Tuple(_) => (),
+                        // FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
+                        //   This will probably require wide-scale changes to support a TupleKind obligation
+                        //   We can't resolve this without knowing the type of the param
+                        ty::Param(_) => (),
+                        _ => {
+                            err()
+                        }
+                    }
+                }
+            }
+
             let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0;
             fcx
         } else {
diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.rs b/src/test/ui/abi/issues/issue-22565-rust-call.rs
new file mode 100644
index 00000000000..055d959b46e
--- /dev/null
+++ b/src/test/ui/abi/issues/issue-22565-rust-call.rs
@@ -0,0 +1,8 @@
+#![feature(unboxed_closures)]
+
+extern "rust-call" fn b(_i: i32) {}
+//~^ ERROR A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+
+fn main () {
+    b(10);
+}
diff --git a/src/test/ui/abi/issues/issue-22565-rust-call.stderr b/src/test/ui/abi/issues/issue-22565-rust-call.stderr
new file mode 100644
index 00000000000..31fb035eb99
--- /dev/null
+++ b/src/test/ui/abi/issues/issue-22565-rust-call.stderr
@@ -0,0 +1,8 @@
+error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+  --> $DIR/issue-22565-rust-call.rs:3:1
+   |
+LL | extern "rust-call" fn b(_i: i32) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/abi/rustcall-generic.rs b/src/test/ui/abi/rustcall-generic.rs
new file mode 100644
index 00000000000..2fa41a7e35a
--- /dev/null
+++ b/src/test/ui/abi/rustcall-generic.rs
@@ -0,0 +1,9 @@
+// check-pass
+#![feature(unboxed_closures)]
+
+extern "rust-call" fn foo<T>(_: T) {}
+
+fn main() {
+    foo(());
+    foo((1, 2));
+}
diff --git a/src/test/ui/feature-gates/feature-gate-abi.stderr b/src/test/ui/feature-gates/feature-gate-abi.stderr
index 50cd8bc68a2..25f0c259d11 100644
--- a/src/test/ui/feature-gates/feature-gate-abi.stderr
+++ b/src/test/ui/feature-gates/feature-gate-abi.stderr
@@ -26,7 +26,7 @@ LL | extern "vectorcall" fn f3() {}
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:18:8
    |
-LL | extern "rust-call" fn f4() {}
+LL | extern "rust-call" fn f4(_: ()) {}
    |        ^^^^^^^^^^^
    |
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -113,7 +113,7 @@ LL |     extern "vectorcall" fn m3();
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:33:12
    |
-LL |     extern "rust-call" fn m4();
+LL |     extern "rust-call" fn m4(_: ());
    |            ^^^^^^^^^^^
    |
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -183,7 +183,7 @@ LL |     extern "vectorcall" fn dm3() {}
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:42:12
    |
-LL |     extern "rust-call" fn dm4() {}
+LL |     extern "rust-call" fn dm4(_: ()) {}
    |            ^^^^^^^^^^^
    |
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -270,7 +270,7 @@ LL |     extern "vectorcall" fn m3() {}
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:60:12
    |
-LL |     extern "rust-call" fn m4() {}
+LL |     extern "rust-call" fn m4(_: ()) {}
    |            ^^^^^^^^^^^
    |
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -357,7 +357,7 @@ LL |     extern "vectorcall" fn im3() {}
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:76:12
    |
-LL |     extern "rust-call" fn im4() {}
+LL |     extern "rust-call" fn im4(_: ()) {}
    |            ^^^^^^^^^^^
    |
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -444,7 +444,7 @@ LL | type A3 = extern "vectorcall" fn();
 error[E0658]: rust-call ABI is subject to change
   --> $DIR/feature-gate-abi.rs:89:18
    |
-LL | type A4 = extern "rust-call" fn();
+LL | type A4 = extern "rust-call" fn(_: ());
    |                  ^^^^^^^^^^^
    |
    = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information