Skip to content

Commit 46115fd

Browse files
committed
fix ICE in CMSE type validation
1 parent d678b81 commit 46115fd

File tree

3 files changed

+70
-13
lines changed

3 files changed

+70
-13
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ pub(crate) fn validate_cmse_abi<'tcx>(
1818
abi: abi::Abi,
1919
fn_sig: ty::PolyFnSig<'tcx>,
2020
) {
21+
// this type is only used for layout computation, which does not rely on regions
22+
let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
23+
2124
if let abi::Abi::CCmseNonSecureCall = abi {
2225
let hir_node = tcx.hir_node(hir_id);
2326
let hir::Node::Ty(hir::Ty {
@@ -67,13 +70,13 @@ pub(crate) fn validate_cmse_abi<'tcx>(
6770
/// Returns whether the inputs will fit into the available registers
6871
fn is_valid_cmse_inputs<'tcx>(
6972
tcx: TyCtxt<'tcx>,
70-
fn_sig: ty::PolyFnSig<'tcx>,
73+
fn_sig: ty::FnSig<'tcx>,
7174
) -> Result<Result<(), usize>, &'tcx LayoutError<'tcx>> {
7275
let mut span = None;
7376
let mut accum = 0u64;
7477

75-
for (index, arg_def) in fn_sig.inputs().iter().enumerate() {
76-
let layout = tcx.layout_of(ParamEnv::reveal_all().and(*arg_def.skip_binder()))?;
78+
for (index, ty) in fn_sig.inputs().iter().enumerate() {
79+
let layout = tcx.layout_of(ParamEnv::reveal_all().and(*ty))?;
7780

7881
let align = layout.layout.align().abi.bytes();
7982
let size = layout.layout.size().bytes();
@@ -96,9 +99,9 @@ fn is_valid_cmse_inputs<'tcx>(
9699
/// Returns whether the output will fit into the available registers
97100
fn is_valid_cmse_output<'tcx>(
98101
tcx: TyCtxt<'tcx>,
99-
fn_sig: ty::PolyFnSig<'tcx>,
102+
fn_sig: ty::FnSig<'tcx>,
100103
) -> Result<bool, &'tcx LayoutError<'tcx>> {
101-
let mut ret_ty = fn_sig.output().skip_binder();
104+
let mut ret_ty = fn_sig.output();
102105
let layout = tcx.layout_of(ParamEnv::reveal_all().and(ret_ty))?;
103106
let size = layout.layout.size().bytes();
104107

tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.rs

+23-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,31 @@ impl Copy for u32 {}
1212
struct Wrapper<T>(T);
1313

1414
struct Test<T: Copy> {
15-
f1: extern "C-cmse-nonsecure-call" fn<U: Copy>(U, u32, u32, u32) -> u64, //~ ERROR cannot find type `U` in this scope
16-
//~^ ERROR function pointer types may not have generic parameters
15+
f1: extern "C-cmse-nonsecure-call" fn<U: Copy>(U, u32, u32, u32) -> u64,
16+
//~^ ERROR cannot find type `U` in this scope
17+
//~| ERROR function pointer types may not have generic parameters
1718
f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64,
1819
//~^ ERROR `impl Trait` is not allowed in `fn` pointer parameters
1920
f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64, //~ ERROR [E0798]
2021
f4: extern "C-cmse-nonsecure-call" fn(Wrapper<T>, u32, u32, u32) -> u64, //~ ERROR [E0798]
2122
}
23+
24+
type WithReference = extern "C-cmse-nonsecure-call" fn(&usize);
25+
26+
trait Trait {}
27+
type WithTraitObject = extern "C-cmse-nonsecure-call" fn(&dyn Trait) -> &dyn Trait;
28+
//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
29+
30+
type WithStaticTraitObject =
31+
extern "C-cmse-nonsecure-call" fn(&'static dyn Trait) -> &'static dyn Trait;
32+
//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
33+
34+
#[repr(transparent)]
35+
struct WrapperTransparent<'a>(&'a dyn Trait);
36+
37+
type WithTransparentTraitObject =
38+
extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTransparent;
39+
//~^ ERROR return value of `"C-cmse-nonsecure-call"` function too large to pass via registers [E0798]
40+
41+
type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);
42+
//~^ ERROR C-variadic function must have a compatible calling convention, like `C` or `cdecl` [E0045]

tests/ui/cmse-nonsecure/cmse-nonsecure-call/generics.stderr

+39-6
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,59 @@ LL | struct Test<T: Copy, U> {
2222
| +++
2323

2424
error[E0562]: `impl Trait` is not allowed in `fn` pointer parameters
25-
--> $DIR/generics.rs:17:43
25+
--> $DIR/generics.rs:18:43
2626
|
2727
LL | f2: extern "C-cmse-nonsecure-call" fn(impl Copy, u32, u32, u32) -> u64,
2828
| ^^^^^^^^^
2929
|
3030
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
3131

3232
error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
33-
--> $DIR/generics.rs:19:9
33+
--> $DIR/generics.rs:20:9
3434
|
3535
LL | f3: extern "C-cmse-nonsecure-call" fn(T, u32, u32, u32) -> u64,
3636
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3737

3838
error[E0798]: function pointers with the `"C-cmse-nonsecure-call"` ABI cannot contain generics in their type
39-
--> $DIR/generics.rs:20:9
39+
--> $DIR/generics.rs:21:9
4040
|
4141
LL | f4: extern "C-cmse-nonsecure-call" fn(Wrapper<T>, u32, u32, u32) -> u64,
4242
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4343

44-
error: aborting due to 5 previous errors
44+
error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
45+
--> $DIR/generics.rs:27:73
46+
|
47+
LL | type WithTraitObject = extern "C-cmse-nonsecure-call" fn(&dyn Trait) -> &dyn Trait;
48+
| ^^^^^^^^^^ this type doesn't fit in the available registers
49+
|
50+
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
51+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
52+
53+
error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
54+
--> $DIR/generics.rs:31:62
55+
|
56+
LL | extern "C-cmse-nonsecure-call" fn(&'static dyn Trait) -> &'static dyn Trait;
57+
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
58+
|
59+
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
60+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
61+
62+
error[E0798]: return value of `"C-cmse-nonsecure-call"` function too large to pass via registers
63+
--> $DIR/generics.rs:38:62
64+
|
65+
LL | extern "C-cmse-nonsecure-call" fn(WrapperTransparent) -> WrapperTransparent;
66+
| ^^^^^^^^^^^^^^^^^^ this type doesn't fit in the available registers
67+
|
68+
= note: functions with the `"C-cmse-nonsecure-call"` ABI must pass their result via the available return registers
69+
= note: the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
70+
71+
error[E0045]: C-variadic function must have a compatible calling convention, like `C` or `cdecl`
72+
--> $DIR/generics.rs:41:20
73+
|
74+
LL | type WithVarArgs = extern "C-cmse-nonsecure-call" fn(u32, ...);
75+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
76+
77+
error: aborting due to 9 previous errors
4578

46-
Some errors have detailed explanations: E0412, E0562, E0798.
47-
For more information about an error, try `rustc --explain E0412`.
79+
Some errors have detailed explanations: E0045, E0412, E0562, E0798.
80+
For more information about an error, try `rustc --explain E0045`.

0 commit comments

Comments
 (0)