Skip to content

Stabilize extern "custom" - #158504

Open
folkertdev wants to merge 1 commit into
rust-lang:mainfrom
folkertdev:stabilize-extern-custom
Open

Stabilize extern "custom"#158504
folkertdev wants to merge 1 commit into
rust-lang:mainfrom
folkertdev:stabilize-extern-custom

Conversation

@folkertdev

@folkertdev folkertdev commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

View all comments

tracking issue: #140829
reference PR: rust-lang/reference#2300
closes #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.

#[unsafe(naked)]
pub unsafe extern "custom" fn __aeabi_uidivmod() {
    core::arch::naked_asm!(
        "push {{lr}}",
        "sub sp, sp, #4",
        "mov r2, sp",
        "bl {trampoline}",
        "ldr r1, [sp]",
        "add sp, sp, #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 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 checks the restrictions: definitions must be unsafe and naked, attempting to call an extern "custom" function gives an error, etc.

History

unresolved questions

None

@folkertdev folkertdev added the F-abi_custom `#![feature(abi_custom)]` label Jun 27, 2026
@rustbot rustbot added A-compiler-builtins Area: compiler-builtins (https://github.com/rust-lang/compiler-builtins) S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jun 27, 2026
@folkertdev

Copy link
Copy Markdown
Contributor Author

r? tgross35

@rustbot

rustbot commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator

tgross35 is currently at their maximum review capacity.
They may take a while to respond.

@folkertdev
folkertdev marked this pull request as ready for review June 28, 2026 15:33
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 28, 2026
@rustbot

rustbot commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator

compiler-builtins is developed in its own repository. If possible, consider making this change to rust-lang/compiler-builtins instead.

cc @tgross35

@rustbot rustbot removed the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Jun 28, 2026
@folkertdev folkertdev added the I-lang-nominated Nominated for discussion during a lang team meeting. label Jun 28, 2026
@rust-bors

This comment has been minimized.

@bjorn3

bjorn3 commented Jun 28, 2026

Copy link
Copy Markdown
Member

Do we deny this on wasm? Wasm requires the function signature to be known when defining or importing it.

@folkertdev

Copy link
Copy Markdown
Contributor Author

In that case, does the whole concept of a naked function even make sense there? That is, can it do something that a normal function whose body is an asm! block cannot do?

Practically inline assembly is unstable (and extremely incomplete) for wasm, so I'm not sure if/how it'll eventually fit in.

But we can deny extern "custom" on wasm if that seems best right now.

@bjorn3

bjorn3 commented Jun 28, 2026

Copy link
Copy Markdown
Member

Naked asm can avoid touching the stack, maybe there are cases that is useful? Naked asm doesn't help for defining functions that use ref types or GC types as there isn't a way to express those using rust syntax, so those still need global_asm!().

@823984418

Copy link
Copy Markdown
Contributor

Allowing only assembly calls seems quite restrictive in terms of cross platform capabilities, as a special case, an extern "custom" fn function that internally calls only another extern "custom" fn function should be allowed and may be treated as syntactic sugar for a direct jump.

@asquared31415

Copy link
Copy Markdown
Contributor

This is a restriction on naked functions already, they must not contain Rust code.

@folkertdev

Copy link
Copy Markdown
Contributor Author

Just making this explicit: #158621 removes support for wasm and spirv targets. Neither have stable assembly, so practically this doesn't change anything, but the whole concept of extern "custom" doesn't really make sense there.

@traviscross traviscross added needs-reference-pr This language change needs an approved Reference PR to proceed. T-lang Relevant to the language team needs-fcp This change is insta-stable, or significant enough to need a team FCP to proceed. P-lang-drag-1 Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang labels Jul 1, 2026
@traviscross

Copy link
Copy Markdown
Contributor

Makes sense to me. Thanks @folkertdev for your work on this.

@rfcbot fcp merge lang

cc @Amanieu

@rust-rfcbot

rust-rfcbot commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

@traviscross has proposed to merge this. The next step is review by the rest of the tagged team members:

Concerns:

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.
See this document for info about what commands tagged team members can give me.

@rust-rfcbot rust-rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Jul 1, 2026
@rust-rfcbot rust-rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. to-announce Announce this issue on triage meeting and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels Jul 11, 2026
@rust-rfcbot

Copy link
Copy Markdown
Collaborator

The final comment period, with a disposition to merge, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

@rustbot

This comment has been minimized.

@folkertdev
folkertdev force-pushed the stabilize-extern-custom branch from e50eeac to 5e6a3e9 Compare July 29, 2026 12:53
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@folkertdev
folkertdev force-pushed the stabilize-extern-custom branch from 5e6a3e9 to 8436fc4 Compare July 29, 2026 13:35
@tgross35

tgross35 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Looks like a pretty trivial stabilization but this needs the RFC rust-lang/rfcs#3980.

@rustbot blocked

@SnoozeThis rust-lang/rfcs#3980 -> remove label S-blocked, add label S-waiting-on-review

@rustbot rustbot added S-blocked Status: Blocked on something else such as an RFC or other implementation work. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 4, 2026
@folkertdev folkertdev added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. has-reference-pr This language change has an approved Reference PR. and removed S-blocked Status: Blocked on something else such as an RFC or other implementation work. needs-reference-pr This language change needs an approved Reference PR to proceed. labels Aug 5, 2026
@folkertdev

Copy link
Copy Markdown
Contributor Author

The RFC has been merged and the reference PR has been approved.

@rust-bors

This comment has been minimized.

@folkertdev
folkertdev force-pushed the stabilize-extern-custom branch from 8436fc4 to 364b5d7 Compare August 8, 2026 11:54
@rustbot

rustbot commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job x86_64-gnu-tools failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
100  177M  100  177M    0     0   216M      0 --:--:-- --:--:-- --:--:--  216M
#12 DONE 1.1s

#13 [ 7/10] RUN unzip -d /usr/bin/ chrome-linux64.zip && rm chrome-linux64.zip
#13 0.047 Archive:  chrome-linux64.zip
#13 0.048   inflating: /usr/bin/chrome-linux64/ABOUT  
#13 0.048   inflating: /usr/bin/chrome-linux64/MEIPreload/manifest.json  
#13 0.048   inflating: /usr/bin/chrome-linux64/MEIPreload/preloaded_data.pb  
#13 0.048   inflating: /usr/bin/chrome-linux64/PrivacySandboxAttestationsPreloaded/manifest.json  
#13 0.048   inflating: /usr/bin/chrome-linux64/PrivacySandboxAttestationsPreloaded/privacy-sandbox-attestations.dat  
#13 0.048   inflating: /usr/bin/chrome-linux64/WidevineCdm/LICENSE  
#13 0.049   inflating: /usr/bin/chrome-linux64/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so  
#13 0.177   inflating: /usr/bin/chrome-linux64/WidevineCdm/manifest.json  
#13 0.177   inflating: /usr/bin/chrome-linux64/chrome  
#13 2.410   inflating: /usr/bin/chrome-linux64/chrome-wrapper  
#13 2.410   inflating: /usr/bin/chrome-linux64/chrome_100_percent.pak  
#13 2.416   inflating: /usr/bin/chrome-linux64/chrome_200_percent.pak  
#13 2.424   inflating: /usr/bin/chrome-linux64/chrome_crashpad_handler  
#13 2.441   inflating: /usr/bin/chrome-linux64/chrome_sandbox  
#13 2.442   inflating: /usr/bin/chrome-linux64/deb.deps  
#13 2.442   inflating: /usr/bin/chrome-linux64/icudtl.dat  
#13 2.522   inflating: /usr/bin/chrome-linux64/libEGL.so  
#13 2.525   inflating: /usr/bin/chrome-linux64/libGLESv2.so  
#13 2.575   inflating: /usr/bin/chrome-linux64/libvk_swiftshader.so  
#13 2.612   inflating: /usr/bin/chrome-linux64/libvulkan.so.1  
#13 2.617   inflating: /usr/bin/chrome-linux64/locales/af.pak  
#13 2.622   inflating: /usr/bin/chrome-linux64/locales/af_FEMININE.pak  
#13 2.622   inflating: /usr/bin/chrome-linux64/locales/af_MASCULINE.pak  
#13 2.622   inflating: /usr/bin/chrome-linux64/locales/af_NEUTER.pak  
#13 2.622   inflating: /usr/bin/chrome-linux64/locales/am.pak  
#13 2.630   inflating: /usr/bin/chrome-linux64/locales/am_FEMININE.pak  
#13 2.630   inflating: /usr/bin/chrome-linux64/locales/am_MASCULINE.pak  
#13 2.630   inflating: /usr/bin/chrome-linux64/locales/am_NEUTER.pak  
#13 2.630   inflating: /usr/bin/chrome-linux64/locales/ar.pak  
#13 2.638   inflating: /usr/bin/chrome-linux64/locales/ar_FEMININE.pak  
#13 2.638   inflating: /usr/bin/chrome-linux64/locales/ar_MASCULINE.pak  
#13 2.638   inflating: /usr/bin/chrome-linux64/locales/ar_NEUTER.pak  
#13 2.638   inflating: /usr/bin/chrome-linux64/locales/bg.pak  
#13 2.646   inflating: /usr/bin/chrome-linux64/locales/bg_FEMININE.pak  
#13 2.646   inflating: /usr/bin/chrome-linux64/locales/bg_MASCULINE.pak  
#13 2.646   inflating: /usr/bin/chrome-linux64/locales/bg_NEUTER.pak  
#13 2.646   inflating: /usr/bin/chrome-linux64/locales/bn.pak  
#13 2.656   inflating: /usr/bin/chrome-linux64/locales/bn_FEMININE.pak  
#13 2.656   inflating: /usr/bin/chrome-linux64/locales/bn_MASCULINE.pak  
#13 2.656   inflating: /usr/bin/chrome-linux64/locales/bn_NEUTER.pak  
#13 2.656   inflating: /usr/bin/chrome-linux64/locales/ca.pak  
#13 2.661   inflating: /usr/bin/chrome-linux64/locales/ca_FEMININE.pak  
#13 2.661   inflating: /usr/bin/chrome-linux64/locales/ca_MASCULINE.pak  
#13 2.661   inflating: /usr/bin/chrome-linux64/locales/ca_NEUTER.pak  
#13 2.661   inflating: /usr/bin/chrome-linux64/locales/cs.pak  
#13 2.667   inflating: /usr/bin/chrome-linux64/locales/cs_FEMININE.pak  
#13 2.667   inflating: /usr/bin/chrome-linux64/locales/cs_MASCULINE.pak  
#13 2.667   inflating: /usr/bin/chrome-linux64/locales/cs_NEUTER.pak  
#13 2.667   inflating: /usr/bin/chrome-linux64/locales/da.pak  
#13 2.672   inflating: /usr/bin/chrome-linux64/locales/da_FEMININE.pak  
#13 2.672   inflating: /usr/bin/chrome-linux64/locales/da_MASCULINE.pak  
#13 2.672   inflating: /usr/bin/chrome-linux64/locales/da_NEUTER.pak  
#13 2.672   inflating: /usr/bin/chrome-linux64/locales/de.pak  
#13 2.678   inflating: /usr/bin/chrome-linux64/locales/de_FEMININE.pak  
#13 2.678   inflating: /usr/bin/chrome-linux64/locales/de_MASCULINE.pak  
#13 2.678   inflating: /usr/bin/chrome-linux64/locales/de_NEUTER.pak  
#13 2.678   inflating: /usr/bin/chrome-linux64/locales/el.pak  
#13 2.686   inflating: /usr/bin/chrome-linux64/locales/el_FEMININE.pak  
#13 2.687   inflating: /usr/bin/chrome-linux64/locales/el_MASCULINE.pak  
#13 2.687   inflating: /usr/bin/chrome-linux64/locales/el_NEUTER.pak  
#13 2.687   inflating: /usr/bin/chrome-linux64/locales/en-GB.pak  
#13 2.691   inflating: /usr/bin/chrome-linux64/locales/en-GB_FEMININE.pak  
#13 2.692   inflating: /usr/bin/chrome-linux64/locales/en-GB_MASCULINE.pak  
#13 2.692   inflating: /usr/bin/chrome-linux64/locales/en-GB_NEUTER.pak  
#13 2.692   inflating: /usr/bin/chrome-linux64/locales/en-US.pak  
#13 2.696   inflating: /usr/bin/chrome-linux64/locales/en-US_FEMININE.pak  
#13 2.696   inflating: /usr/bin/chrome-linux64/locales/en-US_MASCULINE.pak  
#13 2.696   inflating: /usr/bin/chrome-linux64/locales/en-US_NEUTER.pak  
#13 2.697   inflating: /usr/bin/chrome-linux64/locales/es-419.pak  
#13 2.702   inflating: /usr/bin/chrome-linux64/locales/es-419_FEMININE.pak  
#13 2.702   inflating: /usr/bin/chrome-linux64/locales/es-419_MASCULINE.pak  
#13 2.702   inflating: /usr/bin/chrome-linux64/locales/es-419_NEUTER.pak  
#13 2.702   inflating: /usr/bin/chrome-linux64/locales/es.pak  
#13 2.708   inflating: /usr/bin/chrome-linux64/locales/es_FEMININE.pak  
#13 2.708   inflating: /usr/bin/chrome-linux64/locales/es_MASCULINE.pak  
#13 2.708   inflating: /usr/bin/chrome-linux64/locales/es_NEUTER.pak  
#13 2.708   inflating: /usr/bin/chrome-linux64/locales/et.pak  
#13 2.713   inflating: /usr/bin/chrome-linux64/locales/et_FEMININE.pak  
#13 2.713   inflating: /usr/bin/chrome-linux64/locales/et_MASCULINE.pak  
#13 2.714   inflating: /usr/bin/chrome-linux64/locales/et_NEUTER.pak  
#13 2.714   inflating: /usr/bin/chrome-linux64/locales/fa.pak  
#13 2.721   inflating: /usr/bin/chrome-linux64/locales/fa_FEMININE.pak  
#13 2.721   inflating: /usr/bin/chrome-linux64/locales/fa_MASCULINE.pak  
#13 2.721   inflating: /usr/bin/chrome-linux64/locales/fa_NEUTER.pak  
#13 2.721   inflating: /usr/bin/chrome-linux64/locales/fi.pak  
#13 2.726   inflating: /usr/bin/chrome-linux64/locales/fi_FEMININE.pak  
#13 2.726   inflating: /usr/bin/chrome-linux64/locales/fi_MASCULINE.pak  
#13 2.726   inflating: /usr/bin/chrome-linux64/locales/fi_NEUTER.pak  
#13 2.727   inflating: /usr/bin/chrome-linux64/locales/fil.pak  
#13 2.732   inflating: /usr/bin/chrome-linux64/locales/fil_FEMININE.pak  
#13 2.732   inflating: /usr/bin/chrome-linux64/locales/fil_MASCULINE.pak  
#13 2.732   inflating: /usr/bin/chrome-linux64/locales/fil_NEUTER.pak  
#13 2.732   inflating: /usr/bin/chrome-linux64/locales/fr.pak  
#13 2.738   inflating: /usr/bin/chrome-linux64/locales/fr_FEMININE.pak  
#13 2.738   inflating: /usr/bin/chrome-linux64/locales/fr_MASCULINE.pak  
#13 2.738   inflating: /usr/bin/chrome-linux64/locales/fr_NEUTER.pak  
#13 2.738   inflating: /usr/bin/chrome-linux64/locales/gu.pak  
#13 2.748   inflating: /usr/bin/chrome-linux64/locales/gu_FEMININE.pak  
#13 2.748   inflating: /usr/bin/chrome-linux64/locales/gu_MASCULINE.pak  
#13 2.748   inflating: /usr/bin/chrome-linux64/locales/gu_NEUTER.pak  
#13 2.748   inflating: /usr/bin/chrome-linux64/locales/he.pak  
#13 2.755   inflating: /usr/bin/chrome-linux64/locales/he_FEMININE.pak  
#13 2.756   inflating: /usr/bin/chrome-linux64/locales/he_MASCULINE.pak  
#13 2.756   inflating: /usr/bin/chrome-linux64/locales/he_NEUTER.pak  
#13 2.756   inflating: /usr/bin/chrome-linux64/locales/hi.pak  
#13 2.766   inflating: /usr/bin/chrome-linux64/locales/hi_FEMININE.pak  
#13 2.766   inflating: /usr/bin/chrome-linux64/locales/hi_MASCULINE.pak  
#13 2.766   inflating: /usr/bin/chrome-linux64/locales/hi_NEUTER.pak  
#13 2.766   inflating: /usr/bin/chrome-linux64/locales/hr.pak  
#13 2.771   inflating: /usr/bin/chrome-linux64/locales/hr_FEMININE.pak  
#13 2.771   inflating: /usr/bin/chrome-linux64/locales/hr_MASCULINE.pak  
#13 2.772   inflating: /usr/bin/chrome-linux64/locales/hr_NEUTER.pak  
#13 2.772   inflating: /usr/bin/chrome-linux64/locales/hu.pak  
#13 2.777   inflating: /usr/bin/chrome-linux64/locales/hu_FEMININE.pak  
#13 2.777   inflating: /usr/bin/chrome-linux64/locales/hu_MASCULINE.pak  
#13 2.777   inflating: /usr/bin/chrome-linux64/locales/hu_NEUTER.pak  
#13 2.778   inflating: /usr/bin/chrome-linux64/locales/id.pak  
#13 2.783   inflating: /usr/bin/chrome-linux64/locales/id_FEMININE.pak  
#13 2.783   inflating: /usr/bin/chrome-linux64/locales/id_MASCULINE.pak  
#13 2.783   inflating: /usr/bin/chrome-linux64/locales/id_NEUTER.pak  
#13 2.783   inflating: /usr/bin/chrome-linux64/locales/it.pak  
#13 2.788   inflating: /usr/bin/chrome-linux64/locales/it_FEMININE.pak  
#13 2.788   inflating: /usr/bin/chrome-linux64/locales/it_MASCULINE.pak  
#13 2.788   inflating: /usr/bin/chrome-linux64/locales/it_NEUTER.pak  
#13 2.789   inflating: /usr/bin/chrome-linux64/locales/ja.pak  
#13 2.795   inflating: /usr/bin/chrome-linux64/locales/ja_FEMININE.pak  
#13 2.795   inflating: /usr/bin/chrome-linux64/locales/ja_MASCULINE.pak  
#13 2.795   inflating: /usr/bin/chrome-linux64/locales/ja_NEUTER.pak  
#13 2.795   inflating: /usr/bin/chrome-linux64/locales/kn.pak  
#13 2.806   inflating: /usr/bin/chrome-linux64/locales/kn_FEMININE.pak  
#13 2.806   inflating: /usr/bin/chrome-linux64/locales/kn_MASCULINE.pak  
#13 2.806   inflating: /usr/bin/chrome-linux64/locales/kn_NEUTER.pak  
#13 2.806   inflating: /usr/bin/chrome-linux64/locales/ko.pak  
#13 2.812   inflating: /usr/bin/chrome-linux64/locales/ko_FEMININE.pak  
#13 2.812   inflating: /usr/bin/chrome-linux64/locales/ko_MASCULINE.pak  
#13 2.812   inflating: /usr/bin/chrome-linux64/locales/ko_NEUTER.pak  
#13 2.812   inflating: /usr/bin/chrome-linux64/locales/lt.pak  
#13 2.818   inflating: /usr/bin/chrome-linux64/locales/lt_FEMININE.pak  
#13 2.818   inflating: /usr/bin/chrome-linux64/locales/lt_MASCULINE.pak  
#13 2.818   inflating: /usr/bin/chrome-linux64/locales/lt_NEUTER.pak  
#13 2.818   inflating: /usr/bin/chrome-linux64/locales/lv.pak  
#13 2.824   inflating: /usr/bin/chrome-linux64/locales/lv_FEMININE.pak  
#13 2.824   inflating: /usr/bin/chrome-linux64/locales/lv_MASCULINE.pak  
#13 2.824   inflating: /usr/bin/chrome-linux64/locales/lv_NEUTER.pak  
#13 2.824   inflating: /usr/bin/chrome-linux64/locales/ml.pak  
#13 2.835   inflating: /usr/bin/chrome-linux64/locales/ml_FEMININE.pak  
#13 2.835   inflating: /usr/bin/chrome-linux64/locales/ml_MASCULINE.pak  
#13 2.835   inflating: /usr/bin/chrome-linux64/locales/ml_NEUTER.pak  
#13 2.835   inflating: /usr/bin/chrome-linux64/locales/mr.pak  
#13 2.845   inflating: /usr/bin/chrome-linux64/locales/mr_FEMININE.pak  
#13 2.845   inflating: /usr/bin/chrome-linux64/locales/mr_MASCULINE.pak  
#13 2.845   inflating: /usr/bin/chrome-linux64/locales/mr_NEUTER.pak  
#13 2.845   inflating: /usr/bin/chrome-linux64/locales/ms.pak  
#13 2.850   inflating: /usr/bin/chrome-linux64/locales/ms_FEMININE.pak  
#13 2.850   inflating: /usr/bin/chrome-linux64/locales/ms_MASCULINE.pak  
#13 2.850   inflating: /usr/bin/chrome-linux64/locales/ms_NEUTER.pak  
#13 2.851   inflating: /usr/bin/chrome-linux64/locales/nb.pak  
#13 2.855   inflating: /usr/bin/chrome-linux64/locales/nb_FEMININE.pak  
#13 2.855   inflating: /usr/bin/chrome-linux64/locales/nb_MASCULINE.pak  
#13 2.856   inflating: /usr/bin/chrome-linux64/locales/nb_NEUTER.pak  
#13 2.856   inflating: /usr/bin/chrome-linux64/locales/nl.pak  
#13 2.860   inflating: /usr/bin/chrome-linux64/locales/nl_FEMININE.pak  
#13 2.861   inflating: /usr/bin/chrome-linux64/locales/nl_MASCULINE.pak  
#13 2.861   inflating: /usr/bin/chrome-linux64/locales/nl_NEUTER.pak  
#13 2.861   inflating: /usr/bin/chrome-linux64/locales/pl.pak  
#13 2.866   inflating: /usr/bin/chrome-linux64/locales/pl_FEMININE.pak  
#13 2.866   inflating: /usr/bin/chrome-linux64/locales/pl_MASCULINE.pak  
#13 2.867   inflating: /usr/bin/chrome-linux64/locales/pl_NEUTER.pak  
#13 2.867   inflating: /usr/bin/chrome-linux64/locales/pt-BR.pak  
#13 2.872   inflating: /usr/bin/chrome-linux64/locales/pt-BR_FEMININE.pak  
#13 2.872   inflating: /usr/bin/chrome-linux64/locales/pt-BR_MASCULINE.pak  
#13 2.872   inflating: /usr/bin/chrome-linux64/locales/pt-BR_NEUTER.pak  
#13 2.872   inflating: /usr/bin/chrome-linux64/locales/pt-PT.pak  
#13 2.877   inflating: /usr/bin/chrome-linux64/locales/pt-PT_FEMININE.pak  
#13 2.878   inflating: /usr/bin/chrome-linux64/locales/pt-PT_MASCULINE.pak  
#13 2.878   inflating: /usr/bin/chrome-linux64/locales/pt-PT_NEUTER.pak  
#13 2.878   inflating: /usr/bin/chrome-linux64/locales/ro.pak  
#13 2.883   inflating: /usr/bin/chrome-linux64/locales/ro_FEMININE.pak  
#13 2.883   inflating: /usr/bin/chrome-linux64/locales/ro_MASCULINE.pak  
#13 2.884   inflating: /usr/bin/chrome-linux64/locales/ro_NEUTER.pak  
#13 2.884   inflating: /usr/bin/chrome-linux64/locales/ru.pak  
#13 2.891   inflating: /usr/bin/chrome-linux64/locales/ru_FEMININE.pak  
#13 2.891   inflating: /usr/bin/chrome-linux64/locales/ru_MASCULINE.pak  
#13 2.892   inflating: /usr/bin/chrome-linux64/locales/ru_NEUTER.pak  
#13 2.892   inflating: /usr/bin/chrome-linux64/locales/sk.pak  
#13 2.897   inflating: /usr/bin/chrome-linux64/locales/sk_FEMININE.pak  
#13 2.897   inflating: /usr/bin/chrome-linux64/locales/sk_MASCULINE.pak  
#13 2.898   inflating: /usr/bin/chrome-linux64/locales/sk_NEUTER.pak  
#13 2.898   inflating: /usr/bin/chrome-linux64/locales/sl.pak  
#13 2.903   inflating: /usr/bin/chrome-linux64/locales/sl_FEMININE.pak  
#13 2.904   inflating: /usr/bin/chrome-linux64/locales/sl_MASCULINE.pak  
#13 2.904   inflating: /usr/bin/chrome-linux64/locales/sl_NEUTER.pak  
#13 2.904   inflating: /usr/bin/chrome-linux64/locales/sr.pak  
#13 2.911   inflating: /usr/bin/chrome-linux64/locales/sr_FEMININE.pak  
#13 2.911   inflating: /usr/bin/chrome-linux64/locales/sr_MASCULINE.pak  
#13 2.911   inflating: /usr/bin/chrome-linux64/locales/sr_NEUTER.pak  
#13 2.912   inflating: /usr/bin/chrome-linux64/locales/sv.pak  
#13 2.916   inflating: /usr/bin/chrome-linux64/locales/sv_FEMININE.pak  
#13 2.917   inflating: /usr/bin/chrome-linux64/locales/sv_MASCULINE.pak  
#13 2.917   inflating: /usr/bin/chrome-linux64/locales/sv_NEUTER.pak  
#13 2.917   inflating: /usr/bin/chrome-linux64/locales/sw.pak  
#13 2.923   inflating: /usr/bin/chrome-linux64/locales/sw_FEMININE.pak  
#13 2.923   inflating: /usr/bin/chrome-linux64/locales/sw_MASCULINE.pak  
#13 2.923   inflating: /usr/bin/chrome-linux64/locales/sw_NEUTER.pak  
#13 2.923   inflating: /usr/bin/chrome-linux64/locales/ta.pak  
#13 2.934   inflating: /usr/bin/chrome-linux64/locales/ta_FEMININE.pak  
#13 2.934   inflating: /usr/bin/chrome-linux64/locales/ta_MASCULINE.pak  
#13 2.934   inflating: /usr/bin/chrome-linux64/locales/ta_NEUTER.pak  
#13 2.934   inflating: /usr/bin/chrome-linux64/locales/te.pak  
#13 2.944   inflating: /usr/bin/chrome-linux64/locales/te_FEMININE.pak  
#13 2.945   inflating: /usr/bin/chrome-linux64/locales/te_MASCULINE.pak  
#13 2.945   inflating: /usr/bin/chrome-linux64/locales/te_NEUTER.pak  
#13 2.945   inflating: /usr/bin/chrome-linux64/locales/th.pak  
#13 2.953   inflating: /usr/bin/chrome-linux64/locales/th_FEMININE.pak  
#13 2.954   inflating: /usr/bin/chrome-linux64/locales/th_MASCULINE.pak  
#13 2.954   inflating: /usr/bin/chrome-linux64/locales/th_NEUTER.pak  
#13 2.954   inflating: /usr/bin/chrome-linux64/locales/tr.pak  
#13 2.959   inflating: /usr/bin/chrome-linux64/locales/tr_FEMININE.pak  
#13 2.960   inflating: /usr/bin/chrome-linux64/locales/tr_MASCULINE.pak  
#13 2.960   inflating: /usr/bin/chrome-linux64/locales/tr_NEUTER.pak  
#13 2.960   inflating: /usr/bin/chrome-linux64/locales/uk.pak  
#13 2.968   inflating: /usr/bin/chrome-linux64/locales/uk_FEMININE.pak  
#13 2.968   inflating: /usr/bin/chrome-linux64/locales/uk_MASCULINE.pak  
#13 2.968   inflating: /usr/bin/chrome-linux64/locales/uk_NEUTER.pak  
#13 2.968   inflating: /usr/bin/chrome-linux64/locales/ur.pak  
#13 2.975   inflating: /usr/bin/chrome-linux64/locales/ur_FEMININE.pak  
#13 2.975   inflating: /usr/bin/chrome-linux64/locales/ur_MASCULINE.pak  
#13 2.976   inflating: /usr/bin/chrome-linux64/locales/ur_NEUTER.pak  
#13 2.976   inflating: /usr/bin/chrome-linux64/locales/vi.pak  
#13 2.981   inflating: /usr/bin/chrome-linux64/locales/vi_FEMININE.pak  
#13 2.981   inflating: /usr/bin/chrome-linux64/locales/vi_MASCULINE.pak  
#13 2.982   inflating: /usr/bin/chrome-linux64/locales/vi_NEUTER.pak  
#13 2.982   inflating: /usr/bin/chrome-linux64/locales/zh-CN.pak  
#13 2.986   inflating: /usr/bin/chrome-linux64/locales/zh-CN_FEMININE.pak  
#13 2.986   inflating: /usr/bin/chrome-linux64/locales/zh-CN_MASCULINE.pak  
#13 2.987   inflating: /usr/bin/chrome-linux64/locales/zh-CN_NEUTER.pak  
#13 2.987   inflating: /usr/bin/chrome-linux64/locales/zh-TW.pak  
#13 2.991   inflating: /usr/bin/chrome-linux64/locales/zh-TW_FEMININE.pak  
#13 2.991   inflating: /usr/bin/chrome-linux64/locales/zh-TW_MASCULINE.pak  
#13 2.991   inflating: /usr/bin/chrome-linux64/locales/zh-TW_NEUTER.pak  
#13 2.991  extracting: /usr/bin/chrome-linux64/product_logo_48.png  
#13 2.992   inflating: /usr/bin/chrome-linux64/resources.pak  
#13 3.082   inflating: /usr/bin/chrome-linux64/rpm.deps  
#13 3.082   inflating: /usr/bin/chrome-linux64/v8_context_snapshot.bin  
#13 3.088   inflating: /usr/bin/chrome-linux64/vk_swiftshader_icd.json  
#13 3.088    creating: /usr/bin/chrome-linux64/resources/
#13 3.088    creating: /usr/bin/chrome-linux64/resources/inspector_overlay/
#13 3.088   inflating: /usr/bin/chrome-linux64/resources/inspector_overlay/inspector_overlay_resources.grd  
#13 3.089   inflating: /usr/bin/chrome-linux64/resources/inspector_overlay/main.js  
#13 3.089    creating: /usr/bin/chrome-linux64/resources/accessibility/
#13 3.089    creating: /usr/bin/chrome-linux64/resources/accessibility/reading_mode_gdocs_helper/
#13 3.089   inflating: /usr/bin/chrome-linux64/resources/accessibility/reading_mode_gdocs_helper/content.js  
#13 3.089   inflating: /usr/bin/chrome-linux64/resources/accessibility/reading_mode_gdocs_helper/gdocs_script.js  
#13 3.089   inflating: /usr/bin/chrome-linux64/resources/accessibility/reading_mode_gdocs_helper_manifest.json  
#13 3.090    creating: /usr/bin/chrome-linux64/hyphen-data/
#13 3.090   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-tk.hyb  
#13 3.090   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-de-1901.hyb  
#13 3.091   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-de-1996.hyb  
#13 3.093   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-mul-ethi.hyb  
#13 3.093   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-es.hyb  
#13 3.093   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-hi.hyb  
#13 3.094   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-cu.hyb  
#13 3.094   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-as.hyb  
#13 3.094   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-ta.hyb  
#13 3.095   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-pa.hyb  
#13 3.095   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-el.hyb  
#13 3.095   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-te.hyb  
#13 3.095   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-und-ethi.hyb  
#13 3.095   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-de-ch-1901.hyb  
#13 3.097   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-bg.hyb  
#13 3.097   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-gu.hyb  
#13 3.097   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-et.hyb  
#13 3.097   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-cs.hyb  
#13 3.098   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-nl.hyb  
#13 3.099   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-ru.hyb  
#13 3.100   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-hy.hyb  
#13 3.100   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-uk.hyb  
#13 3.100   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-eu.hyb  
#13 3.100   inflating: /usr/bin/chrome-linux64/hyphen-data/manifest.json  
#13 3.101   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-ga.hyb  
#13 3.101   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-sk.hyb  
#13 3.102   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-mr.hyb  
#13 3.102   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-bn.hyb  
#13 3.102   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-nb.hyb  
#13 3.104   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-en-gb.hyb  
#13 3.105   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-or.hyb  
#13 3.105   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-cy.hyb  
#13 3.105   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-hr.hyb  
#13 3.105   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-fr.hyb  
#13 3.106   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-kn.hyb  
#13 3.106   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-mn-cyrl.hyb  
#13 3.106   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-lt.hyb  
#13 3.106   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-en-us.hyb  
#13 3.107   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-ml.hyb  
#13 3.107   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-pt.hyb  
#13 3.108   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-be.hyb  
#13 3.108   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-sl.hyb  
#13 3.108   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-lv.hyb  
#13 3.108   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-sv.hyb  
#13 3.109   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-hu.hyb  
#13 3.113   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-af.hyb  
#13 3.114   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-sq.hyb  
#13 3.114   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-ka.hyb  
#13 3.114   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-it.hyb  
#13 3.114   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-gl.hyb  
#13 3.115   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-da.hyb  
#13 3.115   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-nn.hyb  
#13 3.116   inflating: /usr/bin/chrome-linux64/hyphen-data/hyph-la.hyb  
#13 DONE 3.8s

#14 [ 8/10] COPY scripts/nodejs.sh /scripts/
#14 DONE 0.0s

---
..............F..............................      (145/145)

======== tests/rustdoc-gui/sidebar.goml ========

[ERROR] sidebar output:
Runtime.callFunctionOn timed out. Increase the 'protocolTimeout' setting in launch/connect calls for a higher timeout if needed.
stack: ProtocolError: Runtime.callFunctionOn timed out. Increase the 'protocolTimeout' setting in launch/connect calls for a higher timeout if needed.
    at <instance_members_initializer> (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/common/CallbackRegistry.js:102:14)
    at new Callback (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/common/CallbackRegistry.js:106:16)
    at CallbackRegistry.create (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/common/CallbackRegistry.js:25:26)
    at Connection._rawSend (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/cdp/Connection.js:118:26)
    at CdpCDPSession.send (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/cdp/CdpSession.js:72:14)
    at #evaluate (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/cdp/ExecutionContext.js:360:50)
    at ExecutionContext.evaluate (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/cdp/ExecutionContext.js:274:36)
    at IsolatedWorld.evaluate (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/cdp/IsolatedWorld.js:102:30)
    at CdpFrame.evaluate (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/api/Frame.js:359:43)
    at CdpFrame.<anonymous> (file:///checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-gui/node_modules/puppeteer-core/lib/puppeteer/util/decorators.js:101:27)



<= doc-ui tests done: 144 succeeded, 1 failed, 0 filtered out

@tgross35

tgross35 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

It looks like we currently accept generics, this currently builds:

#![feature(abi_custom)]

use std::arch::naked_asm;

#[unsafe(naked)]
unsafe extern "custom" fn increment<T>() {
    naked_asm!(
        "add rax, 1",
        "ret",
    )
}

https://rust.godbolt.org/z/cv77sYnqE:

I think we should reject this for the same reason we reject arguments. @rust-lang/lang to confirm

@tgross35

tgross35 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Changing my mind here, I can see valid usecases for something like:

#![feature(abi_custom)]

use std::arch::asm;
use std::arch::naked_asm;

/// # Safety
/// Something about ABI and overflow...
#[unsafe(naked)]
unsafe extern "custom" fn increment<T, const N: usize>() {
    naked_asm!(
        "add rax, {x}",
        "add rax, {N}",
        "ret",
        x = const size_of::<T>(),
        N = const N,
    )
}

fn main() {
    let mut x: u64 = 0;
    unsafe {
        asm!(
            "call {}",
            sym increment::<u32, 10>,
            inout("rax") x,
        );
    }
    assert_eq!(x, 4);
}

https://rust.godbolt.org/z/odj6Tcsbd

But lang still needs to weigh in since this didn't come up in the RFC or reference PR as far as I can tell.

@rustbot label +I-lang-nominated

Edit: I see we actually test for this already, at least with const generics

unsafe extern "C" fn const_generic<const N: u64>() {
naked_asm!(
"mov rax, {}",
"ret",
const N,
);
}

@rustbot rustbot added the I-lang-nominated Nominated for discussion during a lang team meeting. label Aug 9, 2026
@tgross35

tgross35 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Second question: should we reject #[cold]? I don't think there's anything we can do with it, assuming it can't bubble up through inline asm somehow.

Currently accepted https://rust.godbolt.org/z/rh5aMbcGK

@tgross35 tgross35 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small test suggestions, otherwise stabilization looks fine to me against rust-lang/reference#2300 at 66b3bc5b8688 with the possible exception of generics and #[cold]. I guess generics are probably fine, would just like somebody from lang to confirm since I haven't seen it discussed anywhere.

View changes since this review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the docs say returning the unit type is okay, it would be good to add a -> () and -> SomeAlias to make sure that actually works and it's not an AST gate (seems like it is fine)

@folkertdev folkertdev Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it is an AST gate, the alias fails https://godbolt.org/z/G35o3EGW6.

Doing it truly based on the type is all kinds of nasty in the case of generics

trait MyTrait {
    type T;

    #[unsafe(naked)]
    unsafe extern "custom" foo() -> Self::T { // error?
        core::arch::asm!("");
    }
}

We also lose span information about the function header I believe, so it would be harder go generate a good error message if we delay.

Comment thread tests/ui/abi/custom.rs
"ret",
const N,
);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't hurt to have something similar for non-const generics

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added in #160805

@traviscross

Copy link
Copy Markdown
Contributor

Thanks @tgross35 for flagging those. For my own part, I agree that generics should be accepted and that cold likely should not be.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-compiler-builtins Area: compiler-builtins (https://github.com/rust-lang/compiler-builtins) disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. F-abi_custom `#![feature(abi_custom)]` finished-final-comment-period The final comment period is finished for this PR / Issue. has-reference-pr This language change has an approved Reference PR. I-lang-nominated Nominated for discussion during a lang team meeting. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-lang Relevant to the language team T-libs Relevant to the library team, which will review and decide on the PR/issue. to-announce Announce this issue on triage meeting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tracking Issue for abi_custom