Skip to content

Commit d88c20c

Browse files
Auto merge of #141435 - RalfJung:unsupported_calling_conventions, r=<try>
Add (back) `unsupported_calling_conventions` lint to reject more invalid calling conventions This adds back the `unsupported_calling_conventions` lint that was removed in #129935, in order to start the process of dealing with #137018. Specifically, we are going for the plan laid out [here](#137018 (comment)): - thiscall, stdcall, fastcall, cdecl should only be accepted on x86-32 - vectorcall should only be accepted on x86-32 and x86-64 The difference to the status quo is that: - We stop accepting stdcall, fastcall on targets that are windows && non-x86-32 (we already don't accept these on targets that are non-windows && non-x86-32) - We stop accepting cdecl on targets that are non-x86-32 - (There is no difference for thiscall, this was already a hard error on non-x86-32) - We stop accepting vectorcall on targets that are windows && non-x86-* Vectorcall is an unstable ABI so we can just make this a hard error immediately. The others are stable, so we emit the `unsupported_calling_conventions` forward-compat lint. I set up the lint to show up in dependencies via cargo's future-compat report immediately, but we could also make it show up just for the local crate first if that is preferred. try-job: i686-msvc-1 try-job: x86_64-msvc-1 try-job: test-various
2 parents 2f2c8c3 + 207b14a commit d88c20c

File tree

22 files changed

+1473
-356
lines changed

22 files changed

+1473
-356
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3786,6 +3786,7 @@ dependencies = [
37863786
"rustc_middle",
37873787
"rustc_session",
37883788
"rustc_span",
3789+
"rustc_target",
37893790
"rustc_trait_selection",
37903791
"smallvec",
37913792
"tracing",

compiler/rustc_hir_analysis/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ rustc_macros = { path = "../rustc_macros" }
2626
rustc_middle = { path = "../rustc_middle" }
2727
rustc_session = { path = "../rustc_session" }
2828
rustc_span = { path = "../rustc_span" }
29+
rustc_target = { path = "../rustc_target" }
2930
rustc_trait_selection = { path = "../rustc_trait_selection" }
3031
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
3132
tracing = "0.1"

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ use std::ops::ControlFlow;
44
use rustc_abi::FieldIdx;
55
use rustc_attr_data_structures::ReprAttr::ReprPacked;
66
use rustc_data_structures::unord::{UnordMap, UnordSet};
7-
use rustc_errors::MultiSpan;
87
use rustc_errors::codes::*;
8+
use rustc_errors::{EmissionGuarantee, MultiSpan};
99
use rustc_hir::def::{CtorKind, DefKind};
1010
use rustc_hir::{LangItem, Node, intravisit};
1111
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
1212
use rustc_infer::traits::{Obligation, ObligationCauseCode};
1313
use rustc_lint_defs::builtin::{
14-
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS,
14+
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_CALLING_CONVENTIONS,
15+
UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS,
1516
};
1617
use rustc_middle::hir::nested_filter;
1718
use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
@@ -24,6 +25,7 @@ use rustc_middle::ty::{
2425
TypeVisitable, TypeVisitableExt, fold_regions,
2526
};
2627
use rustc_session::lint::builtin::UNINHABITED_STATIC;
28+
use rustc_target::spec::{AbiMap, AbiMapping};
2729
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
2830
use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
2931
use rustc_trait_selection::traits;
@@ -35,25 +37,56 @@ use {rustc_attr_data_structures as attrs, rustc_hir as hir};
3537
use super::compare_impl_item::check_type_bounds;
3638
use super::*;
3739

38-
pub fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: ExternAbi) {
39-
if !tcx.sess.target.is_abi_supported(abi) {
40-
struct_span_code_err!(
41-
tcx.dcx(),
42-
span,
43-
E0570,
44-
"`{abi}` is not a supported ABI for the current target",
45-
)
46-
.emit();
40+
pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) {
41+
// FIXME: this should be checked earlier, e.g. in `rustc_ast_lowering`, to fix
42+
// things like #86232.
43+
fn add_help<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T>) {
44+
if let ExternAbi::Cdecl { unwind } = abi {
45+
let c_abi = ExternAbi::C { unwind };
46+
diag.help(format!("use `extern {c_abi}` instead",));
47+
} else if let ExternAbi::Stdcall { unwind } = abi {
48+
let c_abi = ExternAbi::C { unwind };
49+
let system_abi = ExternAbi::System { unwind };
50+
diag.help(format!(
51+
"if you need `extern {abi}` on win32 and `extern {c_abi}` everywhere else, \
52+
use `extern {system_abi}`"
53+
));
54+
}
55+
}
56+
57+
match AbiMap::from_target(&tcx.sess.target).canonize_abi(abi, false) {
58+
AbiMapping::Direct(..) => (),
59+
AbiMapping::Invalid => {
60+
let mut err = struct_span_code_err!(
61+
tcx.dcx(),
62+
span,
63+
E0570,
64+
"`{abi}` is not a supported ABI for the current target",
65+
);
66+
add_help(abi, &mut err);
67+
err.emit();
68+
}
69+
AbiMapping::Deprecated(..) => {
70+
tcx.node_span_lint(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
71+
lint.primary_message("use of calling convention not supported on this target");
72+
add_help(abi, lint);
73+
});
74+
}
4775
}
4876
}
4977

5078
pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) {
51-
if !tcx.sess.target.is_abi_supported(abi) {
52-
tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| {
53-
lint.primary_message(format!(
54-
"the calling convention {abi} is not supported on this target"
55-
));
56-
});
79+
// This is always an FCW, even for `AbiMapping::Invalid`, since we started linting later than
80+
// in `check_abi` above.
81+
match AbiMap::from_target(&tcx.sess.target).canonize_abi(abi, false) {
82+
AbiMapping::Direct(..) => (),
83+
AbiMapping::Deprecated(..) | AbiMapping::Invalid => {
84+
tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| {
85+
lint.primary_message(format!(
86+
"the calling convention {abi} is not supported on this target"
87+
));
88+
});
89+
}
5790
}
5891
}
5992

@@ -779,7 +812,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
779812
let hir::ItemKind::ForeignMod { abi, items } = it.kind else {
780813
return;
781814
};
782-
check_abi(tcx, it.span, abi);
815+
check_abi(tcx, it.hir_id(), it.span, abi);
783816

784817
for item in items {
785818
let def_id = item.id.owner_id.def_id;

compiler/rustc_hir_typeck/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ fn typeck_with_inspect<'tcx>(
150150
tcx.fn_sig(def_id).instantiate_identity()
151151
};
152152

153-
check_abi(tcx, span, fn_sig.abi());
153+
check_abi(tcx, id, span, fn_sig.abi());
154154

155155
// Compute the function signature from point of view of inside the fn.
156156
let mut fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);

compiler/rustc_lint/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,6 @@ fn register_builtins(store: &mut LintStore) {
599599
"converted into hard error, see PR #125380 \
600600
<https://github.com/rust-lang/rust/pull/125380> for more information",
601601
);
602-
store.register_removed("unsupported_calling_conventions", "converted into hard error");
603602
store.register_removed(
604603
"cenum_impl_drop_cast",
605604
"converted into hard error, \

compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3621,6 +3621,54 @@ declare_lint! {
36213621
crate_level_only
36223622
}
36233623

3624+
declare_lint! {
3625+
/// The `unsupported_calling_conventions` lint is output whenever there is a use of the
3626+
/// `stdcall`, `fastcall`, and `cdecl` calling conventions (or their unwind
3627+
/// variants) on targets that cannot meaningfully be supported for the requested target.
3628+
///
3629+
/// For example `stdcall` does not make much sense for a x86_64 or, more apparently, powerpc
3630+
/// code, because this calling convention was never specified for those targets.
3631+
///
3632+
/// Historically MSVC toolchains have fallen back to the regular C calling convention for
3633+
/// targets other than x86, but Rust doesn't really see a similar need to introduce a similar
3634+
/// hack across many more targets.
3635+
///
3636+
/// ### Example
3637+
///
3638+
/// ```rust,ignore (needs specific targets)
3639+
/// extern "stdcall" fn stdcall() {}
3640+
/// ```
3641+
///
3642+
/// This will produce:
3643+
///
3644+
/// ```text
3645+
/// warning: use of calling convention not supported on this target
3646+
/// --> $DIR/unsupported.rs:39:1
3647+
/// |
3648+
/// LL | extern "stdcall" fn stdcall() {}
3649+
/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3650+
/// |
3651+
/// = note: `#[warn(unsupported_calling_conventions)]` on by default
3652+
/// = warning: this was previously accepted by the compiler but is being phased out;
3653+
/// it will become a hard error in a future release!
3654+
/// = note: for more information, see issue ...
3655+
/// ```
3656+
///
3657+
/// ### Explanation
3658+
///
3659+
/// On most of the targets the behaviour of `stdcall` and similar calling conventions is not
3660+
/// defined at all, but was previously accepted due to a bug in the implementation of the
3661+
/// compiler.
3662+
pub UNSUPPORTED_CALLING_CONVENTIONS,
3663+
Warn,
3664+
"use of unsupported calling convention",
3665+
@future_incompatible = FutureIncompatibleInfo {
3666+
reason: FutureIncompatibilityReason::FutureReleaseError,
3667+
report_in_deps: true,
3668+
reference: "issue #137018 <https://github.com/rust-lang/rust/issues/137018>",
3669+
};
3670+
}
3671+
36243672
declare_lint! {
36253673
/// The `unsupported_fn_ptr_calling_conventions` lint is output whenever there is a use of
36263674
/// a target dependent calling convention on a target that does not support this calling

compiler/rustc_metadata/messages.ftl

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,9 @@ metadata_raw_dylib_no_nul =
272272
metadata_raw_dylib_only_windows =
273273
link kind `raw-dylib` is only supported on Windows targets
274274
275+
metadata_raw_dylib_unsupported_abi =
276+
ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
277+
275278
metadata_renaming_no_link =
276279
renaming of the library `{$lib_name}` was specified, however this crate contains no `#[link(...)]` attributes referencing this library
277280
@@ -319,12 +322,6 @@ metadata_unknown_link_modifier =
319322
320323
metadata_unknown_target_modifier_unsafe_allowed = unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}`
321324
322-
metadata_unsupported_abi =
323-
ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
324-
325-
metadata_unsupported_abi_i686 =
326-
ABI not supported by `#[link(kind = "raw-dylib")]` on i686
327-
328325
metadata_wasm_c_abi =
329326
older versions of the `wasm-bindgen` crate are incompatible with current versions of Rust; please update to `wasm-bindgen` v0.2.88
330327

compiler/rustc_metadata/src/errors.rs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -300,15 +300,8 @@ pub struct NoLinkModOverride {
300300
}
301301

302302
#[derive(Diagnostic)]
303-
#[diag(metadata_unsupported_abi_i686)]
304-
pub struct UnsupportedAbiI686 {
305-
#[primary_span]
306-
pub span: Span,
307-
}
308-
309-
#[derive(Diagnostic)]
310-
#[diag(metadata_unsupported_abi)]
311-
pub struct UnsupportedAbi {
303+
#[diag(metadata_raw_dylib_unsupported_abi)]
304+
pub struct RawDylibUnsupportedAbi {
312305
#[primary_span]
313306
pub span: Span,
314307
}

compiler/rustc_metadata/src/native_libs.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,13 @@ impl<'tcx> Collector<'tcx> {
652652
) -> DllImport {
653653
let span = self.tcx.def_span(item);
654654

655-
// this logic is similar to `Target::adjust_abi` (in rustc_target/src/spec/mod.rs) but errors on unsupported inputs
655+
// This `extern` block should have been checked for general ABI support before, but let's
656+
// double-check that.
657+
assert!(self.tcx.sess.target.is_abi_supported(abi));
658+
659+
// This logic is similar to `AbiMap::canonize_abi` (in rustc_target/src/spec/abi_map.rs) but
660+
// we need more detail than those adjustments, and we can't support all ABIs that are
661+
// generally supported.
656662
let calling_convention = if self.tcx.sess.target.arch == "x86" {
657663
match abi {
658664
ExternAbi::C { .. } | ExternAbi::Cdecl { .. } => DllCallingConvention::C,
@@ -679,7 +685,7 @@ impl<'tcx> Collector<'tcx> {
679685
DllCallingConvention::Vectorcall(self.i686_arg_list_size(item))
680686
}
681687
_ => {
682-
self.tcx.dcx().emit_fatal(errors::UnsupportedAbiI686 { span });
688+
self.tcx.dcx().emit_fatal(errors::RawDylibUnsupportedAbi { span });
683689
}
684690
}
685691
} else {
@@ -688,7 +694,7 @@ impl<'tcx> Collector<'tcx> {
688694
DllCallingConvention::C
689695
}
690696
_ => {
691-
self.tcx.dcx().emit_fatal(errors::UnsupportedAbi { span });
697+
self.tcx.dcx().emit_fatal(errors::RawDylibUnsupportedAbi { span });
692698
}
693699
}
694700
};

compiler/rustc_target/src/spec/abi_map.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,6 @@ impl AbiMap {
115115
(ExternAbi::Vectorcall { .. }, Arch::X86 | Arch::X86_64) => {
116116
CanonAbi::X86(X86Call::Vectorcall)
117117
}
118-
(ExternAbi::Vectorcall { .. }, _) if os == OsKind::Windows => {
119-
return AbiMapping::Deprecated(CanonAbi::C);
120-
}
121118
(ExternAbi::Vectorcall { .. }, _) => return AbiMapping::Invalid,
122119

123120
(ExternAbi::SysV64 { .. }, Arch::X86_64) => CanonAbi::X86(X86Call::SysV64),

compiler/rustc_target/src/spec/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ mod abi_map;
6262
mod base;
6363
mod json;
6464

65-
pub use abi_map::AbiMap;
65+
pub use abi_map::{AbiMap, AbiMapping};
6666
pub use base::apple;
6767
pub use base::avr::ef_avr_arch;
6868

0 commit comments

Comments
 (0)