Skip to content

Commit 91eabf5

Browse files
committed
Add a sane error for rust-call functions not taking tuples during type checking, and associated UI tests
1 parent 9d78d1d commit 91eabf5

File tree

5 files changed

+62
-7
lines changed

5 files changed

+62
-7
lines changed

compiler/rustc_typeck/src/check/mod.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ use rustc_hir::def::Res;
108108
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
109109
use rustc_hir::intravisit::Visitor;
110110
use rustc_hir::itemlikevisit::ItemLikeVisitor;
111-
use rustc_hir::{HirIdMap, Node};
111+
use rustc_hir::{HirIdMap, ImplicitSelfKind, Node};
112112
use rustc_index::bit_set::BitSet;
113113
use rustc_index::vec::Idx;
114114
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -137,6 +137,7 @@ use crate::util::common::indenter;
137137

138138
use self::coercion::DynamicCoerceMany;
139139
pub use self::Expectation::*;
140+
use rustc_target::spec::abi;
140141

141142
#[macro_export]
142143
macro_rules! type_error_struct {
@@ -520,6 +521,35 @@ fn typeck_with_fallback<'tcx>(
520521

521522
let fn_sig = fixup_opaque_types(tcx, &fn_sig);
522523

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+
if let Node::Item(item) = tcx.hir().get(id) {
529+
if let hir::ItemKind::Fn(header, ..) = &item.kind {
530+
tcx.sess.span_err(header.span, "A function with the \"rust-call\" ABI must take a single non-self argument that is a tuple")
531+
}
532+
} else {
533+
bug!("Couldn't get span of FnHeader being checked")
534+
}
535+
};
536+
537+
if fn_sig.inputs().len() != expected_args {
538+
err()
539+
} else {
540+
match fn_sig.inputs()[expected_args - 1].kind() {
541+
ty::Tuple(_) => (),
542+
// FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
543+
// This will probably require wide-scale changes to support a TupleKind obligation
544+
// We can't resolve this without knowing the type of the param
545+
ty::Param(_) => (),
546+
_ => {
547+
err()
548+
}
549+
}
550+
}
551+
}
552+
523553
let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None).0;
524554
fcx
525555
} else {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(unboxed_closures)]
2+
3+
extern "rust-call" fn b(_i: i32) {}
4+
//~^ ERROR A function with the "rust-call" ABI must take a single non-self argument that is a tuple
5+
6+
fn main () {
7+
b(10);
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: A function with the "rust-call" ABI must take a single non-self argument that is a tuple
2+
--> $DIR/issue-22565-rust-call.rs:3:1
3+
|
4+
LL | extern "rust-call" fn b(_i: i32) {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+

src/test/ui/abi/rustcall-generic.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// check-pass
2+
#![feature(unboxed_closures)]
3+
4+
extern "rust-call" fn foo<T>(_: T) {}
5+
6+
fn main() {
7+
foo(());
8+
foo((1, 2));
9+
}

src/test/ui/feature-gates/feature-gate-abi.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ LL | extern "vectorcall" fn f3() {}
2626
error[E0658]: rust-call ABI is subject to change
2727
--> $DIR/feature-gate-abi.rs:18:8
2828
|
29-
LL | extern "rust-call" fn f4() {}
29+
LL | extern "rust-call" fn f4(_: ()) {}
3030
| ^^^^^^^^^^^
3131
|
3232
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -113,7 +113,7 @@ LL | extern "vectorcall" fn m3();
113113
error[E0658]: rust-call ABI is subject to change
114114
--> $DIR/feature-gate-abi.rs:33:12
115115
|
116-
LL | extern "rust-call" fn m4();
116+
LL | extern "rust-call" fn m4(_: ());
117117
| ^^^^^^^^^^^
118118
|
119119
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -183,7 +183,7 @@ LL | extern "vectorcall" fn dm3() {}
183183
error[E0658]: rust-call ABI is subject to change
184184
--> $DIR/feature-gate-abi.rs:42:12
185185
|
186-
LL | extern "rust-call" fn dm4() {}
186+
LL | extern "rust-call" fn dm4(_: ()) {}
187187
| ^^^^^^^^^^^
188188
|
189189
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -270,7 +270,7 @@ LL | extern "vectorcall" fn m3() {}
270270
error[E0658]: rust-call ABI is subject to change
271271
--> $DIR/feature-gate-abi.rs:60:12
272272
|
273-
LL | extern "rust-call" fn m4() {}
273+
LL | extern "rust-call" fn m4(_: ()) {}
274274
| ^^^^^^^^^^^
275275
|
276276
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
@@ -357,7 +357,7 @@ LL | extern "vectorcall" fn im3() {}
357357
error[E0658]: rust-call ABI is subject to change
358358
--> $DIR/feature-gate-abi.rs:76:12
359359
|
360-
LL | extern "rust-call" fn im4() {}
360+
LL | extern "rust-call" fn im4(_: ()) {}
361361
| ^^^^^^^^^^^
362362
|
363363
= 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();
444444
error[E0658]: rust-call ABI is subject to change
445445
--> $DIR/feature-gate-abi.rs:89:18
446446
|
447-
LL | type A4 = extern "rust-call" fn();
447+
LL | type A4 = extern "rust-call" fn(_: ());
448448
| ^^^^^^^^^^^
449449
|
450450
= note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information

0 commit comments

Comments
 (0)