Add extern "custom" - #2300
Conversation
|
Reminder, once the PR becomes ready for a review, use |
Co-authored-by: Travis Cross <tc@traviscross.com>
The `extern "custom"` rules were falling under the *Unwinding* section. Let's fix that.
This had said that an `extern "custom"` function *does* not have any parameters, but it's clearer to say it *must* not have any parameters.
c83d315 to
112dfa2
Compare
ac3a0e7 to
8752db9
Compare
On the lang side, we decided the signature rules for `extern "custom"` function pointers should match those for `extern "custom"` function items. Let's consolidate the signature rules on function items into a single rule then cite that rule normatively from the function pointer types chapter.
8752db9 to
e6edcf3
Compare
In review, it was suggested that we add an example showing how `extern "custom"` functions are used in practice. Let's do that.
Often naked functions should use `extern "custom"`. Let's add an admonition to note that.
e6edcf3 to
66b3bc5
Compare
| - Be `unsafe`. | ||
| - Not have any parameters. | ||
| - Return the [unit type]. |
There was a problem hiding this comment.
Needs some consideration for generics, rust-lang/rust#158504 (comment) and the comment below
There was a problem hiding this comment.
I guess that generics are probably okay and allowed by default if not disallowed?
There was a problem hiding this comment.
Looking through the list at https://doc.rust-lang.org/reference/items/functions.html#attributes-on-functions, also noticed that #[cold] may make no sense. Everything else seems fine
There was a problem hiding this comment.
It doesn't do harm either, so should we really make an exception here? I'm not against it per se, just wondering if we should make this calling convention even more special.
d4018bd to
217edc5
Compare
There was a problem hiding this comment.
I've added two updates based on the T-lang meeting (notes).
- we decided that the current implementation of only allowing unit as a return type syntactically (i.e. type aliases that resolve to unit are rejected) is acceptable.
- rust-lang/rust#161002
…, r=tgross35 Stabilize `extern "custom"` tracking issue: rust-lang#140829 reference PR: rust-lang/reference#2300 closes rust-lang#140829 ## Summary An `extern "custom" fn` is a function with a custom ABI that is unknown to rust. Often these are low-level functions that pass arguments in different registers than any standard calling convention. ```rust #[unsafe(naked)] pub unsafe extern "custom" fn __aeabi_uidivmod() { core::arch::naked_asm!( "push {{lr}}", "sub sp, sp, rust-lang#4", "mov r2, sp", "bl {trampoline}", "ldr r1, [sp]", "add sp, sp, rust-lang#4", "pop {{pc}}", trampoline = sym crate::arm::__udivmodsi4 ); } unsafe extern "custom" { fn __fentry__(); } ``` ## Design Because rust doesn't know what calling convention to use, an `extern "custom"` function can only be called via inline assembly or FFI. ``` error: functions with the "custom" ABI cannot be called --> <source>:5:5 | 5 | bar(); | ^^^^^ | note: an `extern "custom"` function can only be called using inline assembly ``` An `extern "custom"` function definition must be a naked function: ``` error: items with the "custom" ABI can only be declared externally or defined via naked functions --> <source>:10:1 | 10 | unsafe extern "custom" fn bar() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: convert this to an `#[unsafe(naked)]` function | 10 + #[unsafe(naked)] 11 | unsafe extern "custom" fn bar() { | ``` An `extern "custom"` function definition must be unsafe. The intent here is that a safety comment is written on how this function may be called. ``` error: functions with the "custom" ABI must be unsafe --> <source>:10:1 | 10 | extern "custom" fn bar() { | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: add the `unsafe` keyword to this definition | 10 | unsafe extern "custom" fn bar() { | ++++++ ``` In an `extern "custom"` block, functions cannot be marked as `safe`: ``` error: foreign functions with the "custom" ABI cannot be safe --> <source>:16:5 | 16 | safe fn foobar(); | ^^^^^^^^^^^^^^^^^ | help: remove the `safe` keyword from this definition | 16 - safe fn foobar(); 16 + fn foobar(); ``` An `extern "custom"` function cannot have any arguments or a return type: ``` error: invalid signature for `extern "custom"` function --> <source>:6:31 | 6 | unsafe extern "custom" fn foo(a: i32) -> i32 { | ^^^^^^ ^^^ | = note: functions with the "custom" ABI cannot have any parameters or return type help: remove the parameters and return type | 6 - unsafe extern "custom" fn foo(a: i32) -> i32 { 6 + unsafe extern "custom" fn foo() { | ``` ## Tests - [tests/ui/abi/custom.rs](https://github.com/rust-lang/rust/blob/main/tests/ui/abi/custom.rs) tests that the feature works as expected, e.g. that functions can be defined, symbols are defined, and extern blocks can be used. - [tests/ui/abi/bad-custom.rs](https://github.com/rust-lang/rust/blob/main/tests/ui/abi/bad-custom.rs) checks the restrictions: definitions must be unsafe and naked, attempting to call an `extern "custom"` function gives an error, etc. - ## History * rust-lang#140566 * rust-lang#140829 * rust-lang#140770 * rust-lang#159780 ## unresolved questions None
…, r=tgross35 Stabilize `extern "custom"` tracking issue: rust-lang#140829 reference PR: rust-lang/reference#2300 closes rust-lang#140829 ## Summary An `extern "custom" fn` is a function with a custom ABI that is unknown to rust. Often these are low-level functions that pass arguments in different registers than any standard calling convention. ```rust #[unsafe(naked)] pub unsafe extern "custom" fn __aeabi_uidivmod() { core::arch::naked_asm!( "push {{lr}}", "sub sp, sp, rust-lang#4", "mov r2, sp", "bl {trampoline}", "ldr r1, [sp]", "add sp, sp, rust-lang#4", "pop {{pc}}", trampoline = sym crate::arm::__udivmodsi4 ); } unsafe extern "custom" { fn __fentry__(); } ``` ## Design Because rust doesn't know what calling convention to use, an `extern "custom"` function can only be called via inline assembly or FFI. ``` error: functions with the "custom" ABI cannot be called --> <source>:5:5 | 5 | bar(); | ^^^^^ | note: an `extern "custom"` function can only be called using inline assembly ``` An `extern "custom"` function definition must be a naked function: ``` error: items with the "custom" ABI can only be declared externally or defined via naked functions --> <source>:10:1 | 10 | unsafe extern "custom" fn bar() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: convert this to an `#[unsafe(naked)]` function | 10 + #[unsafe(naked)] 11 | unsafe extern "custom" fn bar() { | ``` An `extern "custom"` function definition must be unsafe. The intent here is that a safety comment is written on how this function may be called. ``` error: functions with the "custom" ABI must be unsafe --> <source>:10:1 | 10 | extern "custom" fn bar() { | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: add the `unsafe` keyword to this definition | 10 | unsafe extern "custom" fn bar() { | ++++++ ``` In an `extern "custom"` block, functions cannot be marked as `safe`: ``` error: foreign functions with the "custom" ABI cannot be safe --> <source>:16:5 | 16 | safe fn foobar(); | ^^^^^^^^^^^^^^^^^ | help: remove the `safe` keyword from this definition | 16 - safe fn foobar(); 16 + fn foobar(); ``` An `extern "custom"` function cannot have any arguments or a return type: ``` error: invalid signature for `extern "custom"` function --> <source>:6:31 | 6 | unsafe extern "custom" fn foo(a: i32) -> i32 { | ^^^^^^ ^^^ | = note: functions with the "custom" ABI cannot have any parameters or return type help: remove the parameters and return type | 6 - unsafe extern "custom" fn foo(a: i32) -> i32 { 6 + unsafe extern "custom" fn foo() { | ``` ## Tests - [tests/ui/abi/custom.rs](https://github.com/rust-lang/rust/blob/main/tests/ui/abi/custom.rs) tests that the feature works as expected, e.g. that functions can be defined, symbols are defined, and extern blocks can be used. - [tests/ui/abi/bad-custom.rs](https://github.com/rust-lang/rust/blob/main/tests/ui/abi/bad-custom.rs) checks the restrictions: definitions must be unsafe and naked, attempting to call an `extern "custom"` function gives an error, etc. - ## History * rust-lang#140566 * rust-lang#140829 * rust-lang#140770 * rust-lang#159780 ## unresolved questions None
On lang, we decided that an `extern "custom"` function must syntactically have a return type of unit and that the `cold` attribute may not be applied to these functions. Let's revise the text for these new rules.
Rather than putting the rule that the `cold` attribute may not be applied to `extern "custom"` functions in the functions chapter, let's document it with the `cold` attribute. This is what we do in other cases where an attribute has restrictions on where it may be used.
Let's add an example to show that we do not allow applying the `cold` attribute to an `extern "custom"` function.
Let's add an example to show that we do not allow an `extern "custom"` function to have a type alias as its return type, even if that type alias is defined to be the unit type.
…, r=tgross35 Stabilize `extern "custom"` tracking issue: rust-lang#140829 reference PR: rust-lang/reference#2300 closes rust-lang#140829 ## Summary An `extern "custom" fn` is a function with a custom ABI that is unknown to rust. Often these are low-level functions that pass arguments in different registers than any standard calling convention. ```rust #[unsafe(naked)] pub unsafe extern "custom" fn __aeabi_uidivmod() { core::arch::naked_asm!( "push {{lr}}", "sub sp, sp, rust-lang#4", "mov r2, sp", "bl {trampoline}", "ldr r1, [sp]", "add sp, sp, rust-lang#4", "pop {{pc}}", trampoline = sym crate::arm::__udivmodsi4 ); } unsafe extern "custom" { fn __fentry__(); } ``` ## Design Because rust doesn't know what calling convention to use, an `extern "custom"` function can only be called via inline assembly or FFI. ``` error: functions with the "custom" ABI cannot be called --> <source>:5:5 | 5 | bar(); | ^^^^^ | note: an `extern "custom"` function can only be called using inline assembly ``` An `extern "custom"` function definition must be a naked function: ``` error: items with the "custom" ABI can only be declared externally or defined via naked functions --> <source>:10:1 | 10 | unsafe extern "custom" fn bar() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: convert this to an `#[unsafe(naked)]` function | 10 + #[unsafe(naked)] 11 | unsafe extern "custom" fn bar() { | ``` An `extern "custom"` function definition must be unsafe. The intent here is that a safety comment is written on how this function may be called. ``` error: functions with the "custom" ABI must be unsafe --> <source>:10:1 | 10 | extern "custom" fn bar() { | ^^^^^^^^^^^^^^^^^^^^^^^^ | help: add the `unsafe` keyword to this definition | 10 | unsafe extern "custom" fn bar() { | ++++++ ``` In an `extern "custom"` block, functions cannot be marked as `safe`: ``` error: foreign functions with the "custom" ABI cannot be safe --> <source>:16:5 | 16 | safe fn foobar(); | ^^^^^^^^^^^^^^^^^ | help: remove the `safe` keyword from this definition | 16 - safe fn foobar(); 16 + fn foobar(); ``` An `extern "custom"` function cannot have any arguments or a return type: ``` error: invalid signature for `extern "custom"` function --> <source>:6:31 | 6 | unsafe extern "custom" fn foo(a: i32) -> i32 { | ^^^^^^ ^^^ | = note: functions with the "custom" ABI cannot have any parameters or return type help: remove the parameters and return type | 6 - unsafe extern "custom" fn foo(a: i32) -> i32 { 6 + unsafe extern "custom" fn foo() { | ``` ## Tests - [tests/ui/abi/custom.rs](https://github.com/rust-lang/rust/blob/main/tests/ui/abi/custom.rs) tests that the feature works as expected, e.g. that functions can be defined, symbols are defined, and extern blocks can be used. - [tests/ui/abi/bad-custom.rs](https://github.com/rust-lang/rust/blob/main/tests/ui/abi/bad-custom.rs) checks the restrictions: definitions must be unsafe and naked, attempting to call an `extern "custom"` function gives an error, etc. - ## History * rust-lang#140566 * rust-lang#140829 * rust-lang#140770 * rust-lang#159780 ## unresolved questions None
stabilization PR: rust-lang/rust#158504
This is a tricky one that is an exception to some rules. I've tried to put the raw information in, but this'll probably require some refinement.