about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_session/messages.ftl4
-rw-r--r--compiler/rustc_session/src/errors.rs8
-rw-r--r--compiler/rustc_session/src/session.rs7
-rw-r--r--compiler/rustc_target/src/lib.rs1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs21
-rw-r--r--tests/ui/linkage-attr/incompatible-flavor.rs6
-rw-r--r--tests/ui/linkage-attr/incompatible-flavor.stderr6
7 files changed, 51 insertions, 2 deletions
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl
index 5a0b8f9f73c..4897bd8d5da 100644
--- a/compiler/rustc_session/messages.ftl
+++ b/compiler/rustc_session/messages.ftl
@@ -27,6 +27,10 @@ session_feature_gate_error = {$explain}
 session_file_is_not_writeable = output file {$file} is not writeable -- check its permissions
 
 session_hexadecimal_float_literal_not_supported = hexadecimal float literal is not supported
+
+session_incompatible_linker_flavor = linker flavor `{$flavor}` is incompatible with the current target
+    .note = compatible flavors are: {$compatible_list}
+
 session_incorrect_cgu_reuse_type =
     CGU-reuse for `{$cgu_user_name}` is `{$actual_reuse}` but should be {$at_least ->
     [one] {"at least "}
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 546c0fa8e03..4a3e668da11 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -422,3 +422,11 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span:
 pub struct OptimisationFuelExhausted {
     pub msg: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(session_incompatible_linker_flavor)]
+#[note]
+pub struct IncompatibleLinkerFlavor {
+    pub flavor: &'static str,
+    pub compatible_list: String,
+}
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index bbe52dbced0..1eb54cee5a1 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -1675,6 +1675,13 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
     if sess.opts.unstable_opts.instrument_xray.is_some() && !sess.target.options.supports_xray {
         sess.emit_err(errors::InstrumentationNotSupported { us: "XRay".to_string() });
     }
+
+    if let Some(flavor) = sess.opts.cg.linker_flavor {
+        if let Some(compatible_list) = sess.target.linker_flavor.check_compatibility(flavor) {
+            let flavor = flavor.desc();
+            sess.emit_err(errors::IncompatibleLinkerFlavor { flavor, compatible_list });
+        }
+    }
 }
 
 /// Holds data on the current incremental compilation session, if there is one.
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index dc2cc23ffb1..a7b54766bc6 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -11,6 +11,7 @@
 #![feature(assert_matches)]
 #![feature(associated_type_bounds)]
 #![feature(exhaustive_patterns)]
+#![feature(iter_intersperse)]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 6a3eea1427f..05cb7e87a93 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -319,6 +319,19 @@ impl LinkerFlavor {
         self.with_hints(LinkerFlavor::infer_linker_hints(linker_stem))
     }
 
+    pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option<String> {
+        // The CLI flavor should be compatible with the target if it survives this roundtrip.
+        let compatible = |cli| cli == self.with_cli_hints(cli).to_cli();
+        (!compatible(cli)).then(|| {
+            LinkerFlavorCli::all()
+                .iter()
+                .filter(|cli| compatible(**cli))
+                .map(|cli| cli.desc())
+                .intersperse(", ")
+                .collect()
+        })
+    }
+
     pub fn lld_flavor(self) -> LldFlavor {
         match self {
             LinkerFlavor::Gnu(..)
@@ -340,6 +353,10 @@ impl LinkerFlavor {
 macro_rules! linker_flavor_cli_impls {
     ($(($($flavor:tt)*) $string:literal)*) => (
         impl LinkerFlavorCli {
+            const fn all() -> &'static [LinkerFlavorCli] {
+                &[$($($flavor)*,)*]
+            }
+
             pub const fn one_of() -> &'static str {
                 concat!("one of: ", $($string, " ",)*)
             }
@@ -351,8 +368,8 @@ macro_rules! linker_flavor_cli_impls {
                 })
             }
 
-            pub fn desc(&self) -> &str {
-                match *self {
+            pub fn desc(self) -> &'static str {
+                match self {
                     $($($flavor)* => $string,)*
                 }
             }
diff --git a/tests/ui/linkage-attr/incompatible-flavor.rs b/tests/ui/linkage-attr/incompatible-flavor.rs
new file mode 100644
index 00000000000..90c2b612f22
--- /dev/null
+++ b/tests/ui/linkage-attr/incompatible-flavor.rs
@@ -0,0 +1,6 @@
+// compile-flags: --target=x86_64-unknown-linux-gnu -C linker-flavor=msvc --crate-type=rlib
+// error-pattern: linker flavor `msvc` is incompatible with the current target
+// needs-llvm-components:
+
+#![feature(no_core)]
+#![no_core]
diff --git a/tests/ui/linkage-attr/incompatible-flavor.stderr b/tests/ui/linkage-attr/incompatible-flavor.stderr
new file mode 100644
index 00000000000..e07e778521c
--- /dev/null
+++ b/tests/ui/linkage-attr/incompatible-flavor.stderr
@@ -0,0 +1,6 @@
+error: linker flavor `msvc` is incompatible with the current target
+   |
+   = note: compatible flavors are: gcc, ld, ld.lld
+
+error: aborting due to previous error
+