Skip to content

Commit 2f4a55b

Browse files
compiler: plug unsupported ABI leakage from the AST
We modify rustc_ast_lowering to prevent all unsupported ABIs from leaking through the HIR without being checked for target support. Previously ad-hoc checking on various HIR items required making sure we check every HIR item which could contain an `extern "{abi}"` string. This is a losing proposition compared to gating the lowering itself. As a consequence, unsupported ABI strings will now hard-error instead of triggering the FCW `unsupported_fn_ptr_calling_conventions`. This FCW was upgraded to warn in dependencies in Rust 1.87 which was released on 2025 May 17, and it is now 2025 June, so it has become active within a stable Rust version. As we already had errored on these ABIs in most other positions, and have warned for fn ptrs, this breakage has had reasonable foreshadowing. However, this does cause errors for usages of `extern "{abi}"` that were theoretically writeable within source but could not actually be applied in any useful way by Rust programmers without either warning or error. For instance, trait declarations without impls were never checked. These are the exact kinds of leakages that this new approach prevents. A deprecation cycle is not useful for these marginal cases as upon impl, even default impls within traits, different HIR objects would be used. Details of our HIR analysis meant that those objects did get checked. We choose to error twice if an ABI is also barred by a feature gate on the presumption that usage of a target-incorrect ABI is intentional. Co-authored-by: Ralf Jung <post@ralfj.de>
1 parent 42245d3 commit 2f4a55b

File tree

1 file changed

+24
-4
lines changed
  • compiler/rustc_ast_lowering/src

1 file changed

+24
-4
lines changed

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc_abi::ExternAbi;
22
use rustc_ast::ptr::P;
33
use rustc_ast::visit::AssocCtxt;
44
use rustc_ast::*;
5-
use rustc_errors::ErrorGuaranteed;
5+
use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err};
66
use rustc_hir::def::{DefKind, PerNS, Res};
77
use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
88
use rustc_hir::{self as hir, HirId, LifetimeSource, PredicateOrigin};
@@ -1644,9 +1644,29 @@ impl<'hir> LoweringContext<'_, 'hir> {
16441644
self.error_on_invalid_abi(abi_str);
16451645
ExternAbi::Rust
16461646
});
1647-
let sess = self.tcx.sess;
1648-
let features = self.tcx.features();
1649-
gate_unstable_abi(sess, features, span, extern_abi);
1647+
let tcx = self.tcx;
1648+
1649+
// we can't do codegen for unsupported ABIs, so error now so we won't get farther
1650+
if !tcx.sess.target.is_abi_supported(extern_abi) {
1651+
let mut err = struct_span_code_err!(
1652+
tcx.dcx(),
1653+
span,
1654+
E0570,
1655+
"{extern_abi} is not a supported ABI for the current target",
1656+
);
1657+
1658+
if let ExternAbi::Stdcall { unwind } = extern_abi {
1659+
let c_abi = ExternAbi::C { unwind };
1660+
let system_abi = ExternAbi::System { unwind };
1661+
err.help(format!("if you need `extern {extern_abi}` on win32 and `extern {c_abi}` everywhere else, \
1662+
use `extern {system_abi}`"
1663+
));
1664+
}
1665+
err.emit();
1666+
}
1667+
// Show required feature gate even if we already errored, as the user is likely to build the code
1668+
// for the actually intended target next and then they will need the feature gate.
1669+
gate_unstable_abi(tcx.sess, tcx.features(), span, extern_abi);
16501670
extern_abi
16511671
}
16521672

0 commit comments

Comments
 (0)