]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_hir_analysis/src/lib.rs
Rollup merge of #103681 - RalfJung:libtest-thread, r=thomcc
[rust.git] / compiler / rustc_hir_analysis / src / lib.rs
index 525cd24190a4c920db4a1fc0030ba56c31c54f18..bd1a461b93522235cb2b6423a48da8f0f11c4dfa 100644 (file)
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::util;
-use rustc_session::config::EntryFnType;
+use rustc_session::{config::EntryFnType, parse::feature_err};
 use rustc_span::{symbol::sym, Span, DUMMY_SP};
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use bounds::Bounds;
 
 fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) {
-    match (decl.c_variadic, abi) {
-        // The function has the correct calling convention, or isn't a "C-variadic" function.
-        (false, _) | (true, Abi::C { .. }) | (true, Abi::Cdecl { .. }) => {}
-        // The function is a "C-variadic" function with an incorrect calling convention.
-        (true, _) => {
-            let mut err = struct_span_err!(
-                tcx.sess,
+    const ERROR_HEAD: &str = "C-variadic function must have a compatible calling convention";
+    const CONVENTIONS_UNSTABLE: &str = "`C`, `cdecl`, `win64`, `sysv64` or `efiapi`";
+    const CONVENTIONS_STABLE: &str = "`C` or `cdecl`";
+    const UNSTABLE_EXPLAIN: &str =
+        "using calling conventions other than `C` or `cdecl` for varargs functions is unstable";
+
+    if !decl.c_variadic || matches!(abi, Abi::C { .. } | Abi::Cdecl { .. }) {
+        return;
+    }
+
+    let extended_abi_support = tcx.features().extended_varargs_abi_support;
+    let conventions = match (extended_abi_support, abi.supports_varargs()) {
+        // User enabled additional ABI support for varargs and function ABI matches those ones.
+        (true, true) => return,
+
+        // Using this ABI would be ok, if the feature for additional ABI support was enabled.
+        // Return CONVENTIONS_STABLE, because we want the other error to look the same.
+        (false, true) => {
+            feature_err(
+                &tcx.sess.parse_sess,
+                sym::extended_varargs_abi_support,
                 span,
-                E0045,
-                "C-variadic function must have C or cdecl calling convention"
-            );
-            err.span_label(span, "C-variadics require C or cdecl calling convention").emit();
+                UNSTABLE_EXPLAIN,
+            )
+            .emit();
+            CONVENTIONS_STABLE
         }
-    }
+
+        (false, false) => CONVENTIONS_STABLE,
+        (true, false) => CONVENTIONS_UNSTABLE,
+    };
+
+    let mut err = struct_span_err!(tcx.sess, span, E0045, "{}, like {}", ERROR_HEAD, conventions);
+    err.span_label(span, ERROR_HEAD).emit();
 }
 
 fn require_same_types<'tcx>(