From c825c74dc9ab5e5f72e9e1736ddf3cb58e3547ed Mon Sep 17 00:00:00 2001 From: Rune Tynan Date: Tue, 17 Nov 2020 14:42:29 -0500 Subject: [PATCH] Move change to check_fn, fix up overloaded-calls-nontuple --- compiler/rustc_typeck/src/check/check.rs | 31 ++++++++++++++++++++ compiler/rustc_typeck/src/check/mod.rs | 25 ---------------- src/test/ui/overloaded-calls-nontuple.rs | 2 ++ src/test/ui/overloaded-calls-nontuple.stderr | 16 ++++++++-- 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 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 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`.