Skip to main content

rustc_session/config/
cfg.rs

1//! cfg and check-cfg configuration
2//!
3//! This module contains the definition of [`Cfg`] and [`CheckCfg`]
4//! as well as the logic for creating the default configuration for a
5//! given [`Session`].
6//!
7//! It also contains the filling of the well known configs, which should
8//! ALWAYS be in sync with the default_configuration.
9//!
10//! ## Adding a new cfg
11//!
12//! Adding a new feature requires two new symbols one for the cfg itself
13//! and the second one for the unstable feature gate, those are defined in
14//! `rustc_span::symbol`.
15//!
16//! As well as the following points,
17//!  - Add the activation logic in [`default_configuration`]
18//!  - Add the cfg to [`CheckCfg::fill_well_known`] (and related files),
19//!    so that the compiler can know the cfg is expected
20//!  - Add the cfg in [`disallow_cfgs`] to disallow users from setting it via `--cfg`
21//!  - Add the feature gating in `compiler/rustc_feature/src/builtin_attrs.rs`
22
23use std::hash::Hash;
24use std::iter;
25
26use rustc_abi::Align;
27use rustc_ast::ast;
28use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
29use rustc_lint_defs::builtin::EXPLICIT_BUILTIN_CFGS_IN_FLAGS;
30use rustc_span::{Symbol, sym};
31use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, Target};
32
33use crate::config::{CrateType, FmtDebug};
34use crate::{Session, diagnostics};
35
36/// The parsed `--cfg` options that define the compilation environment of the
37/// crate, used to drive conditional compilation.
38///
39/// An `FxIndexSet` is used to ensure deterministic ordering of error messages
40/// relating to `--cfg`.
41pub type Cfg = FxIndexSet<(Symbol, Option<Symbol>)>;
42
43/// The parsed `--check-cfg` options.
44#[derive(#[automatically_derived]
impl ::core::default::Default for CheckCfg {
    #[inline]
    fn default() -> Self {
        Self {
            exhaustive_names: ::core::default::Default::default(),
            exhaustive_values: ::core::default::Default::default(),
            expecteds: ::core::default::Default::default(),
            well_known_names: ::core::default::Default::default(),
        }
    }
}Default)]
45pub struct CheckCfg {
46    /// Is well known names activated
47    pub exhaustive_names: bool,
48    /// Is well known values activated
49    pub exhaustive_values: bool,
50    /// All the expected values for a config name
51    pub expecteds: FxHashMap<Symbol, ExpectedValues<Symbol>>,
52    /// Well known names (only used for diagnostics purposes)
53    pub well_known_names: FxHashSet<Symbol>,
54}
55
56pub enum ExpectedValues<T> {
57    Some(FxHashSet<Option<T>>),
58    Any,
59}
60
61impl<T: Eq + Hash> ExpectedValues<T> {
62    fn insert(&mut self, value: T) -> bool {
63        match self {
64            ExpectedValues::Some(expecteds) => expecteds.insert(Some(value)),
65            ExpectedValues::Any => false,
66        }
67    }
68
69    pub fn contains(&self, value: &Option<T>) -> bool {
70        match self {
71            ExpectedValues::Some(expecteds) => expecteds.contains(value),
72            ExpectedValues::Any => false,
73        }
74    }
75}
76
77impl<T: Eq + Hash> Extend<T> for ExpectedValues<T> {
78    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
79        match self {
80            ExpectedValues::Some(expecteds) => expecteds.extend(iter.into_iter().map(Some)),
81            ExpectedValues::Any => {}
82        }
83    }
84}
85
86impl<'a, T: Eq + Hash + Copy + 'a> Extend<&'a T> for ExpectedValues<T> {
87    fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
88        match self {
89            ExpectedValues::Some(expecteds) => expecteds.extend(iter.into_iter().map(|a| Some(*a))),
90            ExpectedValues::Any => {}
91        }
92    }
93}
94
95/// Disallow builtin cfgs from the CLI.
96pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
97    let disallow = |cfg: &(Symbol, Option<Symbol>), controlled_by| {
98        let cfg_name = cfg.0;
99        let cfg = if let Some(value) = cfg.1 {
100            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}=\"{1}\"", cfg_name, value))
    })format!(r#"{}="{}""#, cfg_name, value)
101        } else {
102            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}", cfg_name))
    })format!("{}", cfg_name)
103        };
104        sess.psess.opt_span_buffer_lint(
105            EXPLICIT_BUILTIN_CFGS_IN_FLAGS,
106            None,
107            ast::CRATE_NODE_ID,
108            diagnostics::UnexpectedBuiltinCfg { cfg, cfg_name, controlled_by }.into(),
109        )
110    };
111
112    // We want to restrict setting builtin cfgs that will produce incoherent behavior
113    // between the cfg and the rustc cli flag that sets it.
114    //
115    // The tests are in tests/ui/cfg/disallowed-cli-cfgs.rs.
116
117    // By-default all builtin cfgs are disallowed, only those are allowed:
118    //  - test: as it makes sense to the have the `test` cfg active without the builtin
119    //          test harness. See Cargo `harness = false` config.
120    //
121    // Cargo `--cfg test`: https://github.com/rust-lang/cargo/blob/bc89bffa5987d4af8f71011c7557119b39e44a65/src/cargo/core/compiler/mod.rs#L1124
122
123    for cfg in user_cfgs {
124        match cfg {
125            (sym::overflow_checks, None) => disallow(cfg, "-C overflow-checks"),
126            (sym::debug_assertions, None) => disallow(cfg, "-C debug-assertions"),
127            (sym::ub_checks, None) => disallow(cfg, "-Z ub-checks"),
128            (sym::contract_checks, None) => disallow(cfg, "-Z contract-checks"),
129            (sym::sanitize, None | Some(_)) => disallow(cfg, "-Z sanitizer"),
130            (
131                sym::sanitizer_cfi_generalize_pointers | sym::sanitizer_cfi_normalize_integers,
132                None | Some(_),
133            ) => disallow(cfg, "-Z sanitizer=cfi"),
134            (sym::proc_macro, None) => disallow(cfg, "--crate-type proc-macro"),
135            (sym::panic, Some(sym::abort | sym::unwind | sym::immediate_abort)) => {
136                disallow(cfg, "-C panic")
137            }
138            (sym::target_feature, Some(_)) => disallow(cfg, "-C target-feature"),
139            (sym::unix, None)
140            | (sym::windows, None)
141            | (sym::relocation_model, Some(_))
142            | (sym::target_abi, None | Some(_))
143            | (sym::target_arch, Some(_))
144            | (sym::target_endian, Some(_))
145            | (sym::target_env, None | Some(_))
146            | (sym::target_family, Some(_))
147            | (sym::target_object_format, Some(_))
148            | (sym::target_os, Some(_))
149            | (sym::target_pointer_width, Some(_))
150            | (sym::target_vendor, None | Some(_))
151            | (sym::target_has_atomic, Some(_))
152            | (sym::target_has_threads, None | Some(_))
153            | (sym::target_has_atomic_primitive_alignment, Some(_))
154            | (sym::target_has_atomic_load_store, Some(_))
155            | (sym::target_has_reliable_f16, None | Some(_))
156            | (sym::target_has_reliable_f16_math, None | Some(_))
157            | (sym::target_has_reliable_f16b, None | Some(_))
158            | (sym::target_has_reliable_f128, None | Some(_))
159            | (sym::target_has_reliable_f128_math, None | Some(_))
160            | (sym::target_thread_local, None) => disallow(cfg, "--target"),
161            (sym::fmt_debug, None | Some(_)) => disallow(cfg, "-Z fmt-debug"),
162            _ => {}
163        }
164    }
165}
166
167/// Generate the default configs for a given session
168pub(crate) fn default_configuration(sess: &Session) -> Cfg {
169    let mut ret = Cfg::default();
170
171    macro_rules! ins_none {
172        ($key:expr) => {
173            ret.insert(($key, None));
174        };
175    }
176    macro_rules! ins_str {
177        ($key:expr, $val_str:expr) => {
178            ret.insert(($key, Some(Symbol::intern($val_str))));
179        };
180    }
181    macro_rules! ins_sym {
182        ($key:expr, $val_sym:expr) => {
183            ret.insert(($key, Some($val_sym)));
184        };
185    }
186
187    // Symbols are inserted in alphabetical order as much as possible.
188    // The exceptions are where control flow forces things out of order.
189    //
190    // Run `rustc --print cfg` to see the configuration in practice.
191    //
192    // NOTE: These insertions should be kept in sync with
193    // `CheckCfg::fill_well_known` below.
194
195    if sess.opts.debug_assertions {
196        ret.insert((sym::debug_assertions, None));ins_none!(sym::debug_assertions);
197    }
198
199    if sess.is_nightly_build() {
200        match sess.opts.unstable_opts.fmt_debug {
201            FmtDebug::Full => {
202                ret.insert((sym::fmt_debug, Some(sym::full)));ins_sym!(sym::fmt_debug, sym::full);
203            }
204            FmtDebug::Shallow => {
205                ret.insert((sym::fmt_debug, Some(sym::shallow)));ins_sym!(sym::fmt_debug, sym::shallow);
206            }
207            FmtDebug::None => {
208                ret.insert((sym::fmt_debug, Some(sym::none)));ins_sym!(sym::fmt_debug, sym::none);
209            }
210        }
211    }
212
213    if sess.overflow_checks() {
214        ret.insert((sym::overflow_checks, None));ins_none!(sym::overflow_checks);
215    }
216
217    // We insert a cfg for the name of session's panic strategy.
218    // Since the ImmediateAbort strategy is new, it also sets cfg(panic="abort"), so that code
219    // which is trying to detect whether unwinding is enabled by checking for cfg(panic="abort")
220    // does not need to be updated.
221    ret.insert((sym::panic, Some(sess.panic_strategy().desc_symbol())));ins_sym!(sym::panic, sess.panic_strategy().desc_symbol());
222    if sess.panic_strategy() == PanicStrategy::ImmediateAbort {
223        ret.insert((sym::panic, Some(PanicStrategy::Abort.desc_symbol())));ins_sym!(sym::panic, PanicStrategy::Abort.desc_symbol());
224    }
225
226    // JUSTIFICATION: before wrapper fn is available
227    #[allow(rustc::bad_opt_access)]
228    if sess.opts.crate_types.contains(&CrateType::ProcMacro) {
229        ret.insert((sym::proc_macro, None));ins_none!(sym::proc_macro);
230    }
231
232    if sess.is_nightly_build() {
233        ret.insert((sym::relocation_model,
        Some(sess.target.relocation_model.desc_symbol())));ins_sym!(sym::relocation_model, sess.target.relocation_model.desc_symbol());
234    }
235
236    for mut s in sess.sanitizers() {
237        // KASAN is still ASAN under the hood, so it uses the same attribute.
238        if s == SanitizerSet::KERNELADDRESS {
239            s = SanitizerSet::ADDRESS;
240        }
241        // KHWASAN is still HWASAN under the hood, so it uses the same attribute.
242        if s == SanitizerSet::KERNELHWADDRESS {
243            s = SanitizerSet::HWADDRESS;
244        }
245        ret.insert((sym::sanitize, Some(Symbol::intern(&s.to_string()))));ins_str!(sym::sanitize, &s.to_string());
246    }
247
248    if sess.is_sanitizer_cfi_generalize_pointers_enabled() {
249        ret.insert((sym::sanitizer_cfi_generalize_pointers, None));ins_none!(sym::sanitizer_cfi_generalize_pointers);
250    }
251    if sess.is_sanitizer_cfi_normalize_integers_enabled() {
252        ret.insert((sym::sanitizer_cfi_normalize_integers, None));ins_none!(sym::sanitizer_cfi_normalize_integers);
253    }
254
255    ret.insert((sym::target_abi, Some(sess.target.cfg_abi.desc_symbol())));ins_sym!(sym::target_abi, sess.target.cfg_abi.desc_symbol());
256    ret.insert((sym::target_arch, Some(sess.target.arch.desc_symbol())));ins_sym!(sym::target_arch, sess.target.arch.desc_symbol());
257    ret.insert((sym::target_endian, Some(sess.target.endian.desc_symbol())));ins_sym!(sym::target_endian, sess.target.endian.desc_symbol());
258    ret.insert((sym::target_env, Some(sess.target.env.desc_symbol())));ins_sym!(sym::target_env, sess.target.env.desc_symbol());
259    ret.insert((sym::target_object_format,
        Some(sess.target.options.binary_format.desc_symbol())));ins_sym!(sym::target_object_format, sess.target.options.binary_format.desc_symbol());
260
261    for family in sess.target.families.as_ref() {
262        ret.insert((sym::target_family, Some(Symbol::intern(family))));ins_str!(sym::target_family, family);
263        if family == "windows" {
264            ret.insert((sym::windows, None));ins_none!(sym::windows);
265        } else if family == "unix" {
266            ret.insert((sym::unix, None));ins_none!(sym::unix);
267        }
268    }
269
270    // `target_has_atomic*`
271    let layout = sess.target.parse_data_layout().unwrap_or_else(|err| {
272        sess.dcx().emit_fatal(err);
273    });
274    let mut has_atomic = false;
275    for (i, align) in [
276        (8, layout.i8_align),
277        (16, layout.i16_align),
278        (32, layout.i32_align),
279        (64, layout.i64_align),
280        (128, layout.i128_align),
281    ] {
282        if i >= sess.target.min_atomic_width() && i <= sess.target.max_atomic_width() {
283            if !has_atomic {
284                has_atomic = true;
285                if sess.is_nightly_build() {
286                    if sess.target.atomic_cas {
287                        ret.insert((sym::target_has_atomic, None));ins_none!(sym::target_has_atomic);
288                    }
289                    ret.insert((sym::target_has_atomic_load_store, None));ins_none!(sym::target_has_atomic_load_store);
290                }
291            }
292            let mut insert_atomic = |sym, align: Align| {
293                if sess.target.atomic_cas {
294                    ret.insert((sym::target_has_atomic, Some(sym)));ins_sym!(sym::target_has_atomic, sym);
295                }
296                if align.bits() == i {
297                    ret.insert((sym::target_has_atomic_primitive_alignment, Some(sym)));ins_sym!(sym::target_has_atomic_primitive_alignment, sym);
298                }
299                ret.insert((sym::target_has_atomic_load_store, Some(sym)));ins_sym!(sym::target_has_atomic_load_store, sym);
300            };
301            insert_atomic(sym::integer(i), align);
302            if sess.target.pointer_width as u64 == i {
303                insert_atomic(sym::ptr, layout.pointer_align().abi);
304            }
305        }
306    }
307
308    if !sess.target.singlethread(&sess.internal_target_features) {
309        ret.insert((sym::target_has_threads, None));ins_none!(sym::target_has_threads);
310    }
311
312    ret.insert((sym::target_os, Some(sess.target.os.desc_symbol())));ins_sym!(sym::target_os, sess.target.os.desc_symbol());
313    ret.insert((sym::target_pointer_width,
        Some(sym::integer(sess.target.pointer_width))));ins_sym!(sym::target_pointer_width, sym::integer(sess.target.pointer_width));
314
315    if sess.opts.unstable_opts.has_thread_local.unwrap_or(sess.target.has_thread_local) {
316        ret.insert((sym::target_thread_local, None));ins_none!(sym::target_thread_local);
317    }
318
319    ret.insert((sym::target_vendor, Some(sess.target.vendor_symbol())));ins_sym!(sym::target_vendor, sess.target.vendor_symbol());
320
321    // If the user wants a test runner, then add the test cfg.
322    if sess.is_test_crate() {
323        ret.insert((sym::test, None));ins_none!(sym::test);
324    }
325
326    if sess.ub_checks() {
327        ret.insert((sym::ub_checks, None));ins_none!(sym::ub_checks);
328    }
329
330    if sess.contract_checks() {
331        ret.insert((sym::contract_checks, None));ins_none!(sym::contract_checks);
332    }
333
334    ret
335}
336
337impl CheckCfg {
338    /// Fill the current [`CheckCfg`] with all the well known cfgs
339    pub fn fill_well_known(&mut self, current_target: &Target) {
340        if !self.exhaustive_values && !self.exhaustive_names {
341            return;
342        }
343
344        // for `#[cfg(foo)]` (i.e. cfg value is none)
345        let no_values = || {
346            let mut values = FxHashSet::default();
347            values.insert(None);
348            ExpectedValues::Some(values)
349        };
350
351        // preparation for inserting some values
352        let empty_values = || {
353            let values = FxHashSet::default();
354            ExpectedValues::Some(values)
355        };
356
357        macro_rules! ins {
358            ($name:expr, $values:expr) => {{
359                self.well_known_names.insert($name);
360                self.expecteds.entry($name).or_insert_with($values)
361            }};
362        }
363
364        // Symbols are inserted in alphabetical order as much as possible.
365        // The exceptions are where control flow forces things out of order.
366        //
367        // NOTE: This should be kept in sync with `default_configuration`.
368        // Note that symbols inserted conditionally in `default_configuration`
369        // are inserted unconditionally here.
370        //
371        // One exception is the `test` cfg which is consider to be a "user-space"
372        // cfg, despite being also set by in `default_configuration` above.
373        // It allows the build system to "deny" using the config by not marking it
374        // as expected (e.g. `lib.test = false` for Cargo).
375        //
376        // When adding a new config here you should also update
377        // `tests/ui/check-cfg/well-known-values.rs` (in order to test the
378        // expected values of the new config) and bless the all directory.
379        //
380        // Don't forget to update `src/doc/rustc/src/check-cfg.md`
381        // in the unstable book as well!
382
383        {
    self.well_known_names.insert(sym::debug_assertions);
    self.expecteds.entry(sym::debug_assertions).or_insert_with(no_values)
};ins!(sym::debug_assertions, no_values);
384
385        {
    self.well_known_names.insert(sym::fmt_debug);
    self.expecteds.entry(sym::fmt_debug).or_insert_with(empty_values)
}ins!(sym::fmt_debug, empty_values).extend(FmtDebug::all());
386
387        // These four are never set by rustc, but we set them anyway; they
388        // should not trigger the lint because `cargo clippy`, `cargo doc`,
389        // `cargo test`, `cargo miri run` and `cargo fmt` (respectively)
390        // can set them.
391        {
    self.well_known_names.insert(sym::clippy);
    self.expecteds.entry(sym::clippy).or_insert_with(no_values)
};ins!(sym::clippy, no_values);
392        {
    self.well_known_names.insert(sym::doc);
    self.expecteds.entry(sym::doc).or_insert_with(no_values)
};ins!(sym::doc, no_values);
393        {
    self.well_known_names.insert(sym::doctest);
    self.expecteds.entry(sym::doctest).or_insert_with(no_values)
};ins!(sym::doctest, no_values);
394        {
    self.well_known_names.insert(sym::miri);
    self.expecteds.entry(sym::miri).or_insert_with(no_values)
};ins!(sym::miri, no_values);
395        {
    self.well_known_names.insert(sym::rust_analyzer);
    self.expecteds.entry(sym::rust_analyzer).or_insert_with(no_values)
};ins!(sym::rust_analyzer, no_values);
396        {
    self.well_known_names.insert(sym::rustfmt);
    self.expecteds.entry(sym::rustfmt).or_insert_with(no_values)
};ins!(sym::rustfmt, no_values);
397
398        {
    self.well_known_names.insert(sym::overflow_checks);
    self.expecteds.entry(sym::overflow_checks).or_insert_with(no_values)
};ins!(sym::overflow_checks, no_values);
399
400        {
    self.well_known_names.insert(sym::panic);
    self.expecteds.entry(sym::panic).or_insert_with(empty_values)
}ins!(sym::panic, empty_values)
401            .extend(PanicStrategy::ALL.iter().map(PanicStrategy::desc_symbol));
402
403        {
    self.well_known_names.insert(sym::proc_macro);
    self.expecteds.entry(sym::proc_macro).or_insert_with(no_values)
};ins!(sym::proc_macro, no_values);
404
405        {
    self.well_known_names.insert(sym::relocation_model);
    self.expecteds.entry(sym::relocation_model).or_insert_with(empty_values)
}ins!(sym::relocation_model, empty_values)
406            .extend(RelocModel::ALL.iter().map(RelocModel::desc_symbol));
407
408        let sanitize_values = SanitizerSet::all()
409            .into_iter()
410            .map(|sanitizer| Symbol::intern(sanitizer.as_str().unwrap()));
411        {
    self.well_known_names.insert(sym::sanitize);
    self.expecteds.entry(sym::sanitize).or_insert_with(empty_values)
}ins!(sym::sanitize, empty_values).extend(sanitize_values);
412
413        {
    self.well_known_names.insert(sym::sanitizer_cfi_generalize_pointers);
    self.expecteds.entry(sym::sanitizer_cfi_generalize_pointers).or_insert_with(no_values)
};ins!(sym::sanitizer_cfi_generalize_pointers, no_values);
414        {
    self.well_known_names.insert(sym::sanitizer_cfi_normalize_integers);
    self.expecteds.entry(sym::sanitizer_cfi_normalize_integers).or_insert_with(no_values)
};ins!(sym::sanitizer_cfi_normalize_integers, no_values);
415
416        {
    self.well_known_names.insert(sym::target_feature);
    self.expecteds.entry(sym::target_feature).or_insert_with(empty_values)
}ins!(sym::target_feature, empty_values).extend(
417            rustc_target::target_features::all_rust_features()
418                .filter(|(_, s)| s.in_cfg())
419                .map(|(f, _s)| f)
420                .chain(rustc_target::target_features::RUSTC_SPECIFIC_FEATURES.iter().cloned())
421                .map(Symbol::intern),
422        );
423
424        // sym::target_*
425        {
426            const VALUES: [&Symbol; 9] = [
427                &sym::target_abi,
428                &sym::target_arch,
429                &sym::target_endian,
430                &sym::target_env,
431                &sym::target_family,
432                &sym::target_object_format,
433                &sym::target_os,
434                &sym::target_pointer_width,
435                &sym::target_vendor,
436            ];
437
438            // Initialize (if not already initialized)
439            for &e in VALUES {
440                if !self.exhaustive_values {
441                    {
    self.well_known_names.insert(e);
    self.expecteds.entry(e).or_insert_with(|| ExpectedValues::Any)
};ins!(e, || ExpectedValues::Any);
442                } else {
443                    {
    self.well_known_names.insert(e);
    self.expecteds.entry(e).or_insert_with(empty_values)
};ins!(e, empty_values);
444                }
445            }
446
447            if self.exhaustive_values {
448                // Get all values map at once otherwise it would be costly.
449                // (8 values * 220 targets ~= 1760 times, at the time of writing this comment).
450                let [
451                    Some(values_target_abi),
452                    Some(values_target_arch),
453                    Some(values_target_endian),
454                    Some(values_target_env),
455                    Some(values_target_family),
456                    Some(values_target_object_format),
457                    Some(values_target_os),
458                    Some(values_target_pointer_width),
459                    Some(values_target_vendor),
460                ] = self.expecteds.get_disjoint_mut(VALUES)
461                else {
462                    {
    ::core::panicking::panic_fmt(format_args!("unable to get all the check-cfg values buckets"));
};panic!("unable to get all the check-cfg values buckets");
463                };
464
465                for target in Target::builtins().chain(iter::once(current_target.clone())) {
466                    values_target_abi.insert(target.options.cfg_abi.desc_symbol());
467                    values_target_arch.insert(target.arch.desc_symbol());
468                    values_target_endian.insert(target.options.endian.desc_symbol());
469                    values_target_env.insert(target.options.env.desc_symbol());
470                    values_target_family.extend(
471                        target.options.families.iter().map(|family| Symbol::intern(family)),
472                    );
473                    values_target_object_format.insert(target.options.binary_format.desc_symbol());
474                    values_target_os.insert(target.options.os.desc_symbol());
475                    values_target_pointer_width.insert(sym::integer(target.pointer_width));
476                    values_target_vendor.insert(target.vendor_symbol());
477                }
478            }
479        }
480
481        let atomic_values = &[
482            sym::ptr,
483            sym::integer(8usize),
484            sym::integer(16usize),
485            sym::integer(32usize),
486            sym::integer(64usize),
487            sym::integer(128usize),
488        ];
489        for sym in [sym::target_has_atomic, sym::target_has_atomic_load_store] {
490            {
    self.well_known_names.insert(sym);
    self.expecteds.entry(sym).or_insert_with(no_values)
}ins!(sym, no_values).extend(atomic_values);
491        }
492        {
    self.well_known_names.insert(sym::target_has_atomic_primitive_alignment);
    self.expecteds.entry(sym::target_has_atomic_primitive_alignment).or_insert_with(empty_values)
}ins!(sym::target_has_atomic_primitive_alignment, empty_values).extend(atomic_values);
493
494        {
    self.well_known_names.insert(sym::target_thread_local);
    self.expecteds.entry(sym::target_thread_local).or_insert_with(no_values)
};ins!(sym::target_thread_local, no_values);
495        {
    self.well_known_names.insert(sym::target_has_threads);
    self.expecteds.entry(sym::target_has_threads).or_insert_with(no_values)
};ins!(sym::target_has_threads, no_values);
496
497        {
    self.well_known_names.insert(sym::ub_checks);
    self.expecteds.entry(sym::ub_checks).or_insert_with(no_values)
};ins!(sym::ub_checks, no_values);
498        {
    self.well_known_names.insert(sym::contract_checks);
    self.expecteds.entry(sym::contract_checks).or_insert_with(no_values)
};ins!(sym::contract_checks, no_values);
499
500        {
    self.well_known_names.insert(sym::unix);
    self.expecteds.entry(sym::unix).or_insert_with(no_values)
};ins!(sym::unix, no_values);
501        {
    self.well_known_names.insert(sym::windows);
    self.expecteds.entry(sym::windows).or_insert_with(no_values)
};ins!(sym::windows, no_values);
502    }
503}