From 26e35d93dcc8e7b3285c51ee316d6914f304be15 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 4 Jul 2026 11:18:38 -0400 Subject: [PATCH 1/2] Add and use cfg(target_has_threads) to enforce no_thread impl usage The standard library has fallback code for targets without threads (e.g., using a Cell-based Mutex and similar). Today there's no enforcement in std that those targets truly don't have threads which makes that code potentially unsound. This will let us add a static assertion that the target spec agrees that the target is non-threaded. --- compiler/rustc_codegen_llvm/src/back/write.rs | 12 +--- compiler/rustc_feature/src/builtin_attrs.rs | 1 + compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_session/src/config/cfg.rs | 6 ++ compiler/rustc_span/src/symbol.rs | 2 + compiler/rustc_target/src/spec/mod.rs | 23 +++++- library/std/src/lib.rs | 1 + .../std/src/sys/sync/condvar/no_threads.rs | 3 + library/std/src/sys/sync/mutex/no_threads.rs | 3 + library/std/src/sys/sync/once/no_threads.rs | 3 + library/std/src/sys/sync/rwlock/no_threads.rs | 3 + .../std/src/sys/thread_local/no_threads.rs | 3 + tests/rustdoc-ui/doc-cfg-2.stderr | 2 +- tests/ui/cfg/disallowed-cli-cfgs.rs | 2 + ...llowed-cli-cfgs.target_has_threads_.stderr | 8 +++ tests/ui/check-cfg/cargo-build-script.stderr | 2 +- tests/ui/check-cfg/cargo-feature.none.stderr | 2 +- tests/ui/check-cfg/cargo-feature.some.stderr | 2 +- tests/ui/check-cfg/cfg-select.stderr | 2 +- .../cfg-value-for-cfg-name-duplicate.stderr | 2 +- .../cfg-value-for-cfg-name-multiple.stderr | 2 +- .../exhaustive-names-values.feature.stderr | 2 +- .../exhaustive-names-values.full.stderr | 2 +- tests/ui/check-cfg/hrtb-crash.stderr | 2 +- tests/ui/check-cfg/mix.stderr | 2 +- tests/ui/check-cfg/nested-cfg.stderr | 2 +- .../check-cfg/raw-keywords.edition2015.stderr | 2 +- .../check-cfg/raw-keywords.edition2021.stderr | 2 +- .../report-in-external-macros.cargo.stderr | 2 +- .../report-in-external-macros.rustc.stderr | 2 +- tests/ui/check-cfg/well-known-names.stderr | 1 + tests/ui/check-cfg/well-known-values.rs | 3 + tests/ui/check-cfg/well-known-values.stderr | 71 +++++++++++-------- .../feature-gate-cfg-target-has-threads.rs | 5 ++ ...feature-gate-cfg-target-has-threads.stderr | 12 ++++ tests/ui/macros/cfg.stderr | 2 +- tests/ui/macros/cfg_select.stderr | 2 +- 37 files changed, 142 insertions(+), 58 deletions(-) create mode 100644 tests/ui/cfg/disallowed-cli-cfgs.target_has_threads_.stderr create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-has-threads.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-has-threads.stderr diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 4426f6ebb3c17..2b0ea569b5a71 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -22,7 +22,7 @@ use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath}; -use rustc_span::{BytePos, InnerSpan, Pos, RemapPathScopeComponents, SpanData, SyntaxContext, sym}; +use rustc_span::{BytePos, InnerSpan, Pos, RemapPathScopeComponents, SpanData, SyntaxContext}; use rustc_target::spec::{CodeModel, FloatAbi, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel}; use tracing::{debug, trace}; @@ -209,14 +209,8 @@ pub(crate) fn target_machine_factory( let code_model = to_llvm_code_model(sess.code_model()); - let mut singlethread = sess.target.singlethread; - - // On the wasm target once the `atomics` feature is enabled that means that - // we're no longer single-threaded, or otherwise we don't want LLVM to - // lower atomic operations to single-threaded operations. - if singlethread && sess.target.is_like_wasm && sess.target_features.contains(&sym::atomics) { - singlethread = false; - } + // This is used to set cfg_has_threads, so all logic must be in this method. + let singlethread = sess.target.singlethread(&sess.target_features); let triple = SmallCStr::new(&versioned_llvm_target(sess)); let cpu = SmallCStr::new(llvm_util::target_cpu(sess)); diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index e081c2989d3c6..6a9cfeff49339 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -50,6 +50,7 @@ const GATED_CFGS: &[GatedCfg] = &[ sym::cfg_target_has_reliable_f16_f128, Features::cfg_target_has_reliable_f16_f128, ), + (sym::target_has_threads, sym::cfg_target_has_threads, Features::cfg_target_has_threads), (sym::target_object_format, sym::cfg_target_object_format, Features::cfg_target_object_format), ]; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index fc38d9de6e143..0edd6a720800a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -254,6 +254,8 @@ declare_features! ( (unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None), /// Allows checking whether or not the backend correctly supports unstable float types. (internal, cfg_target_has_reliable_f16_f128, "1.88.0", None), + /// Allows checking whether or not the target might have thread support. + (internal, cfg_target_has_threads, "CURRENT_RUSTC_VERSION", None), /// Allows identifying the `compiler_builtins` crate. (internal, compiler_builtins, "1.13.0", None), /// Allows skipping `ConstParamTy_` trait implementation checks diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index cd301bea4eebf..955a77f808588 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -149,6 +149,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) { | (sym::target_pointer_width, Some(_)) | (sym::target_vendor, None | Some(_)) | (sym::target_has_atomic, Some(_)) + | (sym::target_has_threads, None | Some(_)) | (sym::target_has_atomic_primitive_alignment, Some(_)) | (sym::target_has_atomic_load_store, Some(_)) | (sym::target_has_reliable_f16, None | Some(_)) @@ -303,6 +304,10 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { } } + if !sess.target.singlethread(&sess.target_features) { + ins_none!(sym::target_has_threads); + } + ins_sym!(sym::target_os, sess.target.os.desc_symbol()); ins_sym!(sym::target_pointer_width, sym::integer(sess.target.pointer_width)); @@ -485,6 +490,7 @@ impl CheckCfg { ins!(sym::target_has_atomic_primitive_alignment, empty_values).extend(atomic_values); ins!(sym::target_thread_local, no_values); + ins!(sym::target_has_threads, no_values); ins!(sym::ub_checks, no_values); ins!(sym::contract_checks, no_values); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 71eae246ebaff..b99198d9ee8c4 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -598,6 +598,7 @@ symbols! { cfg_target_has_atomic, cfg_target_has_atomic_equal_alignment, cfg_target_has_reliable_f16_f128, + cfg_target_has_threads, cfg_target_object_format, cfg_target_thread_local, cfg_target_vendor, @@ -2084,6 +2085,7 @@ symbols! { target_has_reliable_f16_math, target_has_reliable_f128, target_has_reliable_f128_math, + target_has_threads, target_object_format, target_os, target_pointer_width, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 5c19b35e1605c..a02e08d27a8f1 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2256,6 +2256,26 @@ impl Target { } } } + + /// Is this target single-threaded? + /// + /// This affects both optimizations (e.g., atomics can be lowered to regular operations) and + /// is also exposed as cfg(target_has_threads). + pub fn singlethread(&self, target_features: &FxIndexSet) -> bool { + // On the wasm target once the `atomics` feature is enabled that means that + // we're no longer single-threaded, or otherwise we don't want LLVM to + // lower atomic operations to single-threaded operations. + // + // FIXME: This (probably?) implies that atomics should be a target modifier, at which point + // it probably makes sense to be a separate target to ship precompiled artifacts for it? + // + // cc #77839 (tracking issue for wasm atomics) + if self.singlethread && self.is_like_wasm && target_features.contains(&sym::atomics) { + return false; + } + + self.singlethread + } } pub trait HasTargetSpec { @@ -2571,7 +2591,8 @@ pub struct TargetOptions { pub requires_lto: bool, /// This target has no support for threads. - pub singlethread: bool, + // This is private because wasm changes this depending on target features. + singlethread: bool, /// Whether library functions call lowering/optimization is disabled in LLVM /// for this target unconditionally. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index afa30c8c00f27..6dc276f5599c8 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -276,6 +276,7 @@ #![feature(asm_experimental_arch)] #![feature(autodiff)] #![feature(cfg_sanitizer_cfi)] +#![feature(cfg_target_has_threads)] #![feature(cfg_target_thread_local)] #![feature(cfi_encoding)] #![feature(const_trait_impl)] diff --git a/library/std/src/sys/sync/condvar/no_threads.rs b/library/std/src/sys/sync/condvar/no_threads.rs index 18d97d4b17ab0..9dbba490b2851 100644 --- a/library/std/src/sys/sync/condvar/no_threads.rs +++ b/library/std/src/sys/sync/condvar/no_threads.rs @@ -2,6 +2,9 @@ use crate::sys::sync::Mutex; use crate::thread::sleep; use crate::time::Duration; +#[cfg(target_has_threads)] +compile_error!("Using no_threads implementation on a target with threads"); + pub struct Condvar {} impl Condvar { diff --git a/library/std/src/sys/sync/mutex/no_threads.rs b/library/std/src/sys/sync/mutex/no_threads.rs index a1c2696079f86..a87c2747451c5 100644 --- a/library/std/src/sys/sync/mutex/no_threads.rs +++ b/library/std/src/sys/sync/mutex/no_threads.rs @@ -1,5 +1,8 @@ use crate::cell::Cell; +#[cfg(target_has_threads)] +compile_error!("Using no_threads implementation on a target with threads"); + pub struct Mutex { // This platform has no threads, so we can use a Cell here. locked: Cell, diff --git a/library/std/src/sys/sync/once/no_threads.rs b/library/std/src/sys/sync/once/no_threads.rs index 42fe2417307aa..31c9aedb98f96 100644 --- a/library/std/src/sys/sync/once/no_threads.rs +++ b/library/std/src/sys/sync/once/no_threads.rs @@ -2,6 +2,9 @@ use crate::cell::Cell; use crate::sync as public; use crate::sync::once::OnceExclusiveState; +#[cfg(target_has_threads)] +compile_error!("Using no_threads implementation on a target with threads"); + pub struct Once { state: Cell, } diff --git a/library/std/src/sys/sync/rwlock/no_threads.rs b/library/std/src/sys/sync/rwlock/no_threads.rs index 6de5577504c43..efa2629b3110d 100644 --- a/library/std/src/sys/sync/rwlock/no_threads.rs +++ b/library/std/src/sys/sync/rwlock/no_threads.rs @@ -1,5 +1,8 @@ use crate::cell::Cell; +#[cfg(target_has_threads)] +compile_error!("Using no_threads implementation on a target with threads"); + pub struct RwLock { // This platform has no threads, so we can use a Cell here. mode: Cell, diff --git a/library/std/src/sys/thread_local/no_threads.rs b/library/std/src/sys/thread_local/no_threads.rs index 27a589a4a76ac..f9d0ed384fe24 100644 --- a/library/std/src/sys/thread_local/no_threads.rs +++ b/library/std/src/sys/thread_local/no_threads.rs @@ -5,6 +5,9 @@ use crate::cell::{Cell, UnsafeCell}; use crate::mem::MaybeUninit; use crate::ptr; +#[cfg(target_has_threads)] +compile_error!("Using no_threads implementation on a target with threads"); + #[doc(hidden)] #[allow_internal_unstable(thread_local_internals)] #[allow_internal_unsafe] diff --git a/tests/rustdoc-ui/doc-cfg-2.stderr b/tests/rustdoc-ui/doc-cfg-2.stderr index aeb842c338c6b..da202ea4809f1 100644 --- a/tests/rustdoc-ui/doc-cfg-2.stderr +++ b/tests/rustdoc-ui/doc-cfg-2.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `foo` LL | #[doc(cfg(foo), cfg(bar))] | ^^^ | - = help: expected names are: `FALSE` and `test` and 32 more + = help: expected names are: `FALSE` and `test` and 33 more = help: to expect this configuration use `--check-cfg=cfg(foo)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/cfg/disallowed-cli-cfgs.rs b/tests/ui/cfg/disallowed-cli-cfgs.rs index 57aed0016e971..8697f5a747e18 100644 --- a/tests/ui/cfg/disallowed-cli-cfgs.rs +++ b/tests/ui/cfg/disallowed-cli-cfgs.rs @@ -8,6 +8,7 @@ //@ revisions: target_object_format_ target_pointer_width_ target_vendor_ //@ revisions: target_has_atomic_ target_has_atomic_primitive_alignment_ //@ revisions: target_has_atomic_load_store_ target_thread_local_ relocation_model_ +//@ revisions: target_has_threads_ //@ revisions: fmt_debug_ //@ revisions: reliable_f16_ reliable_f16_math_ reliable_f128_ reliable_f128_math_ @@ -34,6 +35,7 @@ //@ [target_has_atomic_]compile-flags: --cfg target_has_atomic="32" //@ [target_has_atomic_primitive_alignment_]compile-flags: --cfg target_has_atomic_primitive_alignment="32" //@ [target_has_atomic_load_store_]compile-flags: --cfg target_has_atomic_load_store="32" +//@ [target_has_threads_]compile-flags: --cfg target_has_threads //@ [target_thread_local_]compile-flags: --cfg target_thread_local //@ [relocation_model_]compile-flags: --cfg relocation_model="a" //@ [fmt_debug_]compile-flags: --cfg fmt_debug="shallow" diff --git a/tests/ui/cfg/disallowed-cli-cfgs.target_has_threads_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.target_has_threads_.stderr new file mode 100644 index 0000000000000..7fc01e2493883 --- /dev/null +++ b/tests/ui/cfg/disallowed-cli-cfgs.target_has_threads_.stderr @@ -0,0 +1,8 @@ +error: unexpected `--cfg target_has_threads` flag + | + = note: config `target_has_threads` is only supposed to be controlled by `--target` + = note: manually setting a built-in cfg can and does create incoherent behaviors + = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default + +error: aborting due to 1 previous error + diff --git a/tests/ui/check-cfg/cargo-build-script.stderr b/tests/ui/check-cfg/cargo-build-script.stderr index 6039af936a319..9694a762a06c4 100644 --- a/tests/ui/check-cfg/cargo-build-script.stderr +++ b/tests/ui/check-cfg/cargo-build-script.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `has_foo` LL | #[cfg(has_foo)] | ^^^^^^^ | - = help: expected names are: `has_bar` and 32 more + = help: expected names are: `has_bar` and 33 more = help: consider using a Cargo feature instead = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: [lints.rust] diff --git a/tests/ui/check-cfg/cargo-feature.none.stderr b/tests/ui/check-cfg/cargo-feature.none.stderr index c710781b68ce9..05d2a41238258 100644 --- a/tests/ui/check-cfg/cargo-feature.none.stderr +++ b/tests/ui/check-cfg/cargo-feature.none.stderr @@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable` LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `docsrs`, `feature`, and `test` and 32 more + = help: expected names are: `docsrs`, `feature`, and `test` and 33 more = help: consider using a Cargo feature instead = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: [lints.rust] diff --git a/tests/ui/check-cfg/cargo-feature.some.stderr b/tests/ui/check-cfg/cargo-feature.some.stderr index 9e3726f6c6259..de84eb2932e7e 100644 --- a/tests/ui/check-cfg/cargo-feature.some.stderr +++ b/tests/ui/check-cfg/cargo-feature.some.stderr @@ -25,7 +25,7 @@ warning: unexpected `cfg` condition name: `tokio_unstable` LL | #[cfg(tokio_unstable)] | ^^^^^^^^^^^^^^ | - = help: expected names are: `CONFIG_NVME`, `docsrs`, `feature`, and `test` and 32 more + = help: expected names are: `CONFIG_NVME`, `docsrs`, `feature`, and `test` and 33 more = help: consider using a Cargo feature instead = help: or consider adding in `Cargo.toml` the `check-cfg` lint config for the lint: [lints.rust] diff --git a/tests/ui/check-cfg/cfg-select.stderr b/tests/ui/check-cfg/cfg-select.stderr index 8733f42b14710..e4bc800f7cc07 100644 --- a/tests/ui/check-cfg/cfg-select.stderr +++ b/tests/ui/check-cfg/cfg-select.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `invalid_cfg1` LL | invalid_cfg1 => {} | ^^^^^^^^^^^^ | - = help: expected names are: `FALSE` and `test` and 32 more + = help: expected names are: `FALSE` and `test` and 33 more = help: to expect this configuration use `--check-cfg=cfg(invalid_cfg1)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr index ed80d25ffccda..50ae3d88f61df 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `value` LL | #[cfg(value)] | ^^^^^ | - = help: expected names are: `bar`, `bee`, `cow`, and `foo` and 32 more + = help: expected names are: `bar`, `bee`, `cow`, and `foo` and 33 more = help: to expect this configuration use `--check-cfg=cfg(value)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr index 5e0f1b02dd459..b432d46920a22 100644 --- a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr +++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_value` LL | #[cfg(my_value)] | ^^^^^^^^ | - = help: expected names are: `bar` and `foo` and 32 more + = help: expected names are: `bar` and `foo` and 33 more = help: to expect this configuration use `--check-cfg=cfg(my_value)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr index 6e21c47c1d7d1..8c0b623d445ed 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `feature` and 32 more + = help: expected names are: `feature` and 33 more = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr index 6e21c47c1d7d1..8c0b623d445ed 100644 --- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr +++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key` LL | #[cfg(unknown_key = "value")] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `feature` and 32 more + = help: expected names are: `feature` and 33 more = help: to expect this configuration use `--check-cfg=cfg(unknown_key, values("value"))` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/hrtb-crash.stderr b/tests/ui/check-cfg/hrtb-crash.stderr index f83bef31e3a18..d07dee86d680c 100644 --- a/tests/ui/check-cfg/hrtb-crash.stderr +++ b/tests/ui/check-cfg/hrtb-crash.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `b` LL | for<#[cfg(b)] c> u8:; | ^ help: found config with similar value: `target_feature = "b"` | - = help: expected names are: `FALSE`, `docsrs`, and `test` and 32 more + = help: expected names are: `FALSE`, `docsrs`, and `test` and 33 more = help: to expect this configuration use `--check-cfg=cfg(b)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr index b42619b04e9bf..bd0ecc2d0ac6b 100644 --- a/tests/ui/check-cfg/mix.stderr +++ b/tests/ui/check-cfg/mix.stderr @@ -44,7 +44,7 @@ warning: unexpected `cfg` condition name: `uu` LL | #[cfg_attr(uu, unix)] | ^^ | - = help: expected names are: `feature` and 32 more + = help: expected names are: `feature` and 33 more = help: to expect this configuration use `--check-cfg=cfg(uu)` = note: see for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/nested-cfg.stderr b/tests/ui/check-cfg/nested-cfg.stderr index 73a1160a2d487..19dd68753b74e 100644 --- a/tests/ui/check-cfg/nested-cfg.stderr +++ b/tests/ui/check-cfg/nested-cfg.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown` LL | #[cfg(unknown)] | ^^^^^^^ | - = help: expected names are: `FALSE` and `test` and 32 more + = help: expected names are: `FALSE` and `test` and 33 more = help: to expect this configuration use `--check-cfg=cfg(unknown)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/raw-keywords.edition2015.stderr b/tests/ui/check-cfg/raw-keywords.edition2015.stderr index 1524c3558fc95..46e02bfbb3ecd 100644 --- a/tests/ui/check-cfg/raw-keywords.edition2015.stderr +++ b/tests/ui/check-cfg/raw-keywords.edition2015.stderr @@ -14,7 +14,7 @@ warning: unexpected `cfg` condition name: `r#false` LL | #[cfg(r#false)] | ^^^^^^^ | - = help: expected names are: `async`, `edition2015`, `edition2021`, and `r#true` and 32 more + = help: expected names are: `async`, `edition2015`, `edition2021`, and `r#true` and 33 more = help: to expect this configuration use `--check-cfg=cfg(r#false)` = note: see for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/raw-keywords.edition2021.stderr b/tests/ui/check-cfg/raw-keywords.edition2021.stderr index 5859b7592941a..3e108debfcf8b 100644 --- a/tests/ui/check-cfg/raw-keywords.edition2021.stderr +++ b/tests/ui/check-cfg/raw-keywords.edition2021.stderr @@ -14,7 +14,7 @@ warning: unexpected `cfg` condition name: `r#false` LL | #[cfg(r#false)] | ^^^^^^^ | - = help: expected names are: `r#async`, `edition2015`, `edition2021`, and `r#true` and 32 more + = help: expected names are: `r#async`, `edition2015`, `edition2021`, and `r#true` and 33 more = help: to expect this configuration use `--check-cfg=cfg(r#false)` = note: see for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr index 18d361ccdbd7f..646c814ef65f6 100644 --- a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr +++ b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_lib_cfg` LL | cfg_macro::my_lib_macro!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `feature` and 32 more + = help: expected names are: `feature` and 33 more = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate = help: try referring to `cfg_macro::my_lib_macro` crate for guidance on how handle this unexpected cfg = note: see for more information about checking conditional configuration diff --git a/tests/ui/check-cfg/report-in-external-macros.rustc.stderr b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr index 860610baa9719..d38f3560063ac 100644 --- a/tests/ui/check-cfg/report-in-external-macros.rustc.stderr +++ b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr @@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `my_lib_cfg` LL | cfg_macro::my_lib_macro!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: expected names are: `feature` and 32 more + = help: expected names are: `feature` and 33 more = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate = help: try referring to `cfg_macro::my_lib_macro` crate for guidance on how handle this unexpected cfg = help: to expect this configuration use `--check-cfg=cfg(my_lib_cfg)` diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr index ec1345fd6b3cd..3f68bca37dd5d 100644 --- a/tests/ui/check-cfg/well-known-names.stderr +++ b/tests/ui/check-cfg/well-known-names.stderr @@ -28,6 +28,7 @@ LL | #[cfg(list_all_well_known_cfgs)] `target_has_atomic` `target_has_atomic_load_store` `target_has_atomic_primitive_alignment` +`target_has_threads` `target_object_format` `target_os` `target_pointer_width` diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs index 5f961989d720f..c10139570570b 100644 --- a/tests/ui/check-cfg/well-known-values.rs +++ b/tests/ui/check-cfg/well-known-values.rs @@ -15,6 +15,7 @@ #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(cfg_target_object_format)] +#![feature(cfg_target_has_threads)] #![feature(cfg_ub_checks)] #![feature(fmt_debug)] @@ -68,6 +69,8 @@ //~^ WARN unexpected `cfg` condition value target_has_atomic_primitive_alignment = "_UNEXPECTED_VALUE", //~^ WARN unexpected `cfg` condition value + target_has_threads = "_UNEXPECTED_VALUE", + //~^ WARN unexpected `cfg` condition value target_object_format = "_UNEXPECTED_VALUE", //~^ WARN unexpected `cfg` condition value target_os = "_UNEXPECTED_VALUE", diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 5c797783e48b8..693833decc971 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -1,5 +1,5 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:29:5 + --> $DIR/well-known-values.rs:30:5 | LL | clippy = "_UNEXPECTED_VALUE", | ^^^^^^---------------------- @@ -11,7 +11,7 @@ LL | clippy = "_UNEXPECTED_VALUE", = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:31:5 + --> $DIR/well-known-values.rs:32:5 | LL | debug_assertions = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^---------------------- @@ -22,7 +22,7 @@ LL | debug_assertions = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:33:5 + --> $DIR/well-known-values.rs:34:5 | LL | doc = "_UNEXPECTED_VALUE", | ^^^---------------------- @@ -33,7 +33,7 @@ LL | doc = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:35:5 + --> $DIR/well-known-values.rs:36:5 | LL | doctest = "_UNEXPECTED_VALUE", | ^^^^^^^---------------------- @@ -44,7 +44,7 @@ LL | doctest = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:37:5 + --> $DIR/well-known-values.rs:38:5 | LL | fmt_debug = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -53,7 +53,7 @@ LL | fmt_debug = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:39:5 + --> $DIR/well-known-values.rs:40:5 | LL | miri = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -64,7 +64,7 @@ LL | miri = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:41:5 + --> $DIR/well-known-values.rs:42:5 | LL | overflow_checks = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^---------------------- @@ -75,7 +75,7 @@ LL | overflow_checks = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:43:5 + --> $DIR/well-known-values.rs:44:5 | LL | panic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -84,7 +84,7 @@ LL | panic = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:45:5 + --> $DIR/well-known-values.rs:46:5 | LL | proc_macro = "_UNEXPECTED_VALUE", | ^^^^^^^^^^---------------------- @@ -95,7 +95,7 @@ LL | proc_macro = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:47:5 + --> $DIR/well-known-values.rs:48:5 | LL | relocation_model = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -104,7 +104,7 @@ LL | relocation_model = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:49:5 + --> $DIR/well-known-values.rs:50:5 | LL | rustfmt = "_UNEXPECTED_VALUE", | ^^^^^^^---------------------- @@ -115,7 +115,7 @@ LL | rustfmt = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:51:5 + --> $DIR/well-known-values.rs:52:5 | LL | sanitize = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -124,7 +124,7 @@ LL | sanitize = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:53:5 + --> $DIR/well-known-values.rs:54:5 | LL | target_abi = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL | target_abi = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:55:5 + --> $DIR/well-known-values.rs:56:5 | LL | target_arch = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,7 +142,7 @@ LL | target_arch = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:57:5 + --> $DIR/well-known-values.rs:58:5 | LL | target_endian = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -151,7 +151,7 @@ LL | target_endian = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:59:5 + --> $DIR/well-known-values.rs:60:5 | LL | target_env = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -160,7 +160,7 @@ LL | target_env = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:61:5 + --> $DIR/well-known-values.rs:62:5 | LL | target_family = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL | target_family = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:65:5 + --> $DIR/well-known-values.rs:66:5 | LL | target_has_atomic = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -178,7 +178,7 @@ LL | target_has_atomic = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:67:5 + --> $DIR/well-known-values.rs:68:5 | LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -187,7 +187,7 @@ LL | target_has_atomic_load_store = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:69:5 + --> $DIR/well-known-values.rs:70:5 | LL | target_has_atomic_primitive_alignment = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -196,7 +196,18 @@ LL | target_has_atomic_primitive_alignment = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:71:5 + --> $DIR/well-known-values.rs:72:5 + | +LL | target_has_threads = "_UNEXPECTED_VALUE", + | ^^^^^^^^^^^^^^^^^^---------------------- + | | + | help: remove the value + | + = note: no expected value for `target_has_threads` + = note: see for more information about checking conditional configuration + +warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` + --> $DIR/well-known-values.rs:74:5 | LL | target_object_format = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +216,7 @@ LL | target_object_format = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:73:5 + --> $DIR/well-known-values.rs:76:5 | LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -214,7 +225,7 @@ LL | target_os = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:75:5 + --> $DIR/well-known-values.rs:78:5 | LL | target_pointer_width = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -223,7 +234,7 @@ LL | target_pointer_width = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:77:5 + --> $DIR/well-known-values.rs:80:5 | LL | target_thread_local = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^---------------------- @@ -234,7 +245,7 @@ LL | target_thread_local = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:79:5 + --> $DIR/well-known-values.rs:82:5 | LL | target_vendor = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -243,7 +254,7 @@ LL | target_vendor = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:81:5 + --> $DIR/well-known-values.rs:84:5 | LL | ub_checks = "_UNEXPECTED_VALUE", | ^^^^^^^^^---------------------- @@ -254,7 +265,7 @@ LL | ub_checks = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:83:5 + --> $DIR/well-known-values.rs:86:5 | LL | unix = "_UNEXPECTED_VALUE", | ^^^^---------------------- @@ -265,7 +276,7 @@ LL | unix = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` - --> $DIR/well-known-values.rs:85:5 + --> $DIR/well-known-values.rs:88:5 | LL | windows = "_UNEXPECTED_VALUE", | ^^^^^^^---------------------- @@ -276,7 +287,7 @@ LL | windows = "_UNEXPECTED_VALUE", = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `linuz` - --> $DIR/well-known-values.rs:91:7 + --> $DIR/well-known-values.rs:94:7 | LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | ^^^^^^^^^^^^------- @@ -286,5 +297,5 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration -warning: 29 warnings emitted +warning: 30 warnings emitted diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-threads.rs b/tests/ui/feature-gates/feature-gate-cfg-target-has-threads.rs new file mode 100644 index 0000000000000..4acafa8e601d6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-threads.rs @@ -0,0 +1,5 @@ +#[cfg(target_has_threads)] +//~^ ERROR `cfg(target_has_threads)` is experimental and subject to change +fn bar() {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-threads.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-has-threads.stderr new file mode 100644 index 0000000000000..f84f739b11ef6 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-threads.stderr @@ -0,0 +1,12 @@ +error[E0658]: `cfg(target_has_threads)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-threads.rs:1:7 + | +LL | #[cfg(target_has_threads)] + | ^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(cfg_target_has_threads)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/macros/cfg.stderr b/tests/ui/macros/cfg.stderr index a5ee463f2a346..b4c7cd3306d26 100644 --- a/tests/ui/macros/cfg.stderr +++ b/tests/ui/macros/cfg.stderr @@ -46,7 +46,7 @@ warning: unexpected `cfg` condition name: `foo` LL | cfg!(foo); | ^^^ | - = help: expected names are: `FALSE` and `test` and 32 more + = help: expected names are: `FALSE` and `test` and 33 more = help: to expect this configuration use `--check-cfg=cfg(foo)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/macros/cfg_select.stderr b/tests/ui/macros/cfg_select.stderr index 1199b1f4d026c..1a72e7a9c0ace 100644 --- a/tests/ui/macros/cfg_select.stderr +++ b/tests/ui/macros/cfg_select.stderr @@ -169,7 +169,7 @@ warning: unexpected `cfg` condition name: `a` LL | a + 1 => {} | ^ help: found config with similar value: `target_feature = "a"` | - = help: expected names are: `FALSE` and `test` and 32 more + = help: expected names are: `FALSE` and `test` and 33 more = help: to expect this configuration use `--check-cfg=cfg(a)` = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default From fe2db9c9f5b732d9d12ddb1a3c251ff6bb18596e Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 5 Jul 2026 15:43:22 -0400 Subject: [PATCH 2/2] Split TargetTuple definition to separate file This avoids compiler/rustc_target/src/spec/mod.rs hitting tidy's file length check by moving out a chunk of code into a separate file. It's probably not the last such move needed (this only offsets ~100 lines), but it's a reasonable chunk of code to separate. --- compiler/rustc_target/src/spec/mod.rs | 147 +----------------------- compiler/rustc_target/src/spec/tuple.rs | 146 +++++++++++++++++++++++ 2 files changed, 150 insertions(+), 143 deletions(-) create mode 100644 compiler/rustc_target/src/spec/tuple.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index a02e08d27a8f1..c386e4f50bddb 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -40,11 +40,11 @@ use core::result::Result; use std::borrow::Cow; use std::collections::BTreeMap; -use std::hash::{Hash, Hasher}; +use std::fmt; +use std::hash::Hash; use std::ops::{Deref, DerefMut}; use std::path::{Path, PathBuf}; use std::str::FromStr; -use std::{fmt, io}; use rustc_abi::{ Align, CVariadicStatus, CanonAbi, Endian, ExternAbi, Integer, Size, TargetDataLayout, @@ -52,9 +52,7 @@ use rustc_abi::{ }; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_error_messages::{DiagArgValue, IntoDiagArg, into_diag_arg_using_display}; -use rustc_fs_util::try_canonicalize; use rustc_macros::{BlobDecodable, Decodable, Encodable, StableHash}; -use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::{Symbol, kw, sym}; use serde_json::Value; use tracing::debug; @@ -67,11 +65,13 @@ pub mod crt_objects; mod abi_map; mod base; mod json; +mod tuple; pub use abi_map::{AbiMap, AbiMapping}; pub use base::apple; pub use base::avr::ef_avr_arch; pub use json::json_schema; +pub use tuple::TargetTuple; /// Linker is called through a C/C++ compiler. #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] @@ -3914,142 +3914,3 @@ impl Target { Symbol::intern(&self.vendor) } } - -/// Either a target tuple string or a path to a JSON file. -#[derive(Clone, Debug)] -pub enum TargetTuple { - TargetTuple(String), - TargetJson { - /// Warning: This field may only be used by rustdoc. Using it anywhere else will lead to - /// inconsistencies as it is discarded during serialization. - path_for_rustdoc: PathBuf, - tuple: String, - contents: String, - }, -} - -// Use a manual implementation to ignore the path field -impl PartialEq for TargetTuple { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0, - ( - Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents }, - Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents }, - ) => l_tuple == r_tuple && l_contents == r_contents, - _ => false, - } - } -} - -// Use a manual implementation to ignore the path field -impl Hash for TargetTuple { - fn hash(&self, state: &mut H) -> () { - match self { - TargetTuple::TargetTuple(tuple) => { - 0u8.hash(state); - tuple.hash(state) - } - TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => { - 1u8.hash(state); - tuple.hash(state); - contents.hash(state) - } - } - } -} - -// Use a manual implementation to prevent encoding the target json file path in the crate metadata -impl Encodable for TargetTuple { - fn encode(&self, s: &mut S) { - match self { - TargetTuple::TargetTuple(tuple) => { - s.emit_u8(0); - s.emit_str(tuple); - } - TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => { - s.emit_u8(1); - s.emit_str(tuple); - s.emit_str(contents); - } - } - } -} - -impl Decodable for TargetTuple { - fn decode(d: &mut D) -> Self { - match d.read_u8() { - 0 => TargetTuple::TargetTuple(d.read_str().to_owned()), - 1 => TargetTuple::TargetJson { - path_for_rustdoc: PathBuf::new(), - tuple: d.read_str().to_owned(), - contents: d.read_str().to_owned(), - }, - _ => { - panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2"); - } - } - } -} - -impl TargetTuple { - /// Creates a target tuple from the passed target tuple string. - pub fn from_tuple(tuple: &str) -> Self { - TargetTuple::TargetTuple(tuple.into()) - } - - /// Creates a target tuple from the passed target path. - pub fn from_path(path: &Path) -> Result { - let canonicalized_path = try_canonicalize(path)?; - let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| { - io::Error::new( - io::ErrorKind::InvalidInput, - format!("target path {canonicalized_path:?} is not a valid file: {err}"), - ) - })?; - let tuple = canonicalized_path - .file_stem() - .expect("target path must not be empty") - .to_str() - .expect("target path must be valid unicode") - .to_owned(); - Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents }) - } - - /// Returns a string tuple for this target. - /// - /// If this target is a path, the file name (without extension) is returned. - pub fn tuple(&self) -> &str { - match *self { - TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => { - tuple - } - } - } - - /// Returns an extended string tuple for this target. - /// - /// If this target is a path, a hash of the path is appended to the tuple returned - /// by `tuple()`. - pub fn debug_tuple(&self) -> String { - use std::hash::DefaultHasher; - - match self { - TargetTuple::TargetTuple(tuple) => tuple.to_owned(), - TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => { - let mut hasher = DefaultHasher::new(); - content.hash(&mut hasher); - let hash = hasher.finish(); - format!("{tuple}-{hash}") - } - } - } -} - -impl fmt::Display for TargetTuple { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.debug_tuple()) - } -} - -into_diag_arg_using_display!(&TargetTuple); diff --git a/compiler/rustc_target/src/spec/tuple.rs b/compiler/rustc_target/src/spec/tuple.rs new file mode 100644 index 0000000000000..2c4a879d79440 --- /dev/null +++ b/compiler/rustc_target/src/spec/tuple.rs @@ -0,0 +1,146 @@ +use std::hash::{Hash, Hasher}; +use std::path::{Path, PathBuf}; +use std::{fmt, io}; + +use rustc_error_messages::into_diag_arg_using_display; +use rustc_fs_util::try_canonicalize; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; + +/// Either a target tuple string or a path to a JSON file. +#[derive(Clone, Debug)] +pub enum TargetTuple { + TargetTuple(String), + TargetJson { + /// Warning: This field may only be used by rustdoc. Using it anywhere else will lead to + /// inconsistencies as it is discarded during serialization. + path_for_rustdoc: PathBuf, + tuple: String, + contents: String, + }, +} + +// Use a manual implementation to ignore the path field +impl PartialEq for TargetTuple { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::TargetTuple(l0), Self::TargetTuple(r0)) => l0 == r0, + ( + Self::TargetJson { path_for_rustdoc: _, tuple: l_tuple, contents: l_contents }, + Self::TargetJson { path_for_rustdoc: _, tuple: r_tuple, contents: r_contents }, + ) => l_tuple == r_tuple && l_contents == r_contents, + _ => false, + } + } +} + +// Use a manual implementation to ignore the path field +impl Hash for TargetTuple { + fn hash(&self, state: &mut H) -> () { + match self { + TargetTuple::TargetTuple(tuple) => { + 0u8.hash(state); + tuple.hash(state) + } + TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => { + 1u8.hash(state); + tuple.hash(state); + contents.hash(state) + } + } + } +} + +// Use a manual implementation to prevent encoding the target json file path in the crate metadata +impl Encodable for TargetTuple { + fn encode(&self, s: &mut S) { + match self { + TargetTuple::TargetTuple(tuple) => { + s.emit_u8(0); + s.emit_str(tuple); + } + TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents } => { + s.emit_u8(1); + s.emit_str(tuple); + s.emit_str(contents); + } + } + } +} + +impl Decodable for TargetTuple { + fn decode(d: &mut D) -> Self { + match d.read_u8() { + 0 => TargetTuple::TargetTuple(d.read_str().to_owned()), + 1 => TargetTuple::TargetJson { + path_for_rustdoc: PathBuf::new(), + tuple: d.read_str().to_owned(), + contents: d.read_str().to_owned(), + }, + _ => { + panic!("invalid enum variant tag while decoding `TargetTuple`, expected 0..2"); + } + } + } +} + +impl TargetTuple { + /// Creates a target tuple from the passed target tuple string. + pub fn from_tuple(tuple: &str) -> Self { + TargetTuple::TargetTuple(tuple.into()) + } + + /// Creates a target tuple from the passed target path. + pub fn from_path(path: &Path) -> Result { + let canonicalized_path = try_canonicalize(path)?; + let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| { + io::Error::new( + io::ErrorKind::InvalidInput, + format!("target path {canonicalized_path:?} is not a valid file: {err}"), + ) + })?; + let tuple = canonicalized_path + .file_stem() + .expect("target path must not be empty") + .to_str() + .expect("target path must be valid unicode") + .to_owned(); + Ok(TargetTuple::TargetJson { path_for_rustdoc: canonicalized_path, tuple, contents }) + } + + /// Returns a string tuple for this target. + /// + /// If this target is a path, the file name (without extension) is returned. + pub fn tuple(&self) -> &str { + match *self { + TargetTuple::TargetTuple(ref tuple) | TargetTuple::TargetJson { ref tuple, .. } => { + tuple + } + } + } + + /// Returns an extended string tuple for this target. + /// + /// If this target is a path, a hash of the path is appended to the tuple returned + /// by `tuple()`. + pub fn debug_tuple(&self) -> String { + use std::hash::DefaultHasher; + + match self { + TargetTuple::TargetTuple(tuple) => tuple.to_owned(), + TargetTuple::TargetJson { path_for_rustdoc: _, tuple, contents: content } => { + let mut hasher = DefaultHasher::new(); + content.hash(&mut hasher); + let hash = hasher.finish(); + format!("{tuple}-{hash}") + } + } + } +} + +impl fmt::Display for TargetTuple { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.debug_tuple()) + } +} + +into_diag_arg_using_display!(&TargetTuple);