Repository navigation
Tracking issue for unsupported_calling_conventions (cdecl, stdcall, fastcall) #137018
Copy link
Copy link
Open
Labels
A-ABIArea: Concerning the application binary interface (ABI)Area: Concerning the application binary interface (ABI)C-bugCategory: This is a bug.Category: This is a bug.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCI-lang-radarItems that are on lang's radar and will need eventual work or consideration.Items that are on lang's radar and will need eventual work or consideration.O-windowsOperating system: WindowsOperating system: WindowsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language team
Description
This is a tracking issue for the unsupported_calling_conventions lint. This lint warns against
- Using
extern "cdecl"on non-x86-32 targets. Useextern "C"instead, there is no difference in behavior. - Using
extern "stdcall"orextern "fastcall"on non-x86-32 Windows targets. These ABIs are only defined for x86-32.- If you want to use "stdcall on x86-32-windows, C everywhere else", then use
extern "system". - Otherwise, if you really need the same function both on x86-32 and on other targets but with a different ABI, consider using the
fn_abicrate. Also we'd be interested to hear about your use-case, so please leave a comment below.
- If you want to use "stdcall on x86-32-windows, C everywhere else", then use
Implementation history:
Timeline:
- This was introduced with Rust 1.89.
- There's no timeline yet for when this will show up in cargo's future-compat reports, or be turned into a hard error. Since windows-sys needs an update to v0.60 to avoid the lint, we'll have to move really slowly here.
Original issue description
We generally accept stdcall on non-x86-32 Windows targets (while rejecting it on other non-x86-32 targets). See the discussion about this at #86231 (comment) and #86231 (comment). However, @ChrisDenton points out that the raw-dylib feature is more strict here. That's an inconsistency that we should probably fix?
@ChrisDenton can you give an example of what exactly is being rejected by raw-dylib here?
2025-05-05: See here for the current latest proposal.
Cc @workingjubilee @rust-lang/lang @nagisa @petrochenkov
Metadata
Metadata
Assignees
Labels
A-ABIArea: Concerning the application binary interface (ABI)Area: Concerning the application binary interface (ABI)C-bugCategory: This is a bug.Category: This is a bug.C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCCategory: An issue tracking the progress of sth. like the implementation of an RFCI-lang-radarItems that are on lang's radar and will need eventual work or consideration.Items that are on lang's radar and will need eventual work or consideration.O-windowsOperating system: WindowsOperating system: WindowsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-langRelevant to the language teamRelevant to the language team
Activity
ChrisDenton commentedon Feb 14, 2025
It's just generally more strict. As far as I recall this is intentional, cc @dpaoliello. For example:
This is rejected on
x86_64-pc-windows-msvcandaarch64-pc-windows-msvc. But removekind = "raw-dylib"and it works.RalfJung commentedon Feb 14, 2025
Aditya-PS-05 commentedon Feb 14, 2025
RalfJung commentedon Feb 14, 2025
@Aditya-PS-05 currently this issue is about discussing what to do next; there is no agreed-upon plan for what to do yet.
Reading the past comments, it seems like ~noone argued in favor of the status quo. So maybe the best next step is to have a FCW lint against
This should probably re-introduce the lint that was removed in #129935.
@ChrisDenton also mentioned cdecl above; I did not have that on my radar yet. Currently, that one is accepted everywhere. Which targets should it support?Either way, raw-dylib shouldn't have its own "does this ABI make sense" logic (currently located here); it should call
is_abi_supportedlike everything else. (But that function might return a three-state value to indicate "not really but for backwards compatibility we accept this in some cases; and raw-dylib can then make a hard error rather than an FCW for those.)Aditya-PS-05 commentedon Feb 14, 2025
ChrisDenton commentedon Feb 14, 2025
dpaoliello commentedon Feb 14, 2025
Yes, it was intentional, although I would describe it more as "let's start restrictive and we'll loosen things later" rather than "this is the absolute correct behavior": #86419 (comment)
raw-dylib has its own logic for historical reasons: primarily that it wasn't supported for all calling conventions or all arches for a while, hence its own logic to filter to what it did support.
Personally, I'm going to bow out of this discussion. I previously said that having this behavior would cause a proliferation of
cfg_attrattributes without a huge benefit to safety or correctness but was told that #87678 would eventually be an error and so this would be moot: https://rust-lang.zulipchat.com/#narrow/channel/233931-t-compiler.2Fmajor-changes/topic/Add.20import_name_type.20parameter.20to.20.23.5Blink.5D.20compiler-team.2352539 remaining items
RalfJung commentedon Jul 1, 2025
There's no such thing as stdcall on ARM64, is there...?
Or do you mean, "the thing that MSVC does when you use stdcall on ARM64"? AFAIK, it just ignores the stdcall, silently, and uses the normal C ABI instead. So in that sense "system" is the same thing, yes.
pronebird commentedon Jul 1, 2025
I have no idea to be frank. I am only exposed to calling conventions as a WinAPI user.
I'd need to boot and see what
#define WINAPItranslates to on ARM64 Windows, however I asked GitHub AI just for giggles and it printed this table for me:Summary Table:
So that coincides with what you said and I assume
systemmaps to the same conventions on each architecture. Alsowindowscrate usessystemwhich is good news.workingjubilee commentedon Jul 1, 2025
Maybe we can make the messaging more precise here?
If you are using
extern "cdecl"then you can always useextern "C"instead, i.e. it's sound to do themem::transmutebetween those ABIs, unconditionally.RalfJung commentedon Jul 1, 2025
The error already explicitly says that you can replace "cdecl" by "C" unconditionally.
"cdecl" is an ABI that only exists on x86, which is why we now warn if you use it anywhere else.
Change stdcall to system calling convention (#3019)
Change stdcall to system calling convention (#3019)
[-]Tracking issue for unsupported_calling_conventions[/-][+]Tracking issue for unsupported_calling_conventions (cdecl, stdcall, fastcall)[/+]kennykerr commentedon Jul 31, 2025
RalfJung commentedon Aug 1, 2025
Fix warnings from unsupported_calling_conventions
Replace `extern "stdcall"` with `extern "system"`
MauriceKayser commentedon Apr 2, 2026
RalfJung on 2025-05-05
I hope this is a good place for feedback, I would like to present the following use case:
On Windows, when interfacing with an MSVC compiled C++ dynamic library that exports C functions to create and free objects of a C++ class, and the class has virtual functions, they will be
thiscallon x86-32, andCotherwise:C++ compilation script if you want to try, should be in a subdirectory of the Rust project directory structure, e.g. "rust-proj\cpp-code\"
The following code does compile for
i686-pc-windows-msvc, but does not forx86_64-pc-windows-msvc, becausethiscallcan not be used instruct Vtbl:The only option I see currently is duplicating the function declarations in
struct Vtbl, e.g. by using a macro:At least for Windows, one of the following options would be preferable:
thiscallbecomesCif arch != x86-32classcalling convention becomingthiscallon x86-32,Celsewhere. Similar tosystembecomingstdcallon x86-32 andCelsewhereTo mimic MSVCs behaviour of ignoring explicit calling conventions on non-x86-32 targets (correct me if I am wrong), the first option would probably be the most ergonomic, as that could extend to other calling conventions like
fastcall, etc. without having to invent new ones likesystemandclass.RalfJung commentedon Apr 2, 2026
Thanks for the report! This issue is primarily about cdecl, stdcall, fastcall... not thiscall. It's related to this issue in the sense that you're basically asking to add the behavior to thiscall that we are in the process of removing from stdcall/fastcall.
I'm not sure what a coherent design would look like here if we give thiscall fallback behavior. Does this mean stdcall and system become synonyms? That seems odd as well.
fix: use extern "C" instead of deprecated extern "cdecl" for MSVC CRT…
feat(cli): runtime/sandbox separation + multi-OS CI + Windows e2e (#35)