about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRune Tynan <runetynan@gmail.com>2020-11-17 14:42:29 -0500
committerRune Tynan <runetynan@gmail.com>2020-11-17 14:42:29 -0500
commitc825c74dc9ab5e5f72e9e1736ddf3cb58e3547ed (patch)
tree288b7e14fd1112ae242aa5b4a66b6f295c464f69
parent1e9d5c70c1c435cd9ae217ab0adbb053e643b01f (diff)
downloadrust-c825c74dc9ab5e5f72e9e1736ddf3cb58e3547ed.tar.gz
rust-c825c74dc9ab5e5f72e9e1736ddf3cb58e3547ed.zip
Move change to check_fn, fix up overloaded-calls-nontuple
-rw-r--r--compiler/rustc_typeck/src/check/check.rs31
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs25
-rw-r--r--src/test/ui/overloaded-calls-nontuple.rs2
-rw-r--r--src/test/ui/overloaded-calls-nontuple.stderr16
4 files changed, 47 insertions, 27 deletions
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 70d94ef869d..9d5d1e8c8e2 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -94,6 +94,37 @@ pub(super) fn check_fn<'a, 'tcx>(
 
     fn_maybe_err(tcx, span, fn_sig.abi);
 
+    if fn_sig.abi == abi::Abi::RustCall {
+        let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 };
+
+        let err = || {
+            let item = match tcx.hir().get(fn_id) {
+                Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header),
+                Node::ImplItem(hir::ImplItem {
+                    kind: hir::ImplItemKind::Fn(header, ..), ..
+                }) => Some(header),
+                // Closures are RustCall, but they tuple their arguments, so shouldn't be checked
+                Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => None,
+                node => bug!("Item being checked wasn't a function/closure: {:?}", node),
+            };
+
+            if let Some(header) = item {
+                tcx.sess.span_err(header.span, "A function with the \"rust-call\" ABI must take a single non-self argument that is a tuple")
+            }
+        };
+
+        if fn_sig.inputs().len() != expected_args {
+            err()
+        } else {
+            // 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
+            if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) {
+                err()
+            }
+        }
+    }
+
     if body.generator_kind.is_some() && can_be_generator.is_some() {
         let yield_ty = fcx
             .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index 04cf1bd5b25..35854b0340e 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -521,31 +521,6 @@ 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 = || {
-                    let item = tcx.hir().expect_item(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!("Item being checked wasn't a function")
-                    }
-                };
-
-                if fn_sig.inputs().len() != expected_args {
-                    err()
-                } else {
-                    // 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
-                    if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | 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/overloaded-calls-nontuple.rs b/src/test/ui/overloaded-calls-nontuple.rs
index 62a7130ddeb..76b114c5592 100644
--- a/src/test/ui/overloaded-calls-nontuple.rs
+++ b/src/test/ui/overloaded-calls-nontuple.rs
@@ -11,11 +11,13 @@ impl FnMut<isize> for S {
     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
         self.x + self.y + z
     }
+    //~^^^ ERROR A function with the "rust-call" ABI must take a single non-self argument
 }
 
 impl FnOnce<isize> for S {
     type Output = isize;
     extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
+    //~^ ERROR A function with the "rust-call" ABI must take a single non-self argument
 }
 
 fn main() {
diff --git a/src/test/ui/overloaded-calls-nontuple.stderr b/src/test/ui/overloaded-calls-nontuple.stderr
index 82c12c4b6e1..bdadb95db29 100644
--- a/src/test/ui/overloaded-calls-nontuple.stderr
+++ b/src/test/ui/overloaded-calls-nontuple.stderr
@@ -1,9 +1,21 @@
+error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+  --> $DIR/overloaded-calls-nontuple.rs:11:5
+   |
+LL |     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
+  --> $DIR/overloaded-calls-nontuple.rs:19:5
+   |
+LL |     extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
-  --> $DIR/overloaded-calls-nontuple.rs:26:10
+  --> $DIR/overloaded-calls-nontuple.rs:28:10
    |
 LL |     drop(s(3))
    |          ^^^^
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0059`.