Skip to content

Commit 345a2e1

Browse files
committed
Auto merge of #148302 - folkertdev:non-rustic-unsized, r=bjorn3
error on non-rustic ABIs using unsized parameters tracking issue: #48055 This came up in #144529 (comment). The idea is that the layout of an unsized type is unstable (following the rust layout rules), and hence stable ABIs should not use unsized types. On stable, unsized types (or generics with a `?Sized` bound) are not accepted as parameters, so the errors introduced by this PR can only be observed when the unstable `unsized_fn_params` feature is enabled. r? `@bjorn3` cc `@RalfJung`
2 parents 8e0b68e + 52bfde2 commit 345a2e1

File tree

6 files changed

+228
-4
lines changed

6 files changed

+228
-4
lines changed

compiler/rustc_abi/src/canon_abi.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,20 @@ pub enum CanonAbi {
5151
X86(X86Call),
5252
}
5353

54+
impl CanonAbi {
55+
pub fn is_rustic_abi(self) -> bool {
56+
match self {
57+
CanonAbi::Rust | CanonAbi::RustCold => true,
58+
CanonAbi::C
59+
| CanonAbi::Custom
60+
| CanonAbi::Arm(_)
61+
| CanonAbi::GpuKernel
62+
| CanonAbi::Interrupt(_)
63+
| CanonAbi::X86(_) => false,
64+
}
65+
}
66+
}
67+
5468
impl fmt::Display for CanonAbi {
5569
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
5670
// convert to the ExternAbi that *shares a string* with this CanonAbi.

compiler/rustc_monomorphize/messages.ftl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@ monomorphize_abi_error_disabled_vector_type =
1212
} here
1313
.help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`)
1414
15+
monomorphize_abi_error_unsupported_unsized_parameter =
16+
this function {$is_call ->
17+
[true] call
18+
*[false] definition
19+
} uses unsized type `{$ty}` which is not supported with the chosen ABI
20+
.label = function {$is_call ->
21+
[true] called
22+
*[false] defined
23+
} here
24+
.help = only rustic ABIs support unsized parameters
25+
1526
monomorphize_abi_error_unsupported_vector_type =
1627
this function {$is_call ->
1728
[true] call

compiler/rustc_monomorphize/src/errors.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,18 @@ pub(crate) struct AbiErrorDisabledVectorType<'a> {
8080
pub is_call: bool,
8181
}
8282

83+
#[derive(Diagnostic)]
84+
#[diag(monomorphize_abi_error_unsupported_unsized_parameter)]
85+
#[help]
86+
pub(crate) struct AbiErrorUnsupportedUnsizedParameter<'a> {
87+
#[primary_span]
88+
#[label]
89+
pub span: Span,
90+
pub ty: Ty<'a>,
91+
/// Whether this is a problem at a call site or at a declaration.
92+
pub is_call: bool,
93+
}
94+
8395
#[derive(Diagnostic)]
8496
#[diag(monomorphize_abi_error_unsupported_vector_type)]
8597
pub(crate) struct AbiErrorUnsupportedVectorType<'a> {

compiler/rustc_monomorphize/src/mono_checks/abi_check.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,37 @@ fn do_check_simd_vector_abi<'tcx>(
7878
}
7979
}
8080

81-
/// Checks that the ABI of a given instance of a function does not contain vector-passed arguments
82-
/// or return values for which the corresponding target feature is not enabled.
81+
/// Emit an error when a non-rustic ABI has unsized parameters.
82+
/// Unsized types do not have a stable layout, so should not be used with stable ABIs.
83+
/// `is_call` indicates whether this is a call-site check or a definition-site check;
84+
/// this is only relevant for the wording in the emitted error.
85+
fn do_check_unsized_params<'tcx>(
86+
tcx: TyCtxt<'tcx>,
87+
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
88+
is_call: bool,
89+
loc: impl Fn() -> (Span, HirId),
90+
) {
91+
// Unsized parameters are allowed with the (unstable) "Rust" (and similar) ABIs.
92+
if fn_abi.conv.is_rustic_abi() {
93+
return;
94+
}
95+
96+
for arg_abi in fn_abi.args.iter() {
97+
if !arg_abi.layout.layout.is_sized() {
98+
let (span, _hir_id) = loc();
99+
tcx.dcx().emit_err(errors::AbiErrorUnsupportedUnsizedParameter {
100+
span,
101+
ty: arg_abi.layout.ty,
102+
is_call,
103+
});
104+
}
105+
}
106+
}
107+
108+
/// Checks the ABI of an Instance, emitting an error when:
109+
///
110+
/// - a non-rustic ABI uses unsized parameters
111+
/// - the signature requires target features that are not enabled
83112
fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
84113
let typing_env = ty::TypingEnv::fully_monomorphized();
85114
let Ok(abi) = tcx.fn_abi_of_instance(typing_env.as_query_input((instance, ty::List::empty())))
@@ -102,11 +131,14 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
102131
def_id.as_local().map(|did| tcx.local_def_id_to_hir_id(did)).unwrap_or(CRATE_HIR_ID),
103132
)
104133
};
134+
do_check_unsized_params(tcx, abi, /*is_call*/ false, loc);
105135
do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, loc);
106136
}
107137

108-
/// Checks that a call expression does not try to pass a vector-passed argument which requires a
109-
/// target feature that the caller does not have, as doing so causes UB because of ABI mismatch.
138+
/// Check the ABI at a call site, emitting an error when:
139+
///
140+
/// - a non-rustic ABI uses unsized parameters
141+
/// - the signature requires target features that are not enabled
110142
fn check_call_site_abi<'tcx>(
111143
tcx: TyCtxt<'tcx>,
112144
callee: Ty<'tcx>,
@@ -140,6 +172,7 @@ fn check_call_site_abi<'tcx>(
140172
// ABI failed to compute; this will not get through codegen.
141173
return;
142174
};
175+
do_check_unsized_params(tcx, callee_abi, /*is_call*/ true, loc);
143176
do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, loc);
144177
}
145178

tests/ui/abi/non-rustic-unsized.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//@ add-core-stubs
2+
//@ build-fail
3+
#![no_core]
4+
#![crate_type = "lib"]
5+
#![feature(no_core, unsized_fn_params)]
6+
#![allow(improper_ctypes_definitions, improper_ctypes)]
7+
8+
extern crate minicore;
9+
use minicore::*;
10+
11+
fn rust(_: [u8]) {}
12+
extern "C" fn c(_: [u8]) {}
13+
//~^ ERROR this function definition uses unsized type `[u8]` which is not supported with the chosen ABI
14+
extern "system" fn system(_: [u8]) {}
15+
//~^ ERROR this function definition uses unsized type `[u8]` which is not supported with the chosen ABI
16+
17+
#[repr(C)]
18+
struct CustomUnsized {
19+
a: i64,
20+
b: [u8],
21+
}
22+
23+
extern "C" fn c_custom_unsized(x: CustomUnsized) {}
24+
//~^ ERROR this function definition uses unsized type `CustomUnsized` which is not supported with the chosen ABI
25+
26+
#[unsafe(no_mangle)]
27+
fn entry(x: [u8], y: [u8], z: [u8], w: CustomUnsized) {
28+
rust(x);
29+
c(y);
30+
//~^ ERROR this function call uses unsized type `[u8]` which is not supported with the chosen ABI
31+
system(z);
32+
//~^ ERROR this function call uses unsized type `[u8]` which is not supported with the chosen ABI
33+
c_custom_unsized(w);
34+
//~^ ERROR this function call uses unsized type `CustomUnsized` which is not supported with the chosen ABI
35+
}
36+
37+
#[unsafe(no_mangle)]
38+
fn test_fn_ptr(rust: extern "Rust" fn(_: [u8]), c: extern "C" fn(_: [u8]), x: [u8], y: [u8]) {
39+
rust(x);
40+
c(y);
41+
//~^ ERROR this function call uses unsized type `[u8]` which is not supported with the chosen ABI
42+
}
43+
44+
#[unsafe(no_mangle)]
45+
fn test_extern(x: [u8], y: [u8]) {
46+
unsafe extern "Rust" {
47+
safe fn rust(_: [u8]);
48+
}
49+
50+
unsafe extern "system" {
51+
safe fn system(_: [u8]);
52+
}
53+
54+
rust(x);
55+
system(y);
56+
//~^ ERROR this function call uses unsized type `[u8]` which is not supported with the chosen ABI
57+
}
58+
59+
extern "C" fn c_polymorphic<T: ?Sized>(_: T) {}
60+
//~^ ERROR this function definition uses unsized type `[u8]` which is not supported with the chosen ABI
61+
62+
#[unsafe(no_mangle)]
63+
fn test_polymorphic(x: [u8]) {
64+
c_polymorphic(x);
65+
//~^ ERROR this function call uses unsized type `[u8]` which is not supported with the chosen ABI
66+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
error: this function call uses unsized type `[u8]` which is not supported with the chosen ABI
2+
--> $DIR/non-rustic-unsized.rs:29:5
3+
|
4+
LL | c(y);
5+
| ^^^^ function called here
6+
|
7+
= help: only rustic ABIs support unsized parameters
8+
9+
error: this function call uses unsized type `[u8]` which is not supported with the chosen ABI
10+
--> $DIR/non-rustic-unsized.rs:31:5
11+
|
12+
LL | system(z);
13+
| ^^^^^^^^^ function called here
14+
|
15+
= help: only rustic ABIs support unsized parameters
16+
17+
error: this function call uses unsized type `CustomUnsized` which is not supported with the chosen ABI
18+
--> $DIR/non-rustic-unsized.rs:33:5
19+
|
20+
LL | c_custom_unsized(w);
21+
| ^^^^^^^^^^^^^^^^^^^ function called here
22+
|
23+
= help: only rustic ABIs support unsized parameters
24+
25+
error: this function definition uses unsized type `[u8]` which is not supported with the chosen ABI
26+
--> $DIR/non-rustic-unsized.rs:12:1
27+
|
28+
LL | extern "C" fn c(_: [u8]) {}
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
30+
|
31+
= help: only rustic ABIs support unsized parameters
32+
33+
error: this function definition uses unsized type `[u8]` which is not supported with the chosen ABI
34+
--> $DIR/non-rustic-unsized.rs:14:1
35+
|
36+
LL | extern "system" fn system(_: [u8]) {}
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
38+
|
39+
= help: only rustic ABIs support unsized parameters
40+
41+
error: this function definition uses unsized type `CustomUnsized` which is not supported with the chosen ABI
42+
--> $DIR/non-rustic-unsized.rs:23:1
43+
|
44+
LL | extern "C" fn c_custom_unsized(x: CustomUnsized) {}
45+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
46+
|
47+
= help: only rustic ABIs support unsized parameters
48+
49+
error: this function call uses unsized type `[u8]` which is not supported with the chosen ABI
50+
--> $DIR/non-rustic-unsized.rs:40:5
51+
|
52+
LL | c(y);
53+
| ^^^^ function called here
54+
|
55+
= help: only rustic ABIs support unsized parameters
56+
57+
error: this function call uses unsized type `[u8]` which is not supported with the chosen ABI
58+
--> $DIR/non-rustic-unsized.rs:55:5
59+
|
60+
LL | system(y);
61+
| ^^^^^^^^^ function called here
62+
|
63+
= help: only rustic ABIs support unsized parameters
64+
65+
error: this function call uses unsized type `[u8]` which is not supported with the chosen ABI
66+
--> $DIR/non-rustic-unsized.rs:64:5
67+
|
68+
LL | c_polymorphic(x);
69+
| ^^^^^^^^^^^^^^^^ function called here
70+
|
71+
= help: only rustic ABIs support unsized parameters
72+
73+
error: this function definition uses unsized type `[u8]` which is not supported with the chosen ABI
74+
--> $DIR/non-rustic-unsized.rs:59:1
75+
|
76+
LL | extern "C" fn c_polymorphic<T: ?Sized>(_: T) {}
77+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here
78+
|
79+
= help: only rustic ABIs support unsized parameters
80+
81+
note: the above error was encountered while instantiating `fn c_polymorphic::<[u8]>`
82+
--> $DIR/non-rustic-unsized.rs:64:5
83+
|
84+
LL | c_polymorphic(x);
85+
| ^^^^^^^^^^^^^^^^
86+
87+
error: aborting due to 10 previous errors
88+

0 commit comments

Comments
 (0)