Add extern "custom"#3980
Conversation
|
Thanks @folkertdev for putting this together. @rfcbot fcp merge lang |
|
@traviscross has proposed to merge this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! cc @rust-lang/lang-advisors: FCP proposed for lang, please feel free to register concerns. |
|
@rfcbot reviewed |
|
🔔 This is now entering its final comment period, as per the review above. 🔔 |
|
@rfcbot reviewed |
|
Seeing a RFC entering a final comment period 1 hour after it was opened is extremely rare, and personally makes me worried. Even if it was discussed extensively in the past and all relevant team members are on-board, I believe we should let the community more time to discuss it. |
|
|
||
| ```rust | ||
| #[unsafe(naked)] | ||
| pub unsafe extern "custom" fn __aeabi_uidivmod() { |
There was a problem hiding this comment.
The motivation for why these must be unsafe is that it will remind people to write safety docs on how to call this correctly, but then you didn't write the docs. If there's going to be a multi-line example implementation there should be example docs too.
Separately, this particular function is one I recognize and it arguably doesn't really need to be a custom ABI, you can call it and return from it correctly using the C ABI if you define the return value to be a u64 value. But that's less important.
There was a problem hiding this comment.
Sure, I've added something but practically this function is not meant to be called (and a lack of safety comment means you can't satisfy the requirements).
There was a problem hiding this comment.
I suspect you know as well as I do that a lack of safety comments doesn't stop people from calling it anyway ;)
|
imo it's fine since that's what the final comment period is for, announcing and giving people time to look at something before it's accepted, when the team already thinks it's good enough. |
|
Right, this is the (final) ping for concerns to be raised. This was coordinated during the T-lang triage meeting. This feature is based on the following lang proposal, it is basically unchanged from that thread. |
| * https://github.com/rust-lang/rust/issues/140566 | ||
| * https://github.com/rust-lang/rust/issues/140829 | ||
| * https://github.com/rust-lang/rust/pull/140770 | ||
| * https://github.com/rust-lang/rust/pull/158504 |
There was a problem hiding this comment.
| * https://github.com/rust-lang/rust/issues/140566 | |
| * https://github.com/rust-lang/rust/issues/140829 | |
| * https://github.com/rust-lang/rust/pull/140770 | |
| * https://github.com/rust-lang/rust/pull/158504 | |
| * Proposal: https://github.com/rust-lang/rust/issues/140566 | |
| * Tracking issue: https://github.com/rust-lang/rust/issues/140829 | |
| * Implementation: https://github.com/rust-lang/rust/pull/140770 | |
| * Stabilization PR: https://github.com/rust-lang/rust/pull/158504 |
Saving a click
| https://github.com/rust-lang/rust/issues/140566 | ||
|
|
||
| The name has already been debated. The name `unknown` has been mentioned, but to write the implementation you really do need to know the ABI. It is custom in the sense that rustc does not know about it, but the author definitely does. | ||
|
|
There was a problem hiding this comment.
Would be good to address parameters since that was discussed at some point:
| Arguments and return types are forbidden because they are not consumed in any way. The compiler has no way of validating them against the function body, similar to other naked functions, but the functions can never be invoked directly so they serve no purpose when calling. The intent is that correct parameter passing and returning will be covered in documentation. |
|
I also felt a bit concerned by the sudden FCP, but the methodology here seems pretty canonical since it uses naked functions. The only potential concern is bikeshedding the name "custom" which could potentially be worded as "none" (since this effectively is no ABI) but that's a pretty weak point and not worth blocking IMHO. Plus, it could be changed even post-acceptance but pre-stabilisation. I see no reason to slow down on the FCP process. |
I would expect this time frame to be fairly short in this case. |
|
"none" is incorrect, as explained in the RFC, there is an ABI happening, it's just not an ABI the compiler knows how to use without assistance. |
Yes, this is another reason justifying the choice, although I do think that "none" that the compiler knows about is still appropriate: the compiler is not using any ABI for the function, even though yes, technically, ABI will always exist no matter what. Even just jumping to a label is still an ABI, after all. My point is that this is technically a weak point of contention, but not one I think is worth discussing here, since the name is more than adequately justified. |
| 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 { | ||
| | ^^^^^^ ^^^ |
There was a problem hiding this comment.
in the current implementation in 1.98.0-nightly (2026-07-01 4c9d2bfe4ad7a6566909) returning ! seems to be accepted (but returning an actual never_type i.e. (!) or std::convert::Infallible is rejected). please clarify
#![feature(abi_custom, never_type)]
use std::arch::naked_asm;
#[unsafe(naked)]
unsafe extern "custom" fn foo() -> ! { // no error.
naked_asm!("ud2")
}
#[unsafe(naked)]
unsafe extern "custom" fn bar() -> (!) { // error: invalid signature for `extern "custom"` function
naked_asm!("ud2")
}| 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() { | ||
| | ++++++ | ||
| ``` |
There was a problem hiding this comment.
Since all ways of actually calling an extern "custom" function are unsafe, it doesn't seem required that we also make the functions themselves unsafe. Yes, you must call it with the right ABI for the call to be safe, but that's true for all functions. Defining such a function just seems analogous to creating a raw pointer to me.
Summary
An
extern "custom" fnis 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.History
extern "unspecified"for naked functions with arbitrary ABI rust#140566abi_customrust#140829extern "custom"functions rust#140770extern "custom"rust#158504Important
Since RFCs involve many conversations at once that can be difficult to follow, please use review comment threads on the text changes instead of direct comments on the RFC.
If you don't have a particular section of the RFC to comment on, you can click on the "Comment on this file" button on the top-right corner of the diff, to the right of the "Viewed" checkbox. This will create a separate thread even if others have commented on the file too.
Rendered