extern macro!(ABI) fn
See original GitHub issueProposal
Summary and problem statement
Today, there are cases where the ABI in extern ABI
should be selected based on static properties, such as the target architecture.
I propose we fix this by making extern macro!(ABI) fn
work. This way, people will not have to write duplicate definitions under #[cfg(...)]
attributes to get the same effect.
Motivation, use-cases, and solution sketches
Today in Rust, there are cases where the same function definition can work for distinct ABI’s depending on target. But you cannot merge them into one definition; you have to use separate function items with distinct #[cfg(...)]
attributes.
For example, this comment describes a scenario where this leads to code duplication (at the level of signature and body) between an extern "thiscall" fn
on i686-windows and an extern "fastcall" fn
on x86_64-windows.
If we made the ABI in extern ABI
a macro expansion position, then the above would be easy to resolve: someone who has literally the same definition for both cases would write an appropriate macro to expand the right way. (I have sketched an idea like extern cfg_match!(target_arch, "x86" => "thiscall", "x86_64" => "fastcall") fn foo() {}
, but this initiative is not about what specific macro to use; it is about enabling macros to be used at all.
Links and related work
Inspired by suggestion from @DrMeepster
Initial people involved
- Owner, if known: pnkfelix
- Liaison
What happens now?
This issue is part of the lang-team initiative process. Once this issue is filed, a Zulip topic will be opened for discussion, and the lang-team will review open proposals in its weekly triage meetings. You should receive feedback within a week or two.
This issue is not meant to be used for technical discussion. There is a Zulip stream for that. Use this issue to leave procedural comments, such as volunteering to review, indicating that you second the proposal (or third, etc), or raising a concern that you would like to be addressed.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:15 (11 by maintainers)
We discussed this in today’s @rust-lang/lang meeting. The consensus of the meeting was actually the reverse of the opinion described here – we felt we did NOT want to add this feature. Therefore, I am going to withdraw my second and adjust the labels.
@rustbot label -final-comment-period -to-announce
Many of us felt initially that we generally want to allow macros everywhere we can, but @cramertj raised a key objection that, in this instance, it was a bit unclear that this macro ought to expand to an ABI string in particular. Given that the ABI part of an
extern fn
is optional, one could imagine thef!()
inextern f!()
might expand to a function or to other modifiers (e.g.,unsafe
). We might also add other sorts of modifiers that go before thefn
that would make for extra confusion here.That fact, combined with general agreement that we should make the 32-bit windows ABIs (e.g., thiscall and friends) “fallback” to the standard ABI in 64-bit case (matching the behavior of MSVC, as I understand it), made this particular placement of macros seem like it could cause more confusion than it would bring benefit.
Another point against this proposal was that it would be quite easy to write a procedural macro that “rewrites” the ABI of functions, so that e.g.
could look at the target and adjust the ABI accordingly.
also, @DrMeepster, I didn’t mean to step on any toes. As I said, I was inspired by your comment to take action here, but I did not know that you had already started drafting a formal RFC.
The language and compiler team have both been working on identifying lighterweight methodologies that have smaller stages with explicit intermediate goals. @nikomatsakis and I both agreed that this would be a language team issue, but not one that requires a ton of effort.
In particular I am thinking we can use the language team initiative process and get started on a prototype implementation, while the RFC process moves forward in parallel.