Skip to content

Commit b744930

Browse files
authored
Rollup merge of rust-lang#143075 - workingjubilee:interrupts-may-return-nevermore, r=davidtwco
compiler: Allow `extern "interrupt" fn() -> !` While reviewing rust-lang#142633 I overlooked a few details because I was kind of excited. - Fixes rust-lang#143072
2 parents 026270a + b5ab966 commit b744930

10 files changed

+429
-3
lines changed

compiler/rustc_ast_passes/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ ast_passes_abi_must_not_have_parameters_or_return_type=
1717
1818
ast_passes_abi_must_not_have_return_type=
1919
invalid signature for `extern {$abi}` function
20-
.note = functions with the "custom" ABI cannot have a return type
20+
.note = functions with the {$abi} ABI cannot have a return type
2121
.help = remove the return type
2222
2323
ast_passes_assoc_const_without_body =

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,13 @@ impl<'a> AstValidator<'a> {
390390
if let InterruptKind::X86 = interrupt_kind {
391391
// "x86-interrupt" is special because it does have arguments.
392392
// FIXME(workingjubilee): properly lint on acceptable input types.
393-
if let FnRetTy::Ty(ref ret_ty) = sig.decl.output {
393+
if let FnRetTy::Ty(ref ret_ty) = sig.decl.output
394+
&& match &ret_ty.kind {
395+
TyKind::Never => false,
396+
TyKind::Tup(tup) if tup.is_empty() => false,
397+
_ => true,
398+
}
399+
{
394400
self.dcx().emit_err(errors::AbiMustNotHaveReturnType {
395401
span: ret_ty.span,
396402
abi,
@@ -449,7 +455,13 @@ impl<'a> AstValidator<'a> {
449455

450456
fn reject_params_or_return(&self, abi: ExternAbi, ident: &Ident, sig: &FnSig) {
451457
let mut spans: Vec<_> = sig.decl.inputs.iter().map(|p| p.span).collect();
452-
if let FnRetTy::Ty(ref ret_ty) = sig.decl.output {
458+
if let FnRetTy::Ty(ref ret_ty) = sig.decl.output
459+
&& match &ret_ty.kind {
460+
TyKind::Never => false,
461+
TyKind::Tup(tup) if tup.is_empty() => false,
462+
_ => true,
463+
}
464+
{
453465
spans.push(ret_ty.span);
454466
}
455467

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error: invalid signature for `extern "avr-interrupt"` function
2+
--> $DIR/interrupt-invalid-signature.rs:44:35
3+
|
4+
LL | extern "avr-interrupt" fn avr_arg(_byte: u8) {}
5+
| ^^^^^^^^^
6+
|
7+
= note: functions with the "avr-interrupt" ABI cannot have any parameters or return type
8+
help: remove the parameters and return type
9+
|
10+
LL - extern "avr-interrupt" fn avr_arg(_byte: u8) {}
11+
LL + extern "avr-interrupt" fn avr_arg() {}
12+
|
13+
14+
error: invalid signature for `extern "avr-interrupt"` function
15+
--> $DIR/interrupt-invalid-signature.rs:59:40
16+
|
17+
LL | extern "avr-interrupt" fn avr_ret() -> u8 {
18+
| ^^
19+
|
20+
= note: functions with the "avr-interrupt" ABI cannot have any parameters or return type
21+
help: remove the parameters and return type
22+
|
23+
LL - extern "avr-interrupt" fn avr_ret() -> u8 {
24+
LL + extern "avr-interrupt" fn avr_ret() {
25+
|
26+
27+
error: aborting due to 2 previous errors
28+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: invalid signature for `extern "x86-interrupt"` function
2+
--> $DIR/interrupt-invalid-signature.rs:83:40
3+
|
4+
LL | extern "x86-interrupt" fn x86_ret() -> u8 {
5+
| ^^
6+
|
7+
= note: functions with the "x86-interrupt" ABI cannot have a return type
8+
help: remove the return type
9+
--> $DIR/interrupt-invalid-signature.rs:83:40
10+
|
11+
LL | extern "x86-interrupt" fn x86_ret() -> u8 {
12+
| ^^
13+
14+
error: aborting due to 1 previous error
15+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
error: invalid signature for `extern "msp430-interrupt"` function
2+
--> $DIR/interrupt-invalid-signature.rs:40:41
3+
|
4+
LL | extern "msp430-interrupt" fn msp430_arg(_byte: u8) {}
5+
| ^^^^^^^^^
6+
|
7+
= note: functions with the "msp430-interrupt" ABI cannot have any parameters or return type
8+
help: remove the parameters and return type
9+
|
10+
LL - extern "msp430-interrupt" fn msp430_arg(_byte: u8) {}
11+
LL + extern "msp430-interrupt" fn msp430_arg() {}
12+
|
13+
14+
error: invalid signature for `extern "msp430-interrupt"` function
15+
--> $DIR/interrupt-invalid-signature.rs:65:46
16+
|
17+
LL | extern "msp430-interrupt" fn msp430_ret() -> u8 {
18+
| ^^
19+
|
20+
= note: functions with the "msp430-interrupt" ABI cannot have any parameters or return type
21+
help: remove the parameters and return type
22+
|
23+
LL - extern "msp430-interrupt" fn msp430_ret() -> u8 {
24+
LL + extern "msp430-interrupt" fn msp430_ret() {
25+
|
26+
27+
error: aborting due to 2 previous errors
28+
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
error: invalid signature for `extern "riscv-interrupt-m"` function
2+
--> $DIR/interrupt-invalid-signature.rs:48:43
3+
|
4+
LL | extern "riscv-interrupt-m" fn riscv_m_arg(_byte: u8) {}
5+
| ^^^^^^^^^
6+
|
7+
= note: functions with the "riscv-interrupt-m" ABI cannot have any parameters or return type
8+
help: remove the parameters and return type
9+
|
10+
LL - extern "riscv-interrupt-m" fn riscv_m_arg(_byte: u8) {}
11+
LL + extern "riscv-interrupt-m" fn riscv_m_arg() {}
12+
|
13+
14+
error: invalid signature for `extern "riscv-interrupt-s"` function
15+
--> $DIR/interrupt-invalid-signature.rs:52:43
16+
|
17+
LL | extern "riscv-interrupt-s" fn riscv_s_arg(_byte: u8) {}
18+
| ^^^^^^^^^
19+
|
20+
= note: functions with the "riscv-interrupt-s" ABI cannot have any parameters or return type
21+
help: remove the parameters and return type
22+
|
23+
LL - extern "riscv-interrupt-s" fn riscv_s_arg(_byte: u8) {}
24+
LL + extern "riscv-interrupt-s" fn riscv_s_arg() {}
25+
|
26+
27+
error: invalid signature for `extern "riscv-interrupt-m"` function
28+
--> $DIR/interrupt-invalid-signature.rs:71:48
29+
|
30+
LL | extern "riscv-interrupt-m" fn riscv_m_ret() -> u8 {
31+
| ^^
32+
|
33+
= note: functions with the "riscv-interrupt-m" ABI cannot have any parameters or return type
34+
help: remove the parameters and return type
35+
|
36+
LL - extern "riscv-interrupt-m" fn riscv_m_ret() -> u8 {
37+
LL + extern "riscv-interrupt-m" fn riscv_m_ret() {
38+
|
39+
40+
error: invalid signature for `extern "riscv-interrupt-s"` function
41+
--> $DIR/interrupt-invalid-signature.rs:77:48
42+
|
43+
LL | extern "riscv-interrupt-s" fn riscv_s_ret() -> u8 {
44+
| ^^
45+
|
46+
= note: functions with the "riscv-interrupt-s" ABI cannot have any parameters or return type
47+
help: remove the parameters and return type
48+
|
49+
LL - extern "riscv-interrupt-s" fn riscv_s_ret() -> u8 {
50+
LL + extern "riscv-interrupt-s" fn riscv_s_ret() {
51+
|
52+
53+
error: aborting due to 4 previous errors
54+
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
error: invalid signature for `extern "riscv-interrupt-m"` function
2+
--> $DIR/interrupt-invalid-signature.rs:48:43
3+
|
4+
LL | extern "riscv-interrupt-m" fn riscv_m_arg(_byte: u8) {}
5+
| ^^^^^^^^^
6+
|
7+
= note: functions with the "riscv-interrupt-m" ABI cannot have any parameters or return type
8+
help: remove the parameters and return type
9+
|
10+
LL - extern "riscv-interrupt-m" fn riscv_m_arg(_byte: u8) {}
11+
LL + extern "riscv-interrupt-m" fn riscv_m_arg() {}
12+
|
13+
14+
error: invalid signature for `extern "riscv-interrupt-s"` function
15+
--> $DIR/interrupt-invalid-signature.rs:52:43
16+
|
17+
LL | extern "riscv-interrupt-s" fn riscv_s_arg(_byte: u8) {}
18+
| ^^^^^^^^^
19+
|
20+
= note: functions with the "riscv-interrupt-s" ABI cannot have any parameters or return type
21+
help: remove the parameters and return type
22+
|
23+
LL - extern "riscv-interrupt-s" fn riscv_s_arg(_byte: u8) {}
24+
LL + extern "riscv-interrupt-s" fn riscv_s_arg() {}
25+
|
26+
27+
error: invalid signature for `extern "riscv-interrupt-m"` function
28+
--> $DIR/interrupt-invalid-signature.rs:71:48
29+
|
30+
LL | extern "riscv-interrupt-m" fn riscv_m_ret() -> u8 {
31+
| ^^
32+
|
33+
= note: functions with the "riscv-interrupt-m" ABI cannot have any parameters or return type
34+
help: remove the parameters and return type
35+
|
36+
LL - extern "riscv-interrupt-m" fn riscv_m_ret() -> u8 {
37+
LL + extern "riscv-interrupt-m" fn riscv_m_ret() {
38+
|
39+
40+
error: invalid signature for `extern "riscv-interrupt-s"` function
41+
--> $DIR/interrupt-invalid-signature.rs:77:48
42+
|
43+
LL | extern "riscv-interrupt-s" fn riscv_s_ret() -> u8 {
44+
| ^^
45+
|
46+
= note: functions with the "riscv-interrupt-s" ABI cannot have any parameters or return type
47+
help: remove the parameters and return type
48+
|
49+
LL - extern "riscv-interrupt-s" fn riscv_s_ret() -> u8 {
50+
LL + extern "riscv-interrupt-s" fn riscv_s_ret() {
51+
|
52+
53+
error: aborting due to 4 previous errors
54+
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*! Tests interrupt ABIs have a constricted signature
2+
3+
Most interrupt ABIs share a similar restriction in terms of not allowing most signatures.
4+
Specifically, they generally cannot have arguments or return types.
5+
So we test that they error in essentially all of the same places.
6+
A notable and interesting exception is x86.
7+
8+
This test uses `cfg` because it is not testing whether these ABIs work on the platform.
9+
*/
10+
//@ add-core-stubs
11+
//@ revisions: x64 i686 riscv32 riscv64 avr msp430
12+
//
13+
//@ [x64] needs-llvm-components: x86
14+
//@ [x64] compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib
15+
//@ [i686] needs-llvm-components: x86
16+
//@ [i686] compile-flags: --target=i686-unknown-linux-gnu --crate-type=rlib
17+
//@ [riscv32] needs-llvm-components: riscv
18+
//@ [riscv32] compile-flags: --target=riscv32i-unknown-none-elf --crate-type=rlib
19+
//@ [riscv64] needs-llvm-components: riscv
20+
//@ [riscv64] compile-flags: --target=riscv64gc-unknown-none-elf --crate-type=rlib
21+
//@ [avr] needs-llvm-components: avr
22+
//@ [avr] compile-flags: --target=avr-none -C target-cpu=atmega328p --crate-type=rlib
23+
//@ [msp430] needs-llvm-components: msp430
24+
//@ [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib
25+
#![no_core]
26+
#![feature(
27+
no_core,
28+
abi_msp430_interrupt,
29+
abi_avr_interrupt,
30+
abi_x86_interrupt,
31+
abi_riscv_interrupt
32+
)]
33+
34+
extern crate minicore;
35+
use minicore::*;
36+
37+
/* most extern "interrupt" definitions should not accept args */
38+
39+
#[cfg(msp430)]
40+
extern "msp430-interrupt" fn msp430_arg(_byte: u8) {}
41+
//[msp430]~^ ERROR invalid signature
42+
43+
#[cfg(avr)]
44+
extern "avr-interrupt" fn avr_arg(_byte: u8) {}
45+
//[avr]~^ ERROR invalid signature
46+
47+
#[cfg(any(riscv32,riscv64))]
48+
extern "riscv-interrupt-m" fn riscv_m_arg(_byte: u8) {}
49+
//[riscv32,riscv64]~^ ERROR invalid signature
50+
51+
#[cfg(any(riscv32,riscv64))]
52+
extern "riscv-interrupt-s" fn riscv_s_arg(_byte: u8) {}
53+
//[riscv32,riscv64]~^ ERROR invalid signature
54+
55+
56+
/* all extern "interrupt" definitions should not return non-1ZST values */
57+
58+
#[cfg(avr)]
59+
extern "avr-interrupt" fn avr_ret() -> u8 {
60+
//[avr]~^ ERROR invalid signature
61+
1
62+
}
63+
64+
#[cfg(msp430)]
65+
extern "msp430-interrupt" fn msp430_ret() -> u8 {
66+
//[msp430]~^ ERROR invalid signature
67+
1
68+
}
69+
70+
#[cfg(any(riscv32,riscv64))]
71+
extern "riscv-interrupt-m" fn riscv_m_ret() -> u8 {
72+
//[riscv32,riscv64]~^ ERROR invalid signature
73+
1
74+
}
75+
76+
#[cfg(any(riscv32,riscv64))]
77+
extern "riscv-interrupt-s" fn riscv_s_ret() -> u8 {
78+
//[riscv32,riscv64]~^ ERROR invalid signature
79+
1
80+
}
81+
82+
#[cfg(any(x64,i686))]
83+
extern "x86-interrupt" fn x86_ret() -> u8 {
84+
//[x64,i686]~^ ERROR invalid signature
85+
1
86+
}
87+
88+
89+
90+
/* extern "interrupt" fnptrs with invalid signatures */
91+
92+
#[cfg(avr)]
93+
fn avr_ptr(_f: extern "avr-interrupt" fn(u8) -> u8) {
94+
}
95+
96+
#[cfg(msp430)]
97+
fn msp430_ptr(_f: extern "msp430-interrupt" fn(u8) -> u8) {
98+
}
99+
100+
#[cfg(any(riscv32,riscv64))]
101+
fn riscv_m_ptr(_f: extern "riscv-interrupt-m" fn(u8) -> u8) {
102+
}
103+
104+
#[cfg(any(riscv32,riscv64))]
105+
fn riscv_s_ptr(_f: extern "riscv-interrupt-s" fn(u8) -> u8) {
106+
}
107+
108+
#[cfg(any(x64,i686))]
109+
fn x86_ptr(_f: extern "x86-interrupt" fn() -> u8) {
110+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: invalid signature for `extern "x86-interrupt"` function
2+
--> $DIR/interrupt-invalid-signature.rs:83:40
3+
|
4+
LL | extern "x86-interrupt" fn x86_ret() -> u8 {
5+
| ^^
6+
|
7+
= note: functions with the "x86-interrupt" ABI cannot have a return type
8+
help: remove the return type
9+
--> $DIR/interrupt-invalid-signature.rs:83:40
10+
|
11+
LL | extern "x86-interrupt" fn x86_ret() -> u8 {
12+
| ^^
13+
14+
error: aborting due to 1 previous error
15+

0 commit comments

Comments
 (0)