Skip to content

Commit c825c74

Browse files
committed
Move change to check_fn, fix up overloaded-calls-nontuple
1 parent 1e9d5c7 commit c825c74

File tree

4 files changed

+47
-27
lines changed

4 files changed

+47
-27
lines changed

compiler/rustc_typeck/src/check/check.rs

+31
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,37 @@ pub(super) fn check_fn<'a, 'tcx>(
9494

9595
fn_maybe_err(tcx, span, fn_sig.abi);
9696

97+
if fn_sig.abi == abi::Abi::RustCall {
98+
let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 };
99+
100+
let err = || {
101+
let item = match tcx.hir().get(fn_id) {
102+
Node::Item(hir::Item { kind: ItemKind::Fn(header, ..), .. }) => Some(header),
103+
Node::ImplItem(hir::ImplItem {
104+
kind: hir::ImplItemKind::Fn(header, ..), ..
105+
}) => Some(header),
106+
// Closures are RustCall, but they tuple their arguments, so shouldn't be checked
107+
Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => None,
108+
node => bug!("Item being checked wasn't a function/closure: {:?}", node),
109+
};
110+
111+
if let Some(header) = item {
112+
tcx.sess.span_err(header.span, "A function with the \"rust-call\" ABI must take a single non-self argument that is a tuple")
113+
}
114+
};
115+
116+
if fn_sig.inputs().len() != expected_args {
117+
err()
118+
} else {
119+
// FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
120+
// This will probably require wide-scale changes to support a TupleKind obligation
121+
// We can't resolve this without knowing the type of the param
122+
if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) {
123+
err()
124+
}
125+
}
126+
}
127+
97128
if body.generator_kind.is_some() && can_be_generator.is_some() {
98129
let yield_ty = fcx
99130
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });

compiler/rustc_typeck/src/check/mod.rs

-25
Original file line numberDiff line numberDiff line change
@@ -521,31 +521,6 @@ fn typeck_with_fallback<'tcx>(
521521

522522
let fn_sig = fixup_opaque_types(tcx, &fn_sig);
523523

524-
if fn_sig.abi == abi::Abi::RustCall {
525-
let expected_args = if let ImplicitSelfKind::None = decl.implicit_self { 1 } else { 2 };
526-
527-
let err = || {
528-
let item = tcx.hir().expect_item(id);
529-
530-
if let hir::ItemKind::Fn(header, ..) = &item.kind {
531-
tcx.sess.span_err(header.span, "A function with the \"rust-call\" ABI must take a single non-self argument that is a tuple")
532-
} else {
533-
bug!("Item being checked wasn't a function")
534-
}
535-
};
536-
537-
if fn_sig.inputs().len() != expected_args {
538-
err()
539-
} else {
540-
// FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
541-
// This will probably require wide-scale changes to support a TupleKind obligation
542-
// We can't resolve this without knowing the type of the param
543-
if !matches!(fn_sig.inputs()[expected_args - 1].kind(), ty::Tuple(_) | ty::Param(_)) {
544-
err()
545-
}
546-
}
547-
}
548-
549524
let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0;
550525
fcx
551526
} else {

src/test/ui/overloaded-calls-nontuple.rs

+2
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ impl FnMut<isize> for S {
1111
extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
1212
self.x + self.y + z
1313
}
14+
//~^^^ ERROR A function with the "rust-call" ABI must take a single non-self argument
1415
}
1516

1617
impl FnOnce<isize> for S {
1718
type Output = isize;
1819
extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
20+
//~^ ERROR A function with the "rust-call" ABI must take a single non-self argument
1921
}
2022

2123
fn main() {
+14-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1+
error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
2+
--> $DIR/overloaded-calls-nontuple.rs:11:5
3+
|
4+
LL | extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
8+
--> $DIR/overloaded-calls-nontuple.rs:19:5
9+
|
10+
LL | extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
113
error[E0059]: cannot use call notation; the first type parameter for the function trait is neither a tuple nor unit
2-
--> $DIR/overloaded-calls-nontuple.rs:26:10
14+
--> $DIR/overloaded-calls-nontuple.rs:28:10
315
|
416
LL | drop(s(3))
517
| ^^^^
618

7-
error: aborting due to previous error
19+
error: aborting due to 3 previous errors
820

921
For more information about this error, try `rustc --explain E0059`.

0 commit comments

Comments
 (0)