about summary refs log tree commit diff
path: root/compiler/rustc_hir_analysis/src/check/check.rs
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-05-29 12:10:14 +0200
committerRalf Jung <post@ralfj.de>2025-06-08 07:34:41 +0200
commitfab11f619dbab4a6b37d8f99d945a459a158ee5b (patch)
tree33b7c0e4049b5f1ae06dfd9d19a379269948e96a /compiler/rustc_hir_analysis/src/check/check.rs
parent1fc6be419adaf4e6573632e283b85b610135a013 (diff)
downloadrust-fab11f619dbab4a6b37d8f99d945a459a158ee5b.tar.gz
rust-fab11f619dbab4a6b37d8f99d945a459a158ee5b.zip
add specific help messages for stdcall and cdecl
Diffstat (limited to 'compiler/rustc_hir_analysis/src/check/check.rs')
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs26
1 files changed, 22 insertions, 4 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 26a6d67f230..8519ab8d021 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -4,8 +4,8 @@ use std::ops::ControlFlow;
 use rustc_abi::FieldIdx;
 use rustc_attr_data_structures::ReprAttr::ReprPacked;
 use rustc_data_structures::unord::{UnordMap, UnordSet};
-use rustc_errors::MultiSpan;
 use rustc_errors::codes::*;
+use rustc_errors::{EmissionGuarantee, MultiSpan};
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::{LangItem, Node, intravisit};
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
@@ -38,20 +38,38 @@ use super::compare_impl_item::check_type_bounds;
 use super::*;
 
 pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) {
+    // FIXME: this should be checked earlier, e.g. in `rustc_ast_lowering`, to fix
+    // things like #86232.
+    fn add_help<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T>) {
+        if let ExternAbi::Cdecl { unwind } = abi {
+            let c_abi = ExternAbi::C { unwind };
+            diag.help(format!("use `extern {c_abi}` instead",));
+        } else if let ExternAbi::Stdcall { unwind } = abi {
+            let c_abi = ExternAbi::C { unwind };
+            let system_abi = ExternAbi::System { unwind };
+            diag.help(format!(
+                "if you need `extern {abi}` on win32 and `extern {c_abi}` everywhere else, \
+                use `extern {system_abi}`"
+            ));
+        }
+    }
+
     match AbiMap::from_target(&tcx.sess.target).canonize_abi(abi, false) {
         AbiMapping::Direct(..) => (),
         AbiMapping::Invalid => {
-            struct_span_code_err!(
+            let mut err = struct_span_code_err!(
                 tcx.dcx(),
                 span,
                 E0570,
                 "`{abi}` is not a supported ABI for the current target",
-            )
-            .emit();
+            );
+            add_help(abi, &mut err);
+            err.emit();
         }
         AbiMapping::Deprecated(..) => {
             tcx.node_span_lint(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| {
                 lint.primary_message("use of calling convention not supported on this target");
+                add_help(abi, lint);
             });
         }
     }