Reject unsupported extern "{abi}"s consistently in all positions#142134
Merged
bors merged 12 commits intorust-lang:masterfrom Jun 24, 2025
Merged
Reject unsupported extern "{abi}"s consistently in all positions#142134bors merged 12 commits intorust-lang:masterfrom
extern "{abi}"s consistently in all positions#142134bors merged 12 commits intorust-lang:masterfrom
Conversation
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Modify the handling of
extern "{abi}"in the compiler so that it has consistent errors without regard to the position in the grammar.What
Implement the following breakages:
unsupported_fn_ptr_calling_conventionsfrom a warning to a hard errorIn particular, these architecture-specific ABIs now only compile on their architectures1:
ABIs that are logically x86-specific but actually permitted on all Windows targets remain permitted on Windows, as before. For non-Windows targets, they error if we had previously done so in other positions.
How
We modify rustc_ast_lowering to prevent unsupported ABIs from leaking through the HIR without being checked for target support. They now emit hard errors for every case where we would return
InvalidfromAbiMap::canonize_abi. Previously ad-hoc checking on various HIR items required making sure we check every HIR item which could contain anextern "{abi}"string. This is a losing proposition compared to gating the lowering itself.As a consequence, unsupported ABI strings error instead of triggering the warning
unsupported_fn_ptr_calling_conventions. The code is also simpler compared to alternative implementations that might e.g. split on unstable vs. stable, only suffering some unavoidable complication to support the newly-revivedunsupported_calling_conventionslint.2However, per #86232 this does cause errors for rare usages of
extern "{abi}"that were theoretically possible to write in Rust source, without previous warning or error. For instance, trait declarations without impls were never checked. These are the exact kinds of leakages that this new approach prevents.This differs from the following PRs:
unsupported_calling_conventionslint to reject more invalid calling conventions #141435 is orthogonal, as it adds a new lint for ABIs we have not warned on and are not touched by this PRWhy or Why Not
We already made the decision to issue the
unsupported_fn_ptr_calling_conventionsfuture compatibility warning. It has warned in dependencies since #135767, which reached stable with Rust 1.87. That was released on 2025 May 17, and it is now June. As we already had erred on these ABI strings in most other positions, and warn on stable for function pointer types, this breakage has had reasonable foreshadowing.Upgrading the warning to an error addresses a real problem. In some cases the Rust compiler can attempt to actually compute the ABI for calling a function with an unsupported ABI. We could accept this case and compute unsupported ABIs according to some other ABI, silently3. However, this obviously exposes Rust to errors in codegen. We cannot lower directly to the "obvious", target-incorrect ABI and then trust code generators like LLVM to reliably error on these cases, either.
Other considerations include:
unsupported_calling_conventionslint, means people who would otherwise have to deal with two lints only have to update their code in one batch. Of course, one of them is as breakage.r? lang
Fixes #86232
Fixes #132430
Fixes #138738
Fixes #142107
Footnotes
Some already will not compile, due to reaching ICEs or LLVM errors. ↩
That lint cannot be moved in a similar way yet because lints operate on HIR, so you cannot emit lints when the HIR has not been completely formed. ↩
We already do this for all
AbiStrwe cannot parse, pretending they areExternAbi::Rust, but we also emit an error to prevent reaching too far into codegen. ↩Upon any impl, even for provided fn within trait declarations, e.g.
pub extern "gpu-kernel" fn sneaky() {}, different HIR types were used which would, in fact, get checked. Likewise for anything with function pointers. Thus we would be discussing deprecation cycles for code that is impotent or forewarned5. ↩It actually did appear in two cases in rustc's test suite because we are a collection of Rust edge-cases by the simple fact that we don't care if the code actually runs. These cases are being excised in 643a9d2 ↩