Skip to content

Commit 5a58b50

Browse files
authored
Rollup merge of #78961 - CraftSpider:22565, r=oli-obk
Make bad "rust-call" arguments no longer ICE The simplest of bad rust-call definitions will no longer cause an ICE. There is a FIXME added for future work, as I wanted to get this easy fix in before trying to either add a hack or mess with the whole obligation system fixes #22565
2 parents 7e20323 + e8426a6 commit 5a58b50

9 files changed

+85
-15
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::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

+1-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};
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.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
1515
extern "platform-intrinsic" fn f2() {} //~ ERROR platform intrinsics are experimental
1616
//~^ ERROR intrinsic must be in
1717
extern "vectorcall" fn f3() {} //~ ERROR vectorcall is experimental and subject to change
18-
extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change
18+
extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change
1919
extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental
2020
extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change
2121
extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
@@ -30,7 +30,7 @@ trait Tr {
3030
extern "platform-intrinsic" fn m2(); //~ ERROR platform intrinsics are experimental
3131
//~^ ERROR intrinsic must be in
3232
extern "vectorcall" fn m3(); //~ ERROR vectorcall is experimental and subject to change
33-
extern "rust-call" fn m4(); //~ ERROR rust-call ABI is subject to change
33+
extern "rust-call" fn m4(_: ()); //~ ERROR rust-call ABI is subject to change
3434
extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental
3535
extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change
3636
extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
@@ -39,7 +39,7 @@ trait Tr {
3939
extern "efiapi" fn m10(); //~ ERROR efiapi ABI is experimental and subject to change
4040

4141
extern "vectorcall" fn dm3() {} //~ ERROR vectorcall is experimental and subject to change
42-
extern "rust-call" fn dm4() {} //~ ERROR rust-call ABI is subject to change
42+
extern "rust-call" fn dm4(_: ()) {} //~ ERROR rust-call ABI is subject to change
4343
extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental
4444
extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change
4545
extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
@@ -57,7 +57,7 @@ impl Tr for S {
5757
extern "platform-intrinsic" fn m2() {} //~ ERROR platform intrinsics are experimental
5858
//~^ ERROR intrinsic must be in
5959
extern "vectorcall" fn m3() {} //~ ERROR vectorcall is experimental and subject to change
60-
extern "rust-call" fn m4() {} //~ ERROR rust-call ABI is subject to change
60+
extern "rust-call" fn m4(_: ()) {} //~ ERROR rust-call ABI is subject to change
6161
extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental
6262
extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change
6363
extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
@@ -73,7 +73,7 @@ impl S {
7373
extern "platform-intrinsic" fn im2() {} //~ ERROR platform intrinsics are experimental
7474
//~^ ERROR intrinsic must be in
7575
extern "vectorcall" fn im3() {} //~ ERROR vectorcall is experimental and subject to change
76-
extern "rust-call" fn im4() {} //~ ERROR rust-call ABI is subject to change
76+
extern "rust-call" fn im4(_: ()) {} //~ ERROR rust-call ABI is subject to change
7777
extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental
7878
extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change
7979
extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
@@ -86,7 +86,7 @@ impl S {
8686
type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
8787
type A2 = extern "platform-intrinsic" fn(); //~ ERROR platform intrinsics are experimental
8888
type A3 = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental and subject to change
89-
type A4 = extern "rust-call" fn(); //~ ERROR rust-call ABI is subject to change
89+
type A4 = extern "rust-call" fn(_: ()); //~ ERROR rust-call ABI is subject to change
9090
type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental
9191
type A6 = extern "ptx-kernel" fn (); //~ ERROR PTX ABIs are experimental and subject to change
9292
type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental

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

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)