Skip to main content

rustc_session/
config.rs

1//! Contains infrastructure for configuring the compiler, including parsing
2//! command-line options.
3
4use std::collections::btree_map::{
5    Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
6};
7use std::collections::{BTreeMap, BTreeSet};
8use std::ffi::OsStr;
9use std::hash::Hash;
10use std::path::{Path, PathBuf};
11use std::str::{self, FromStr};
12use std::sync::LazyLock;
13use std::{cmp, fs, iter};
14
15use externs::{ExternOpt, split_extern_opt};
16use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
17use rustc_data_structures::stable_hasher::{StableHasher, StableOrd, ToStableHashKey};
18use rustc_errors::emitter::HumanReadableErrorType;
19use rustc_errors::{ColorConfig, DiagCtxtFlags};
20use rustc_feature::UnstableFeatures;
21use rustc_hashes::Hash64;
22use rustc_macros::{BlobDecodable, Decodable, Encodable, HashStable_Generic};
23use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION};
24use rustc_span::source_map::FilePathMapping;
25use rustc_span::{
26    FileName, HashStableContext, RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm,
27    Symbol, sym,
28};
29use rustc_target::spec::{
30    FramePointer, LinkSelfContainedComponents, LinkerFeatures, PanicStrategy, SplitDebuginfo,
31    Target, TargetTuple,
32};
33use tracing::debug;
34
35pub use crate::config::cfg::{Cfg, CheckCfg, ExpectedValues};
36use crate::config::native_libs::parse_native_libs;
37pub use crate::config::print_request::{PrintKind, PrintRequest};
38use crate::errors::FileWriteFail;
39pub use crate::options::*;
40use crate::search_paths::SearchPath;
41use crate::utils::CanonicalizedPath;
42use crate::{EarlyDiagCtxt, Session, filesearch, lint};
43
44mod cfg;
45mod externs;
46mod native_libs;
47mod print_request;
48pub mod sigpipe;
49
50/// The different settings that the `-C strip` flag can have.
51#[derive(#[automatically_derived]
impl ::core::clone::Clone for Strip {
    #[inline]
    fn clone(&self) -> Strip { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Strip { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for Strip {
    #[inline]
    fn eq(&self, other: &Strip) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for Strip {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Strip {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                Strip::None => "None",
                Strip::Debuginfo => "Debuginfo",
                Strip::Symbols => "Symbols",
            })
    }
}Debug)]
52pub enum Strip {
53    /// Do not strip at all.
54    None,
55
56    /// Strip debuginfo.
57    Debuginfo,
58
59    /// Strip all symbols.
60    Symbols,
61}
62
63/// The different settings that the `-C control-flow-guard` flag can have.
64#[derive(#[automatically_derived]
impl ::core::clone::Clone for CFGuard {
    #[inline]
    fn clone(&self) -> CFGuard { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for CFGuard { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for CFGuard {
    #[inline]
    fn eq(&self, other: &CFGuard) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for CFGuard {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for CFGuard {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                CFGuard::Disabled => "Disabled",
                CFGuard::NoChecks => "NoChecks",
                CFGuard::Checks => "Checks",
            })
    }
}Debug)]
65pub enum CFGuard {
66    /// Do not emit Control Flow Guard metadata or checks.
67    Disabled,
68
69    /// Emit Control Flow Guard metadata but no checks.
70    NoChecks,
71
72    /// Emit Control Flow Guard metadata and checks.
73    Checks,
74}
75
76/// The different settings that the `-Z cf-protection` flag can have.
77#[derive(#[automatically_derived]
impl ::core::clone::Clone for CFProtection {
    #[inline]
    fn clone(&self) -> CFProtection { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for CFProtection { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for CFProtection {
    #[inline]
    fn eq(&self, other: &CFProtection) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for CFProtection {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for CFProtection {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                CFProtection::None => "None",
                CFProtection::Branch => "Branch",
                CFProtection::Return => "Return",
                CFProtection::Full => "Full",
            })
    }
}Debug)]
78pub enum CFProtection {
79    /// Do not enable control-flow protection
80    None,
81
82    /// Emit control-flow protection for branches (enables indirect branch tracking).
83    Branch,
84
85    /// Emit control-flow protection for returns.
86    Return,
87
88    /// Emit control-flow protection for both branches and returns.
89    Full,
90}
91
92#[derive(#[automatically_derived]
impl ::core::clone::Clone for OptLevel {
    #[inline]
    fn clone(&self) -> OptLevel { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for OptLevel { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for OptLevel {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                OptLevel::No => "No",
                OptLevel::Less => "Less",
                OptLevel::More => "More",
                OptLevel::Aggressive => "Aggressive",
                OptLevel::Size => "Size",
                OptLevel::SizeMin => "SizeMin",
            })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for OptLevel {
    #[inline]
    fn eq(&self, other: &OptLevel) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for OptLevel {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for OptLevel where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    OptLevel::No => {}
                    OptLevel::Less => {}
                    OptLevel::More => {}
                    OptLevel::Aggressive => {}
                    OptLevel::Size => {}
                    OptLevel::SizeMin => {}
                }
            }
        }
    };HashStable_Generic, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for OptLevel {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        OptLevel::No => { 0usize }
                        OptLevel::Less => { 1usize }
                        OptLevel::More => { 2usize }
                        OptLevel::Aggressive => { 3usize }
                        OptLevel::Size => { 4usize }
                        OptLevel::SizeMin => { 5usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    OptLevel::No => {}
                    OptLevel::Less => {}
                    OptLevel::More => {}
                    OptLevel::Aggressive => {}
                    OptLevel::Size => {}
                    OptLevel::SizeMin => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for OptLevel {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { OptLevel::No }
                    1usize => { OptLevel::Less }
                    2usize => { OptLevel::More }
                    3usize => { OptLevel::Aggressive }
                    4usize => { OptLevel::Size }
                    5usize => { OptLevel::SizeMin }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `OptLevel`, expected 0..6, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
93pub enum OptLevel {
94    /// `-Copt-level=0`
95    No,
96    /// `-Copt-level=1`
97    Less,
98    /// `-Copt-level=2`
99    More,
100    /// `-Copt-level=3` / `-O`
101    Aggressive,
102    /// `-Copt-level=s`
103    Size,
104    /// `-Copt-level=z`
105    SizeMin,
106}
107
108/// This is what the `LtoCli` values get mapped to after resolving defaults and
109/// and taking other command line options into account.
110///
111/// Note that linker plugin-based LTO is a different mechanism entirely.
112#[derive(#[automatically_derived]
impl ::core::clone::Clone for Lto {
    #[inline]
    fn clone(&self) -> Lto {
        match self {
            Lto::No => Lto::No,
            Lto::Thin => Lto::Thin,
            Lto::ThinLocal => Lto::ThinLocal,
            Lto::Fat => Lto::Fat,
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Lto {
    #[inline]
    fn eq(&self, other: &Lto) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for Lto {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        Lto::No => { 0usize }
                        Lto::Thin => { 1usize }
                        Lto::ThinLocal => { 2usize }
                        Lto::Fat => { 3usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    Lto::No => {}
                    Lto::Thin => {}
                    Lto::ThinLocal => {}
                    Lto::Fat => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for Lto {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { Lto::No }
                    1usize => { Lto::Thin }
                    2usize => { Lto::ThinLocal }
                    3usize => { Lto::Fat }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Lto`, expected 0..4, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
113pub enum Lto {
114    /// Don't do any LTO whatsoever.
115    No,
116
117    /// Do a full-crate-graph (inter-crate) LTO with ThinLTO.
118    Thin,
119
120    /// Do a local ThinLTO (intra-crate, over the CodeGen Units of the local crate only). This is
121    /// only relevant if multiple CGUs are used.
122    ThinLocal,
123
124    /// Do a full-crate-graph (inter-crate) LTO with "fat" LTO.
125    Fat,
126}
127
128/// The different settings that the `-C lto` flag can have.
129#[derive(#[automatically_derived]
impl ::core::clone::Clone for LtoCli {
    #[inline]
    fn clone(&self) -> LtoCli { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for LtoCli { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for LtoCli {
    #[inline]
    fn eq(&self, other: &LtoCli) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for LtoCli {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for LtoCli {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                LtoCli::No => "No",
                LtoCli::Yes => "Yes",
                LtoCli::NoParam => "NoParam",
                LtoCli::Thin => "Thin",
                LtoCli::Fat => "Fat",
                LtoCli::Unspecified => "Unspecified",
            })
    }
}Debug)]
130pub enum LtoCli {
131    /// `-C lto=no`
132    No,
133    /// `-C lto=yes`
134    Yes,
135    /// `-C lto`
136    NoParam,
137    /// `-C lto=thin`
138    Thin,
139    /// `-C lto=fat`
140    Fat,
141    /// No `-C lto` flag passed
142    Unspecified,
143}
144
145/// The different settings that the `-C instrument-coverage` flag can have.
146#[derive(#[automatically_derived]
impl ::core::clone::Clone for InstrumentCoverage {
    #[inline]
    fn clone(&self) -> InstrumentCoverage { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for InstrumentCoverage { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for InstrumentCoverage {
    #[inline]
    fn eq(&self, other: &InstrumentCoverage) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for InstrumentCoverage {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for InstrumentCoverage {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                InstrumentCoverage::No => "No",
                InstrumentCoverage::Yes => "Yes",
            })
    }
}Debug)]
147pub enum InstrumentCoverage {
148    /// `-C instrument-coverage=no` (or `off`, `false` etc.)
149    No,
150    /// `-C instrument-coverage` or `-C instrument-coverage=yes`
151    Yes,
152}
153
154/// Individual flag values controlled by `-Zcoverage-options`.
155#[derive(#[automatically_derived]
impl ::core::clone::Clone for CoverageOptions {
    #[inline]
    fn clone(&self) -> CoverageOptions {
        let _: ::core::clone::AssertParamIsClone<CoverageLevel>;
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for CoverageOptions { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for CoverageOptions {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "CoverageOptions", "level", &self.level,
            "discard_all_spans_in_codegen",
            &&self.discard_all_spans_in_codegen)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for CoverageOptions {
    #[inline]
    fn eq(&self, other: &CoverageOptions) -> bool {
        self.discard_all_spans_in_codegen ==
                other.discard_all_spans_in_codegen &&
            self.level == other.level
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for CoverageOptions {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<CoverageLevel>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for CoverageOptions {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.level, state);
        ::core::hash::Hash::hash(&self.discard_all_spans_in_codegen, state)
    }
}Hash, #[automatically_derived]
impl ::core::default::Default for CoverageOptions {
    #[inline]
    fn default() -> CoverageOptions {
        CoverageOptions {
            level: ::core::default::Default::default(),
            discard_all_spans_in_codegen: ::core::default::Default::default(),
        }
    }
}Default)]
156pub struct CoverageOptions {
157    pub level: CoverageLevel,
158
159    /// **(internal test-only flag)**
160    /// `-Zcoverage-options=discard-all-spans-in-codegen`: During codegen,
161    /// discard all coverage spans as though they were invalid. Needed by
162    /// regression tests for #133606, because we don't have an easy way to
163    /// reproduce it from actual source code.
164    pub discard_all_spans_in_codegen: bool,
165}
166
167/// Controls whether branch coverage is enabled.
168#[derive(#[automatically_derived]
impl ::core::clone::Clone for CoverageLevel {
    #[inline]
    fn clone(&self) -> CoverageLevel { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for CoverageLevel { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for CoverageLevel {
    #[inline]
    fn eq(&self, other: &CoverageLevel) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for CoverageLevel {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for CoverageLevel {
    #[inline]
    fn partial_cmp(&self, other: &CoverageLevel)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for CoverageLevel {
    #[inline]
    fn cmp(&self, other: &CoverageLevel) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for CoverageLevel {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for CoverageLevel {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                CoverageLevel::Block => "Block",
                CoverageLevel::Branch => "Branch",
                CoverageLevel::Condition => "Condition",
            })
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for CoverageLevel {
    #[inline]
    fn default() -> CoverageLevel { Self::Block }
}Default)]
169pub enum CoverageLevel {
170    /// Instrument for coverage at the MIR block level.
171    #[default]
172    Block,
173    /// Also instrument branch points (includes block coverage).
174    Branch,
175    /// Same as branch coverage, but also adds branch instrumentation for
176    /// certain boolean expressions that are not directly used for branching.
177    ///
178    /// For example, in the following code, `b` does not directly participate
179    /// in a branch, but condition coverage will instrument it as its own
180    /// artificial branch:
181    /// ```
182    /// # let (a, b) = (false, true);
183    /// let x = a && b;
184    /// //           ^ last operand
185    /// ```
186    ///
187    /// This level is mainly intended to be a stepping-stone towards full MC/DC
188    /// instrumentation, so it might be removed in the future when MC/DC is
189    /// sufficiently complete, or if it is making MC/DC changes difficult.
190    Condition,
191}
192
193// The different settings that the `-Z offload` flag can have.
194#[derive(#[automatically_derived]
impl ::core::clone::Clone for Offload {
    #[inline]
    fn clone(&self) -> Offload {
        match self {
            Offload::Device => Offload::Device,
            Offload::Host(__self_0) =>
                Offload::Host(::core::clone::Clone::clone(__self_0)),
            Offload::Test => Offload::Test,
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for Offload {
    #[inline]
    fn eq(&self, other: &Offload) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (Offload::Host(__self_0), Offload::Host(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for Offload {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            Offload::Host(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Offload {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Offload::Device => ::core::fmt::Formatter::write_str(f, "Device"),
            Offload::Host(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Host",
                    &__self_0),
            Offload::Test => ::core::fmt::Formatter::write_str(f, "Test"),
        }
    }
}Debug, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for Offload {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        Offload::Device => { 0usize }
                        Offload::Host(ref __binding_0) => { 1usize }
                        Offload::Test => { 2usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    Offload::Device => {}
                    Offload::Host(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    Offload::Test => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for Offload {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { Offload::Device }
                    1usize => {
                        Offload::Host(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    2usize => { Offload::Test }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Offload`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
195pub enum Offload {
196    /// Entry point for `std::offload`, enables kernel compilation for a gpu device
197    Device,
198    /// Second step in the offload pipeline, generates the host code to call kernels.
199    Host(String),
200    /// Test is similar to Host, but allows testing without a device artifact.
201    Test,
202}
203
204/// The different settings that the `-Z autodiff` flag can have.
205#[derive(#[automatically_derived]
impl ::core::clone::Clone for AutoDiff {
    #[inline]
    fn clone(&self) -> AutoDiff {
        match self {
            AutoDiff::Enable => AutoDiff::Enable,
            AutoDiff::PrintTA => AutoDiff::PrintTA,
            AutoDiff::PrintTAFn(__self_0) =>
                AutoDiff::PrintTAFn(::core::clone::Clone::clone(__self_0)),
            AutoDiff::PrintAA => AutoDiff::PrintAA,
            AutoDiff::PrintPerf => AutoDiff::PrintPerf,
            AutoDiff::PrintSteps => AutoDiff::PrintSteps,
            AutoDiff::PrintModBefore => AutoDiff::PrintModBefore,
            AutoDiff::PrintModAfter => AutoDiff::PrintModAfter,
            AutoDiff::PrintModFinal => AutoDiff::PrintModFinal,
            AutoDiff::PrintPasses => AutoDiff::PrintPasses,
            AutoDiff::NoPostopt => AutoDiff::NoPostopt,
            AutoDiff::LooseTypes => AutoDiff::LooseTypes,
            AutoDiff::Inline => AutoDiff::Inline,
            AutoDiff::NoTT => AutoDiff::NoTT,
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for AutoDiff {
    #[inline]
    fn eq(&self, other: &AutoDiff) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (AutoDiff::PrintTAFn(__self_0), AutoDiff::PrintTAFn(__arg1_0))
                    => __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for AutoDiff {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            AutoDiff::PrintTAFn(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for AutoDiff {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            AutoDiff::Enable =>
                ::core::fmt::Formatter::write_str(f, "Enable"),
            AutoDiff::PrintTA =>
                ::core::fmt::Formatter::write_str(f, "PrintTA"),
            AutoDiff::PrintTAFn(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "PrintTAFn", &__self_0),
            AutoDiff::PrintAA =>
                ::core::fmt::Formatter::write_str(f, "PrintAA"),
            AutoDiff::PrintPerf =>
                ::core::fmt::Formatter::write_str(f, "PrintPerf"),
            AutoDiff::PrintSteps =>
                ::core::fmt::Formatter::write_str(f, "PrintSteps"),
            AutoDiff::PrintModBefore =>
                ::core::fmt::Formatter::write_str(f, "PrintModBefore"),
            AutoDiff::PrintModAfter =>
                ::core::fmt::Formatter::write_str(f, "PrintModAfter"),
            AutoDiff::PrintModFinal =>
                ::core::fmt::Formatter::write_str(f, "PrintModFinal"),
            AutoDiff::PrintPasses =>
                ::core::fmt::Formatter::write_str(f, "PrintPasses"),
            AutoDiff::NoPostopt =>
                ::core::fmt::Formatter::write_str(f, "NoPostopt"),
            AutoDiff::LooseTypes =>
                ::core::fmt::Formatter::write_str(f, "LooseTypes"),
            AutoDiff::Inline =>
                ::core::fmt::Formatter::write_str(f, "Inline"),
            AutoDiff::NoTT => ::core::fmt::Formatter::write_str(f, "NoTT"),
        }
    }
}Debug, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for AutoDiff {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        AutoDiff::Enable => { 0usize }
                        AutoDiff::PrintTA => { 1usize }
                        AutoDiff::PrintTAFn(ref __binding_0) => { 2usize }
                        AutoDiff::PrintAA => { 3usize }
                        AutoDiff::PrintPerf => { 4usize }
                        AutoDiff::PrintSteps => { 5usize }
                        AutoDiff::PrintModBefore => { 6usize }
                        AutoDiff::PrintModAfter => { 7usize }
                        AutoDiff::PrintModFinal => { 8usize }
                        AutoDiff::PrintPasses => { 9usize }
                        AutoDiff::NoPostopt => { 10usize }
                        AutoDiff::LooseTypes => { 11usize }
                        AutoDiff::Inline => { 12usize }
                        AutoDiff::NoTT => { 13usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    AutoDiff::Enable => {}
                    AutoDiff::PrintTA => {}
                    AutoDiff::PrintTAFn(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    AutoDiff::PrintAA => {}
                    AutoDiff::PrintPerf => {}
                    AutoDiff::PrintSteps => {}
                    AutoDiff::PrintModBefore => {}
                    AutoDiff::PrintModAfter => {}
                    AutoDiff::PrintModFinal => {}
                    AutoDiff::PrintPasses => {}
                    AutoDiff::NoPostopt => {}
                    AutoDiff::LooseTypes => {}
                    AutoDiff::Inline => {}
                    AutoDiff::NoTT => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for AutoDiff {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { AutoDiff::Enable }
                    1usize => { AutoDiff::PrintTA }
                    2usize => {
                        AutoDiff::PrintTAFn(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    3usize => { AutoDiff::PrintAA }
                    4usize => { AutoDiff::PrintPerf }
                    5usize => { AutoDiff::PrintSteps }
                    6usize => { AutoDiff::PrintModBefore }
                    7usize => { AutoDiff::PrintModAfter }
                    8usize => { AutoDiff::PrintModFinal }
                    9usize => { AutoDiff::PrintPasses }
                    10usize => { AutoDiff::NoPostopt }
                    11usize => { AutoDiff::LooseTypes }
                    12usize => { AutoDiff::Inline }
                    13usize => { AutoDiff::NoTT }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `AutoDiff`, expected 0..14, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
206pub enum AutoDiff {
207    /// Enable the autodiff opt pipeline
208    Enable,
209
210    /// Print TypeAnalysis information
211    PrintTA,
212    /// Print TypeAnalysis information for a specific function
213    PrintTAFn(String),
214    /// Print ActivityAnalysis Information
215    PrintAA,
216    /// Print Performance Warnings from Enzyme
217    PrintPerf,
218    /// Print intermediate IR generation steps
219    PrintSteps,
220    /// Print the module, before running autodiff.
221    PrintModBefore,
222    /// Print the module after running autodiff.
223    PrintModAfter,
224    /// Print the module after running autodiff and optimizations.
225    PrintModFinal,
226
227    /// Print all passes scheduled by LLVM
228    PrintPasses,
229    /// Disable extra opt run after running autodiff
230    NoPostopt,
231    /// Enzyme's loose type debug helper (can cause incorrect gradients!!)
232    /// Usable in cases where Enzyme errors with `can not deduce type of X`.
233    LooseTypes,
234    /// Runs Enzyme's aggressive inlining
235    Inline,
236    /// Disable Type Tree
237    NoTT,
238}
239
240/// The different settings that the `-Z annotate-moves` flag can have.
241#[derive(#[automatically_derived]
impl ::core::clone::Clone for AnnotateMoves {
    #[inline]
    fn clone(&self) -> AnnotateMoves {
        let _: ::core::clone::AssertParamIsClone<Option<u64>>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for AnnotateMoves { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for AnnotateMoves {
    #[inline]
    fn eq(&self, other: &AnnotateMoves) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (AnnotateMoves::Enabled(__self_0),
                    AnnotateMoves::Enabled(__arg1_0)) => __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for AnnotateMoves {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            AnnotateMoves::Enabled(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for AnnotateMoves {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            AnnotateMoves::Disabled =>
                ::core::fmt::Formatter::write_str(f, "Disabled"),
            AnnotateMoves::Enabled(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Enabled", &__self_0),
        }
    }
}Debug)]
242pub enum AnnotateMoves {
243    /// `-Z annotate-moves=no` (or `off`, `false` etc.)
244    Disabled,
245    /// `-Z annotate-moves` or `-Z annotate-moves=yes` (use default size limit)
246    /// `-Z annotate-moves=SIZE` (use specified size limit)
247    Enabled(Option<u64>),
248}
249
250/// Settings for `-Z instrument-xray` flag.
251#[derive(#[automatically_derived]
impl ::core::clone::Clone for InstrumentXRay {
    #[inline]
    fn clone(&self) -> InstrumentXRay {
        let _: ::core::clone::AssertParamIsClone<bool>;
        let _: ::core::clone::AssertParamIsClone<Option<usize>>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for InstrumentXRay { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for InstrumentXRay {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["always", "never", "ignore_loops", "instruction_threshold",
                        "skip_entry", "skip_exit"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.always, &self.never, &self.ignore_loops,
                        &self.instruction_threshold, &self.skip_entry,
                        &&self.skip_exit];
        ::core::fmt::Formatter::debug_struct_fields_finish(f,
            "InstrumentXRay", names, values)
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for InstrumentXRay {
    #[inline]
    fn default() -> InstrumentXRay {
        InstrumentXRay {
            always: ::core::default::Default::default(),
            never: ::core::default::Default::default(),
            ignore_loops: ::core::default::Default::default(),
            instruction_threshold: ::core::default::Default::default(),
            skip_entry: ::core::default::Default::default(),
            skip_exit: ::core::default::Default::default(),
        }
    }
}Default, #[automatically_derived]
impl ::core::cmp::PartialEq for InstrumentXRay {
    #[inline]
    fn eq(&self, other: &InstrumentXRay) -> bool {
        self.always == other.always && self.never == other.never &&
                        self.ignore_loops == other.ignore_loops &&
                    self.skip_entry == other.skip_entry &&
                self.skip_exit == other.skip_exit &&
            self.instruction_threshold == other.instruction_threshold
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for InstrumentXRay {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<bool>;
        let _: ::core::cmp::AssertParamIsEq<Option<usize>>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for InstrumentXRay {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.always, state);
        ::core::hash::Hash::hash(&self.never, state);
        ::core::hash::Hash::hash(&self.ignore_loops, state);
        ::core::hash::Hash::hash(&self.instruction_threshold, state);
        ::core::hash::Hash::hash(&self.skip_entry, state);
        ::core::hash::Hash::hash(&self.skip_exit, state)
    }
}Hash)]
252pub struct InstrumentXRay {
253    /// `-Z instrument-xray=always`, force instrumentation
254    pub always: bool,
255    /// `-Z instrument-xray=never`, disable instrumentation
256    pub never: bool,
257    /// `-Z instrument-xray=ignore-loops`, ignore presence of loops,
258    /// instrument functions based only on instruction count
259    pub ignore_loops: bool,
260    /// `-Z instrument-xray=instruction-threshold=N`, explicitly set instruction threshold
261    /// for instrumentation, or `None` to use compiler's default
262    pub instruction_threshold: Option<usize>,
263    /// `-Z instrument-xray=skip-entry`, do not instrument function entry
264    pub skip_entry: bool,
265    /// `-Z instrument-xray=skip-exit`, do not instrument function exit
266    pub skip_exit: bool,
267}
268
269#[derive(#[automatically_derived]
impl ::core::clone::Clone for LinkerPluginLto {
    #[inline]
    fn clone(&self) -> LinkerPluginLto {
        match self {
            LinkerPluginLto::LinkerPlugin(__self_0) =>
                LinkerPluginLto::LinkerPlugin(::core::clone::Clone::clone(__self_0)),
            LinkerPluginLto::LinkerPluginAuto =>
                LinkerPluginLto::LinkerPluginAuto,
            LinkerPluginLto::Disabled => LinkerPluginLto::Disabled,
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for LinkerPluginLto {
    #[inline]
    fn eq(&self, other: &LinkerPluginLto) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (LinkerPluginLto::LinkerPlugin(__self_0),
                    LinkerPluginLto::LinkerPlugin(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for LinkerPluginLto {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            LinkerPluginLto::LinkerPlugin(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for LinkerPluginLto {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            LinkerPluginLto::LinkerPlugin(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "LinkerPlugin", &__self_0),
            LinkerPluginLto::LinkerPluginAuto =>
                ::core::fmt::Formatter::write_str(f, "LinkerPluginAuto"),
            LinkerPluginLto::Disabled =>
                ::core::fmt::Formatter::write_str(f, "Disabled"),
        }
    }
}Debug)]
270pub enum LinkerPluginLto {
271    LinkerPlugin(PathBuf),
272    LinkerPluginAuto,
273    Disabled,
274}
275
276impl LinkerPluginLto {
277    pub fn enabled(&self) -> bool {
278        match *self {
279            LinkerPluginLto::LinkerPlugin(_) | LinkerPluginLto::LinkerPluginAuto => true,
280            LinkerPluginLto::Disabled => false,
281        }
282    }
283}
284
285/// The different values `-C link-self-contained` can take: a list of individually enabled or
286/// disabled components used during linking, coming from the rustc distribution, instead of being
287/// found somewhere on the host system.
288///
289/// They can be set in bulk via `-C link-self-contained=yes|y|on` or `-C
290/// link-self-contained=no|n|off`, and those boolean values are the historical defaults.
291///
292/// But each component is fine-grained, and can be unstably targeted, to use:
293/// - some CRT objects
294/// - the libc static library
295/// - libgcc/libunwind libraries
296/// - a linker we distribute
297/// - some sanitizer runtime libraries
298/// - all other MinGW libraries and Windows import libs
299///
300#[derive(#[automatically_derived]
impl ::core::default::Default for LinkSelfContained {
    #[inline]
    fn default() -> LinkSelfContained {
        LinkSelfContained {
            explicitly_set: ::core::default::Default::default(),
            enabled_components: ::core::default::Default::default(),
            disabled_components: ::core::default::Default::default(),
        }
    }
}Default, #[automatically_derived]
impl ::core::clone::Clone for LinkSelfContained {
    #[inline]
    fn clone(&self) -> LinkSelfContained {
        LinkSelfContained {
            explicitly_set: ::core::clone::Clone::clone(&self.explicitly_set),
            enabled_components: ::core::clone::Clone::clone(&self.enabled_components),
            disabled_components: ::core::clone::Clone::clone(&self.disabled_components),
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for LinkSelfContained {
    #[inline]
    fn eq(&self, other: &LinkSelfContained) -> bool {
        self.explicitly_set == other.explicitly_set &&
                self.enabled_components == other.enabled_components &&
            self.disabled_components == other.disabled_components
    }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for LinkSelfContained {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "LinkSelfContained", "explicitly_set", &self.explicitly_set,
            "enabled_components", &self.enabled_components,
            "disabled_components", &&self.disabled_components)
    }
}Debug)]
301pub struct LinkSelfContained {
302    /// Whether the user explicitly set `-C link-self-contained` on or off, the historical values.
303    /// Used for compatibility with the existing opt-in and target inference.
304    pub explicitly_set: Option<bool>,
305
306    /// The components that are enabled on the CLI, using the `+component` syntax or one of the
307    /// `true` shortcuts.
308    enabled_components: LinkSelfContainedComponents,
309
310    /// The components that are disabled on the CLI, using the `-component` syntax or one of the
311    /// `false` shortcuts.
312    disabled_components: LinkSelfContainedComponents,
313}
314
315impl LinkSelfContained {
316    /// Incorporates an enabled or disabled component as specified on the CLI, if possible.
317    /// For example: `+linker`, and `-crto`.
318    pub(crate) fn handle_cli_component(&mut self, component: &str) -> Option<()> {
319        // Note that for example `-Cself-contained=y -Cself-contained=-linker` is not an explicit
320        // set of all values like `y` or `n` used to be. Therefore, if this flag had previously been
321        // set in bulk with its historical values, then manually setting a component clears that
322        // `explicitly_set` state.
323        if let Some(component_to_enable) = component.strip_prefix('+') {
324            self.explicitly_set = None;
325            self.enabled_components
326                .insert(LinkSelfContainedComponents::from_str(component_to_enable).ok()?);
327            Some(())
328        } else if let Some(component_to_disable) = component.strip_prefix('-') {
329            self.explicitly_set = None;
330            self.disabled_components
331                .insert(LinkSelfContainedComponents::from_str(component_to_disable).ok()?);
332            Some(())
333        } else {
334            None
335        }
336    }
337
338    /// Turns all components on or off and records that this was done explicitly for compatibility
339    /// purposes.
340    pub(crate) fn set_all_explicitly(&mut self, enabled: bool) {
341        self.explicitly_set = Some(enabled);
342
343        if enabled {
344            self.enabled_components = LinkSelfContainedComponents::all();
345            self.disabled_components = LinkSelfContainedComponents::empty();
346        } else {
347            self.enabled_components = LinkSelfContainedComponents::empty();
348            self.disabled_components = LinkSelfContainedComponents::all();
349        }
350    }
351
352    /// Helper creating a fully enabled `LinkSelfContained` instance. Used in tests.
353    pub fn on() -> Self {
354        let mut on = LinkSelfContained::default();
355        on.set_all_explicitly(true);
356        on
357    }
358
359    /// To help checking CLI usage while some of the values are unstable: returns whether one of the
360    /// unstable components was set individually, for the given `TargetTuple`. This would also
361    /// require the `-Zunstable-options` flag, to be allowed.
362    fn check_unstable_variants(&self, target_tuple: &TargetTuple) -> Result<(), String> {
363        if self.explicitly_set.is_some() {
364            return Ok(());
365        }
366
367        // `-C link-self-contained=-linker` is only stable on x64 linux.
368        let has_minus_linker = self.disabled_components.is_linker_enabled();
369        if has_minus_linker && target_tuple.tuple() != "x86_64-unknown-linux-gnu" {
370            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`-C link-self-contained=-linker` is unstable on the `{0}` target. The `-Z unstable-options` flag must also be passed to use it on this target",
                target_tuple))
    })format!(
371                "`-C link-self-contained=-linker` is unstable on the `{target_tuple}` \
372                    target. The `-Z unstable-options` flag must also be passed to use it on this target",
373            ));
374        }
375
376        // Any `+linker` or other component used is unstable, and that's an error.
377        let unstable_enabled = self.enabled_components;
378        let unstable_disabled = self.disabled_components - LinkSelfContainedComponents::LINKER;
379        if !unstable_enabled.union(unstable_disabled).is_empty() {
380            return Err(String::from(
381                "only `-C link-self-contained` values `y`/`yes`/`on`/`n`/`no`/`off`/`-linker` \
382                are stable, the `-Z unstable-options` flag must also be passed to use \
383                the unstable values",
384            ));
385        }
386
387        Ok(())
388    }
389
390    /// Returns whether the self-contained linker component was enabled on the CLI, using the
391    /// `-C link-self-contained=+linker` syntax, or one of the `true` shortcuts.
392    pub fn is_linker_enabled(&self) -> bool {
393        self.enabled_components.contains(LinkSelfContainedComponents::LINKER)
394    }
395
396    /// Returns whether the self-contained linker component was disabled on the CLI, using the
397    /// `-C link-self-contained=-linker` syntax, or one of the `false` shortcuts.
398    pub fn is_linker_disabled(&self) -> bool {
399        self.disabled_components.contains(LinkSelfContainedComponents::LINKER)
400    }
401
402    /// Returns CLI inconsistencies to emit errors: individual components were both enabled and
403    /// disabled.
404    fn check_consistency(&self) -> Option<LinkSelfContainedComponents> {
405        if self.explicitly_set.is_some() {
406            None
407        } else {
408            let common = self.enabled_components.intersection(self.disabled_components);
409            if common.is_empty() { None } else { Some(common) }
410        }
411    }
412}
413
414/// The different values that `-C linker-features` can take on the CLI: a list of individually
415/// enabled or disabled features used during linking.
416///
417/// There is no need to enable or disable them in bulk. Each feature is fine-grained, and can be
418/// used to turn `LinkerFeatures` on or off, without needing to change the linker flavor:
419/// - using the system lld, or the self-contained `rust-lld` linker
420/// - using a C/C++ compiler to drive the linker (not yet exposed on the CLI)
421/// - etc.
422#[derive(#[automatically_derived]
impl ::core::default::Default for LinkerFeaturesCli {
    #[inline]
    fn default() -> LinkerFeaturesCli {
        LinkerFeaturesCli {
            enabled: ::core::default::Default::default(),
            disabled: ::core::default::Default::default(),
        }
    }
}Default, #[automatically_derived]
impl ::core::marker::Copy for LinkerFeaturesCli { }Copy, #[automatically_derived]
impl ::core::clone::Clone for LinkerFeaturesCli {
    #[inline]
    fn clone(&self) -> LinkerFeaturesCli {
        let _: ::core::clone::AssertParamIsClone<LinkerFeatures>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for LinkerFeaturesCli {
    #[inline]
    fn eq(&self, other: &LinkerFeaturesCli) -> bool {
        self.enabled == other.enabled && self.disabled == other.disabled
    }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for LinkerFeaturesCli {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "LinkerFeaturesCli", "enabled", &self.enabled, "disabled",
            &&self.disabled)
    }
}Debug)]
423pub struct LinkerFeaturesCli {
424    /// The linker features that are enabled on the CLI, using the `+feature` syntax.
425    pub enabled: LinkerFeatures,
426
427    /// The linker features that are disabled on the CLI, using the `-feature` syntax.
428    pub disabled: LinkerFeatures,
429}
430
431impl LinkerFeaturesCli {
432    /// Accumulates an enabled or disabled feature as specified on the CLI, if possible.
433    /// For example: `+lld`, and `-lld`.
434    pub(crate) fn handle_cli_feature(&mut self, feature: &str) -> Option<()> {
435        // Duplicate flags are reduced as we go, the last occurrence wins:
436        // `+feature,-feature,+feature` only enables the feature, and does not record it as both
437        // enabled and disabled on the CLI.
438        // We also only expose `+/-lld` at the moment, as it's currently the only implemented linker
439        // feature and toggling `LinkerFeatures::CC` would be a noop.
440        match feature {
441            "+lld" => {
442                self.enabled.insert(LinkerFeatures::LLD);
443                self.disabled.remove(LinkerFeatures::LLD);
444                Some(())
445            }
446            "-lld" => {
447                self.disabled.insert(LinkerFeatures::LLD);
448                self.enabled.remove(LinkerFeatures::LLD);
449                Some(())
450            }
451            _ => None,
452        }
453    }
454
455    /// When *not* using `-Z unstable-options` on the CLI, ensure only stable linker features are
456    /// used, for the given `TargetTuple`. Returns `Ok` if no unstable variants are used.
457    /// The caller should ensure that e.g. `nightly_options::is_unstable_enabled()`
458    /// returns false.
459    pub(crate) fn check_unstable_variants(&self, target_tuple: &TargetTuple) -> Result<(), String> {
460        // `-C linker-features=-lld` is only stable on x64 linux.
461        let has_minus_lld = self.disabled.is_lld_enabled();
462        if has_minus_lld && target_tuple.tuple() != "x86_64-unknown-linux-gnu" {
463            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`-C linker-features=-lld` is unstable on the `{0}` target. The `-Z unstable-options` flag must also be passed to use it on this target",
                target_tuple))
    })format!(
464                "`-C linker-features=-lld` is unstable on the `{target_tuple}` \
465                    target. The `-Z unstable-options` flag must also be passed to use it on this target",
466            ));
467        }
468
469        // Any `+lld` or non-lld feature used is unstable, and that's an error.
470        let unstable_enabled = self.enabled;
471        let unstable_disabled = self.disabled - LinkerFeatures::LLD;
472        if !unstable_enabled.union(unstable_disabled).is_empty() {
473            let unstable_features: Vec<_> = unstable_enabled
474                .iter()
475                .map(|f| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("+{0}", f.as_str().unwrap()))
    })format!("+{}", f.as_str().unwrap()))
476                .chain(unstable_disabled.iter().map(|f| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("-{0}", f.as_str().unwrap()))
    })format!("-{}", f.as_str().unwrap())))
477                .collect();
478            return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`-C linker-features={0}` is unstable, and also requires the `-Z unstable-options` flag to be used",
                unstable_features.join(",")))
    })format!(
479                "`-C linker-features={}` is unstable, and also requires the \
480                `-Z unstable-options` flag to be used",
481                unstable_features.join(","),
482            ));
483        }
484
485        Ok(())
486    }
487}
488
489/// Used with `-Z assert-incr-state`.
490#[derive(#[automatically_derived]
impl ::core::clone::Clone for IncrementalStateAssertion {
    #[inline]
    fn clone(&self) -> IncrementalStateAssertion { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for IncrementalStateAssertion { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for IncrementalStateAssertion {
    #[inline]
    fn eq(&self, other: &IncrementalStateAssertion) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for IncrementalStateAssertion {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for IncrementalStateAssertion {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                IncrementalStateAssertion::Loaded => "Loaded",
                IncrementalStateAssertion::NotLoaded => "NotLoaded",
            })
    }
}Debug)]
491pub enum IncrementalStateAssertion {
492    /// Found and loaded an existing session directory.
493    ///
494    /// Note that this says nothing about whether any particular query
495    /// will be found to be red or green.
496    Loaded,
497    /// Did not load an existing session directory.
498    NotLoaded,
499}
500
501/// The different settings that can be enabled via the `-Z location-detail` flag.
502#[derive(#[automatically_derived]
impl ::core::marker::Copy for LocationDetail { }Copy, #[automatically_derived]
impl ::core::clone::Clone for LocationDetail {
    #[inline]
    fn clone(&self) -> LocationDetail {
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for LocationDetail {
    #[inline]
    fn eq(&self, other: &LocationDetail) -> bool {
        self.file == other.file && self.line == other.line &&
            self.column == other.column
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for LocationDetail {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.file, state);
        ::core::hash::Hash::hash(&self.line, state);
        ::core::hash::Hash::hash(&self.column, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for LocationDetail {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "LocationDetail", "file", &self.file, "line", &self.line,
            "column", &&self.column)
    }
}Debug)]
503pub struct LocationDetail {
504    pub file: bool,
505    pub line: bool,
506    pub column: bool,
507}
508
509impl LocationDetail {
510    pub(crate) fn all() -> Self {
511        Self { file: true, line: true, column: true }
512    }
513}
514
515/// Values for the `-Z fmt-debug` flag.
516#[derive(#[automatically_derived]
impl ::core::marker::Copy for FmtDebug { }Copy, #[automatically_derived]
impl ::core::clone::Clone for FmtDebug {
    #[inline]
    fn clone(&self) -> FmtDebug { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for FmtDebug {
    #[inline]
    fn eq(&self, other: &FmtDebug) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for FmtDebug {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for FmtDebug {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                FmtDebug::Full => "Full",
                FmtDebug::Shallow => "Shallow",
                FmtDebug::None => "None",
            })
    }
}Debug)]
517pub enum FmtDebug {
518    /// Derive fully-featured implementation
519    Full,
520    /// Print only type name, without fields
521    Shallow,
522    /// `#[derive(Debug)]` and `{:?}` are no-ops
523    None,
524}
525
526impl FmtDebug {
527    pub(crate) fn all() -> [Symbol; 3] {
528        [sym::full, sym::none, sym::shallow]
529    }
530}
531
532#[derive(#[automatically_derived]
impl ::core::clone::Clone for SwitchWithOptPath {
    #[inline]
    fn clone(&self) -> SwitchWithOptPath {
        match self {
            SwitchWithOptPath::Enabled(__self_0) =>
                SwitchWithOptPath::Enabled(::core::clone::Clone::clone(__self_0)),
            SwitchWithOptPath::Disabled => SwitchWithOptPath::Disabled,
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for SwitchWithOptPath {
    #[inline]
    fn eq(&self, other: &SwitchWithOptPath) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (SwitchWithOptPath::Enabled(__self_0),
                    SwitchWithOptPath::Enabled(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for SwitchWithOptPath {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            SwitchWithOptPath::Enabled(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for SwitchWithOptPath {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            SwitchWithOptPath::Enabled(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Enabled", &__self_0),
            SwitchWithOptPath::Disabled =>
                ::core::fmt::Formatter::write_str(f, "Disabled"),
        }
    }
}Debug, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for SwitchWithOptPath {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        SwitchWithOptPath::Enabled(ref __binding_0) => { 0usize }
                        SwitchWithOptPath::Disabled => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    SwitchWithOptPath::Enabled(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SwitchWithOptPath::Disabled => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for SwitchWithOptPath {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        SwitchWithOptPath::Enabled(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => { SwitchWithOptPath::Disabled }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `SwitchWithOptPath`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
533pub enum SwitchWithOptPath {
534    Enabled(Option<PathBuf>),
535    Disabled,
536}
537
538impl SwitchWithOptPath {
539    pub fn enabled(&self) -> bool {
540        match *self {
541            SwitchWithOptPath::Enabled(_) => true,
542            SwitchWithOptPath::Disabled => false,
543        }
544    }
545}
546
547#[derive(#[automatically_derived]
impl ::core::marker::Copy for SymbolManglingVersion { }Copy, #[automatically_derived]
impl ::core::clone::Clone for SymbolManglingVersion {
    #[inline]
    fn clone(&self) -> SymbolManglingVersion { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for SymbolManglingVersion {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                SymbolManglingVersion::Legacy => "Legacy",
                SymbolManglingVersion::V0 => "V0",
                SymbolManglingVersion::Hashed => "Hashed",
            })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for SymbolManglingVersion {
    #[inline]
    fn eq(&self, other: &SymbolManglingVersion) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for SymbolManglingVersion {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for SymbolManglingVersion {
    #[inline]
    fn partial_cmp(&self, other: &SymbolManglingVersion)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for SymbolManglingVersion {
    #[inline]
    fn cmp(&self, other: &SymbolManglingVersion) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for SymbolManglingVersion {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for SymbolManglingVersion where
            __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    SymbolManglingVersion::Legacy => {}
                    SymbolManglingVersion::V0 => {}
                    SymbolManglingVersion::Hashed => {}
                }
            }
        }
    };HashStable_Generic)]
548#[derive(const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for SymbolManglingVersion {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        SymbolManglingVersion::Legacy => { 0usize }
                        SymbolManglingVersion::V0 => { 1usize }
                        SymbolManglingVersion::Hashed => { 2usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    SymbolManglingVersion::Legacy => {}
                    SymbolManglingVersion::V0 => {}
                    SymbolManglingVersion::Hashed => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::BlobDecoder> ::rustc_serialize::Decodable<__D>
            for SymbolManglingVersion {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { SymbolManglingVersion::Legacy }
                    1usize => { SymbolManglingVersion::V0 }
                    2usize => { SymbolManglingVersion::Hashed }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `SymbolManglingVersion`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };BlobDecodable)]
549pub enum SymbolManglingVersion {
550    Legacy,
551    V0,
552    Hashed,
553}
554
555#[derive(#[automatically_derived]
impl ::core::clone::Clone for DebugInfo {
    #[inline]
    fn clone(&self) -> DebugInfo { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for DebugInfo { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for DebugInfo {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                DebugInfo::None => "None",
                DebugInfo::LineDirectivesOnly => "LineDirectivesOnly",
                DebugInfo::LineTablesOnly => "LineTablesOnly",
                DebugInfo::Limited => "Limited",
                DebugInfo::Full => "Full",
            })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for DebugInfo {
    #[inline]
    fn eq(&self, other: &DebugInfo) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for DebugInfo {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash)]
556pub enum DebugInfo {
557    None,
558    LineDirectivesOnly,
559    LineTablesOnly,
560    Limited,
561    Full,
562}
563
564#[derive(#[automatically_derived]
impl ::core::clone::Clone for DebugInfoCompression {
    #[inline]
    fn clone(&self) -> DebugInfoCompression { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for DebugInfoCompression { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for DebugInfoCompression {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                DebugInfoCompression::None => "None",
                DebugInfoCompression::Zlib => "Zlib",
                DebugInfoCompression::Zstd => "Zstd",
            })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for DebugInfoCompression {
    #[inline]
    fn eq(&self, other: &DebugInfoCompression) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for DebugInfoCompression {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash)]
565pub enum DebugInfoCompression {
566    None,
567    Zlib,
568    Zstd,
569}
570
571#[derive(#[automatically_derived]
impl ::core::clone::Clone for MirStripDebugInfo {
    #[inline]
    fn clone(&self) -> MirStripDebugInfo { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for MirStripDebugInfo { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for MirStripDebugInfo {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                MirStripDebugInfo::None => "None",
                MirStripDebugInfo::LocalsInTinyFunctions =>
                    "LocalsInTinyFunctions",
                MirStripDebugInfo::AllLocals => "AllLocals",
            })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for MirStripDebugInfo {
    #[inline]
    fn eq(&self, other: &MirStripDebugInfo) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for MirStripDebugInfo {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash)]
572pub enum MirStripDebugInfo {
573    None,
574    LocalsInTinyFunctions,
575    AllLocals,
576}
577
578/// Split debug-information is enabled by `-C split-debuginfo`, this enum is only used if split
579/// debug-information is enabled (in either `Packed` or `Unpacked` modes), and the platform
580/// uses DWARF for debug-information.
581///
582/// Some debug-information requires link-time relocation and some does not. LLVM can partition
583/// the debuginfo into sections depending on whether or not it requires link-time relocation. Split
584/// DWARF provides a mechanism which allows the linker to skip the sections which don't require
585/// link-time relocation - either by putting those sections in DWARF object files, or by keeping
586/// them in the object file in such a way that the linker will skip them.
587#[derive(#[automatically_derived]
impl ::core::clone::Clone for SplitDwarfKind {
    #[inline]
    fn clone(&self) -> SplitDwarfKind { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for SplitDwarfKind { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for SplitDwarfKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                SplitDwarfKind::Single => "Single",
                SplitDwarfKind::Split => "Split",
            })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for SplitDwarfKind {
    #[inline]
    fn eq(&self, other: &SplitDwarfKind) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for SplitDwarfKind {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for SplitDwarfKind {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        SplitDwarfKind::Single => { 0usize }
                        SplitDwarfKind::Split => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    SplitDwarfKind::Single => {}
                    SplitDwarfKind::Split => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for SplitDwarfKind {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { SplitDwarfKind::Single }
                    1usize => { SplitDwarfKind::Split }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `SplitDwarfKind`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
588pub enum SplitDwarfKind {
589    /// Sections which do not require relocation are written into object file but ignored by the
590    /// linker.
591    Single,
592    /// Sections which do not require relocation are written into a DWARF object (`.dwo`) file
593    /// which is ignored by the linker.
594    Split,
595}
596
597impl FromStr for SplitDwarfKind {
598    type Err = ();
599
600    fn from_str(s: &str) -> Result<Self, ()> {
601        Ok(match s {
602            "single" => SplitDwarfKind::Single,
603            "split" => SplitDwarfKind::Split,
604            _ => return Err(()),
605        })
606    }
607}
608
609macro_rules! define_output_types {
610    (
611        $(
612            $(#[doc = $doc:expr])*
613            $Variant:ident => {
614                shorthand: $shorthand:expr,
615                extension: $extension:expr,
616                description: $description:expr,
617                default_filename: $default_filename:expr,
618                is_text: $is_text:expr,
619                compatible_with_cgus_and_single_output: $compatible:expr
620            }
621        ),* $(,)?
622    ) => {
623        #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, HashStable_Generic)]
624        #[derive(Encodable, Decodable)]
625        pub enum OutputType {
626            $(
627                $(#[doc = $doc])*
628                $Variant,
629            )*
630        }
631
632
633        impl StableOrd for OutputType {
634            const CAN_USE_UNSTABLE_SORT: bool = true;
635
636            // Trivial C-Style enums have a stable sort order across compilation sessions.
637            const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
638        }
639
640        impl<Hcx: HashStableContext> ToStableHashKey<Hcx> for OutputType {
641            type KeyType = Self;
642
643            fn to_stable_hash_key(&self, _: &mut Hcx) -> Self::KeyType {
644                *self
645            }
646        }
647
648
649        impl OutputType {
650            pub fn iter_all() -> impl Iterator<Item = OutputType> {
651                static ALL_VARIANTS: &[OutputType] = &[
652                    $(
653                        OutputType::$Variant,
654                    )*
655                ];
656                ALL_VARIANTS.iter().copied()
657            }
658
659            fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
660                match *self {
661                    $(
662                        OutputType::$Variant => $compatible,
663                    )*
664                }
665            }
666
667            pub fn shorthand(&self) -> &'static str {
668                match *self {
669                    $(
670                        OutputType::$Variant => $shorthand,
671                    )*
672                }
673            }
674
675            fn from_shorthand(shorthand: &str) -> Option<Self> {
676                match shorthand {
677                    $(
678                        s if s == $shorthand => Some(OutputType::$Variant),
679                    )*
680                    _ => None,
681                }
682            }
683
684            fn shorthands_display() -> String {
685                let shorthands = vec![
686                    $(
687                        format!("`{}`", $shorthand),
688                    )*
689                ];
690                shorthands.join(", ")
691            }
692
693            pub fn extension(&self) -> &'static str {
694                match *self {
695                    $(
696                        OutputType::$Variant => $extension,
697                    )*
698                }
699            }
700
701            pub fn is_text_output(&self) -> bool {
702                match *self {
703                    $(
704                        OutputType::$Variant => $is_text,
705                    )*
706                }
707            }
708
709            pub fn description(&self) -> &'static str {
710                match *self {
711                    $(
712                        OutputType::$Variant => $description,
713                    )*
714                }
715            }
716
717            pub fn default_filename(&self) -> &'static str {
718                match *self {
719                    $(
720                        OutputType::$Variant => $default_filename,
721                    )*
722                }
723            }
724
725
726        }
727    }
728}
729
730#[automatically_derived]
impl ::core::clone::Clone for OutputType {
    #[inline]
    fn clone(&self) -> OutputType { *self }
}
#[automatically_derived]
impl ::core::marker::Copy for OutputType { }
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for OutputType { }
#[automatically_derived]
impl ::core::cmp::PartialEq for OutputType {
    #[inline]
    fn eq(&self, other: &OutputType) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}
#[automatically_derived]
impl ::core::cmp::Eq for OutputType {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}
#[automatically_derived]
impl ::core::hash::Hash for OutputType {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}
#[automatically_derived]
impl ::core::fmt::Debug for OutputType {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                OutputType::Assembly => "Assembly",
                OutputType::Bitcode => "Bitcode",
                OutputType::DepInfo => "DepInfo",
                OutputType::Exe => "Exe",
                OutputType::LlvmAssembly => "LlvmAssembly",
                OutputType::Metadata => "Metadata",
                OutputType::Mir => "Mir",
                OutputType::Object => "Object",
                OutputType::ThinLinkBitcode => "ThinLinkBitcode",
            })
    }
}
#[automatically_derived]
impl ::core::cmp::PartialOrd for OutputType {
    #[inline]
    fn partial_cmp(&self, other: &OutputType)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}
#[automatically_derived]
impl ::core::cmp::Ord for OutputType {
    #[inline]
    fn cmp(&self, other: &OutputType) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}
const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for OutputType where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    OutputType::Assembly => {}
                    OutputType::Bitcode => {}
                    OutputType::DepInfo => {}
                    OutputType::Exe => {}
                    OutputType::LlvmAssembly => {}
                    OutputType::Metadata => {}
                    OutputType::Mir => {}
                    OutputType::Object => {}
                    OutputType::ThinLinkBitcode => {}
                }
            }
        }
    };
impl StableOrd for OutputType {
    const CAN_USE_UNSTABLE_SORT: bool = true;
    const THIS_IMPLEMENTATION_HAS_BEEN_TRIPLE_CHECKED: () = ();
}
impl<Hcx: HashStableContext> ToStableHashKey<Hcx> for OutputType {
    type KeyType = Self;
    fn to_stable_hash_key(&self, _: &mut Hcx) -> Self::KeyType { *self }
}
impl OutputType {
    pub fn iter_all() -> impl Iterator<Item = OutputType> {
        static ALL_VARIANTS: &[OutputType] =
            &[OutputType::Assembly, OutputType::Bitcode, OutputType::DepInfo,
                        OutputType::Exe, OutputType::LlvmAssembly,
                        OutputType::Metadata, OutputType::Mir, OutputType::Object,
                        OutputType::ThinLinkBitcode];
        ALL_VARIANTS.iter().copied()
    }
    fn is_compatible_with_codegen_units_and_single_output_file(&self)
        -> bool {
        match *self {
            OutputType::Assembly => false,
            OutputType::Bitcode => false,
            OutputType::DepInfo => true,
            OutputType::Exe => true,
            OutputType::LlvmAssembly => false,
            OutputType::Metadata => true,
            OutputType::Mir => false,
            OutputType::Object => false,
            OutputType::ThinLinkBitcode => false,
        }
    }
    pub fn shorthand(&self) -> &'static str {
        match *self {
            OutputType::Assembly => "asm",
            OutputType::Bitcode => "llvm-bc",
            OutputType::DepInfo => "dep-info",
            OutputType::Exe => "link",
            OutputType::LlvmAssembly => "llvm-ir",
            OutputType::Metadata => "metadata",
            OutputType::Mir => "mir",
            OutputType::Object => "obj",
            OutputType::ThinLinkBitcode => "thin-link-bitcode",
        }
    }
    fn from_shorthand(shorthand: &str) -> Option<Self> {
        match shorthand {
            s if s == "asm" => Some(OutputType::Assembly),
            s if s == "llvm-bc" => Some(OutputType::Bitcode),
            s if s == "dep-info" => Some(OutputType::DepInfo),
            s if s == "link" => Some(OutputType::Exe),
            s if s == "llvm-ir" => Some(OutputType::LlvmAssembly),
            s if s == "metadata" => Some(OutputType::Metadata),
            s if s == "mir" => Some(OutputType::Mir),
            s if s == "obj" => Some(OutputType::Object),
            s if s == "thin-link-bitcode" =>
                Some(OutputType::ThinLinkBitcode),
            _ => None,
        }
    }
    fn shorthands_display() -> String {
        let shorthands =
            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                    [::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "asm"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "llvm-bc"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "dep-info"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "link"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "llvm-ir"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "metadata"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "mir"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "obj"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`",
                                            "thin-link-bitcode"))
                                })]));
        shorthands.join(", ")
    }
    pub fn extension(&self) -> &'static str {
        match *self {
            OutputType::Assembly => "s",
            OutputType::Bitcode => "bc",
            OutputType::DepInfo => "d",
            OutputType::Exe => "",
            OutputType::LlvmAssembly => "ll",
            OutputType::Metadata => "rmeta",
            OutputType::Mir => "mir",
            OutputType::Object => "o",
            OutputType::ThinLinkBitcode => "indexing.o",
        }
    }
    pub fn is_text_output(&self) -> bool {
        match *self {
            OutputType::Assembly => true,
            OutputType::Bitcode => false,
            OutputType::DepInfo => true,
            OutputType::Exe => false,
            OutputType::LlvmAssembly => true,
            OutputType::Metadata => false,
            OutputType::Mir => true,
            OutputType::Object => false,
            OutputType::ThinLinkBitcode => false,
        }
    }
    pub fn description(&self) -> &'static str {
        match *self {
            OutputType::Assembly =>
                "Generates a file with the crate's assembly code",
            OutputType::Bitcode =>
                "Generates a binary file containing the LLVM bitcode",
            OutputType::DepInfo =>
                "Generates a file with Makefile syntax that indicates all the source files that were loaded to generate the crate",
            OutputType::Exe =>
                "Generates the crates specified by --crate-type. This is the default if --emit is not specified",
            OutputType::LlvmAssembly => "Generates a file containing LLVM IR",
            OutputType::Metadata =>
                "Generates a file containing metadata about the crate",
            OutputType::Mir =>
                "Generates a file containing rustc's mid-level intermediate representation",
            OutputType::Object => "Generates a native object file",
            OutputType::ThinLinkBitcode =>
                "Generates the ThinLTO summary as bitcode",
        }
    }
    pub fn default_filename(&self) -> &'static str {
        match *self {
            OutputType::Assembly => "CRATE_NAME.s",
            OutputType::Bitcode => "CRATE_NAME.bc",
            OutputType::DepInfo => "CRATE_NAME.d",
            OutputType::Exe => "(platform and crate-type dependent)",
            OutputType::LlvmAssembly => "CRATE_NAME.ll",
            OutputType::Metadata => "libCRATE_NAME.rmeta",
            OutputType::Mir => "CRATE_NAME.mir",
            OutputType::Object => "CRATE_NAME.o",
            OutputType::ThinLinkBitcode => "CRATE_NAME.indexing.o",
        }
    }
}define_output_types! {
731    Assembly => {
732        shorthand: "asm",
733        extension: "s",
734        description: "Generates a file with the crate's assembly code",
735        default_filename: "CRATE_NAME.s",
736        is_text: true,
737        compatible_with_cgus_and_single_output: false
738    },
739    #[doc = "This is the optimized bitcode, which could be either pre-LTO or non-LTO bitcode,"]
740    #[doc = "depending on the specific request type."]
741    Bitcode => {
742        shorthand: "llvm-bc",
743        extension: "bc",
744        description: "Generates a binary file containing the LLVM bitcode",
745        default_filename: "CRATE_NAME.bc",
746        is_text: false,
747        compatible_with_cgus_and_single_output: false
748    },
749    DepInfo => {
750        shorthand: "dep-info",
751        extension: "d",
752        description: "Generates a file with Makefile syntax that indicates all the source files that were loaded to generate the crate",
753        default_filename: "CRATE_NAME.d",
754        is_text: true,
755        compatible_with_cgus_and_single_output: true
756    },
757    Exe => {
758        shorthand: "link",
759        extension: "",
760        description: "Generates the crates specified by --crate-type. This is the default if --emit is not specified",
761        default_filename: "(platform and crate-type dependent)",
762        is_text: false,
763        compatible_with_cgus_and_single_output: true
764    },
765    LlvmAssembly => {
766        shorthand: "llvm-ir",
767        extension: "ll",
768        description: "Generates a file containing LLVM IR",
769        default_filename: "CRATE_NAME.ll",
770        is_text: true,
771        compatible_with_cgus_and_single_output: false
772    },
773    Metadata => {
774        shorthand: "metadata",
775        extension: "rmeta",
776        description: "Generates a file containing metadata about the crate",
777        default_filename: "libCRATE_NAME.rmeta",
778        is_text: false,
779        compatible_with_cgus_and_single_output: true
780    },
781    Mir => {
782        shorthand: "mir",
783        extension: "mir",
784        description: "Generates a file containing rustc's mid-level intermediate representation",
785        default_filename: "CRATE_NAME.mir",
786        is_text: true,
787        compatible_with_cgus_and_single_output: false
788    },
789    Object => {
790        shorthand: "obj",
791        extension: "o",
792        description: "Generates a native object file",
793        default_filename: "CRATE_NAME.o",
794        is_text: false,
795        compatible_with_cgus_and_single_output: false
796    },
797    #[doc = "This is the summary or index data part of the ThinLTO bitcode."]
798    ThinLinkBitcode => {
799        shorthand: "thin-link-bitcode",
800        extension: "indexing.o",
801        description: "Generates the ThinLTO summary as bitcode",
802        default_filename: "CRATE_NAME.indexing.o",
803        is_text: false,
804        compatible_with_cgus_and_single_output: false
805    },
806}
807
808/// The type of diagnostics output to generate.
809#[derive(#[automatically_derived]
impl ::core::clone::Clone for ErrorOutputType {
    #[inline]
    fn clone(&self) -> ErrorOutputType {
        let _: ::core::clone::AssertParamIsClone<HumanReadableErrorType>;
        let _: ::core::clone::AssertParamIsClone<ColorConfig>;
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for ErrorOutputType { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for ErrorOutputType {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            ErrorOutputType::HumanReadable {
                kind: __self_0, color_config: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "HumanReadable", "kind", __self_0, "color_config",
                    &__self_1),
            ErrorOutputType::Json {
                pretty: __self_0,
                json_rendered: __self_1,
                color_config: __self_2 } =>
                ::core::fmt::Formatter::debug_struct_field3_finish(f, "Json",
                    "pretty", __self_0, "json_rendered", __self_1,
                    "color_config", &__self_2),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for ErrorOutputType {
    #[inline]
    fn eq(&self, other: &ErrorOutputType) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (ErrorOutputType::HumanReadable {
                    kind: __self_0, color_config: __self_1 },
                    ErrorOutputType::HumanReadable {
                    kind: __arg1_0, color_config: __arg1_1 }) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (ErrorOutputType::Json {
                    pretty: __self_0,
                    json_rendered: __self_1,
                    color_config: __self_2 }, ErrorOutputType::Json {
                    pretty: __arg1_0,
                    json_rendered: __arg1_1,
                    color_config: __arg1_2 }) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1 &&
                        __self_2 == __arg1_2,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for ErrorOutputType {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<HumanReadableErrorType>;
        let _: ::core::cmp::AssertParamIsEq<ColorConfig>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::default::Default for ErrorOutputType {
    #[inline]
    fn default() -> ErrorOutputType {
        Self::HumanReadable {
            kind: const HumanReadableErrorType {
                        short: false,
                        unicode: false,
                    },
            color_config: const ColorConfig::Auto,
        }
    }
}Default)]
810pub enum ErrorOutputType {
811    /// Output meant for the consumption of humans.
812    #[default]
813    HumanReadable {
814        kind: HumanReadableErrorType = HumanReadableErrorType { short: false, unicode: false },
815        color_config: ColorConfig = ColorConfig::Auto,
816    },
817    /// Output that's consumed by other tools such as `rustfix` or the `RLS`.
818    Json {
819        /// Render the JSON in a human readable way (with indents and newlines).
820        pretty: bool,
821        /// The JSON output includes a `rendered` field that includes the rendered
822        /// human output.
823        json_rendered: HumanReadableErrorType,
824        color_config: ColorConfig,
825    },
826}
827
828#[derive(#[automatically_derived]
impl ::core::clone::Clone for ResolveDocLinks {
    #[inline]
    fn clone(&self) -> ResolveDocLinks {
        match self {
            ResolveDocLinks::None => ResolveDocLinks::None,
            ResolveDocLinks::ExportedMetadata =>
                ResolveDocLinks::ExportedMetadata,
            ResolveDocLinks::Exported => ResolveDocLinks::Exported,
            ResolveDocLinks::All => ResolveDocLinks::All,
        }
    }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for ResolveDocLinks {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for ResolveDocLinks {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                ResolveDocLinks::None => "None",
                ResolveDocLinks::ExportedMetadata => "ExportedMetadata",
                ResolveDocLinks::Exported => "Exported",
                ResolveDocLinks::All => "All",
            })
    }
}Debug)]
829pub enum ResolveDocLinks {
830    /// Do not resolve doc links.
831    None,
832    /// Resolve doc links on exported items only for crate types that have metadata.
833    ExportedMetadata,
834    /// Resolve doc links on exported items.
835    Exported,
836    /// Resolve doc links on all items.
837    All,
838}
839
840/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
841/// *Do not* switch `BTreeMap` out for an unsorted container type! That would break
842/// dependency tracking for command-line arguments. Also only hash keys, since tracking
843/// should only depend on the output types, not the paths they're written to.
844#[derive(#[automatically_derived]
impl ::core::clone::Clone for OutputTypes {
    #[inline]
    fn clone(&self) -> OutputTypes {
        OutputTypes(::core::clone::Clone::clone(&self.0))
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for OutputTypes {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f, "OutputTypes",
            &&self.0)
    }
}Debug, #[automatically_derived]
impl ::core::hash::Hash for OutputTypes {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.0, state)
    }
}Hash, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for OutputTypes where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    OutputTypes(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for OutputTypes {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    OutputTypes(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for OutputTypes {
            fn decode(__decoder: &mut __D) -> Self {
                OutputTypes(::rustc_serialize::Decodable::decode(__decoder))
            }
        }
    };Decodable)]
845pub struct OutputTypes(BTreeMap<OutputType, Option<OutFileName>>);
846
847impl OutputTypes {
848    pub fn new(entries: &[(OutputType, Option<OutFileName>)]) -> OutputTypes {
849        OutputTypes(BTreeMap::from_iter(entries.iter().map(|&(k, ref v)| (k, v.clone()))))
850    }
851
852    pub(crate) fn get(&self, key: &OutputType) -> Option<&Option<OutFileName>> {
853        self.0.get(key)
854    }
855
856    pub fn contains_key(&self, key: &OutputType) -> bool {
857        self.0.contains_key(key)
858    }
859
860    /// Returns `true` if user specified a name and not just produced type
861    pub fn contains_explicit_name(&self, key: &OutputType) -> bool {
862        #[allow(non_exhaustive_omitted_patterns)] match self.0.get(key) {
    Some(Some(..)) => true,
    _ => false,
}matches!(self.0.get(key), Some(Some(..)))
863    }
864
865    pub fn iter(&self) -> BTreeMapIter<'_, OutputType, Option<OutFileName>> {
866        self.0.iter()
867    }
868
869    pub fn keys(&self) -> BTreeMapKeysIter<'_, OutputType, Option<OutFileName>> {
870        self.0.keys()
871    }
872
873    pub fn values(&self) -> BTreeMapValuesIter<'_, OutputType, Option<OutFileName>> {
874        self.0.values()
875    }
876
877    pub fn len(&self) -> usize {
878        self.0.len()
879    }
880
881    /// Returns `true` if any of the output types require codegen or linking.
882    pub fn should_codegen(&self) -> bool {
883        self.0.keys().any(|k| match *k {
884            OutputType::Bitcode
885            | OutputType::ThinLinkBitcode
886            | OutputType::Assembly
887            | OutputType::LlvmAssembly
888            | OutputType::Mir
889            | OutputType::Object
890            | OutputType::Exe => true,
891            OutputType::Metadata | OutputType::DepInfo => false,
892        })
893    }
894
895    /// Returns `true` if any of the output types require linking.
896    pub fn should_link(&self) -> bool {
897        self.0.keys().any(|k| match *k {
898            OutputType::Bitcode
899            | OutputType::ThinLinkBitcode
900            | OutputType::Assembly
901            | OutputType::LlvmAssembly
902            | OutputType::Mir
903            | OutputType::Metadata
904            | OutputType::Object
905            | OutputType::DepInfo => false,
906            OutputType::Exe => true,
907        })
908    }
909}
910
911/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
912/// *Do not* switch `BTreeMap` or `BTreeSet` out for an unsorted container type! That
913/// would break dependency tracking for command-line arguments.
914#[derive(#[automatically_derived]
impl ::core::clone::Clone for Externs {
    #[inline]
    fn clone(&self) -> Externs {
        Externs(::core::clone::Clone::clone(&self.0))
    }
}Clone)]
915pub struct Externs(BTreeMap<String, ExternEntry>);
916
917#[derive(#[automatically_derived]
impl ::core::clone::Clone for ExternEntry {
    #[inline]
    fn clone(&self) -> ExternEntry {
        ExternEntry {
            location: ::core::clone::Clone::clone(&self.location),
            is_private_dep: ::core::clone::Clone::clone(&self.is_private_dep),
            add_prelude: ::core::clone::Clone::clone(&self.add_prelude),
            nounused_dep: ::core::clone::Clone::clone(&self.nounused_dep),
            force: ::core::clone::Clone::clone(&self.force),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for ExternEntry {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field5_finish(f, "ExternEntry",
            "location", &self.location, "is_private_dep",
            &self.is_private_dep, "add_prelude", &self.add_prelude,
            "nounused_dep", &self.nounused_dep, "force", &&self.force)
    }
}Debug)]
918pub struct ExternEntry {
919    pub location: ExternLocation,
920    /// Indicates this is a "private" dependency for the
921    /// `exported_private_dependencies` lint.
922    ///
923    /// This can be set with the `priv` option like
924    /// `--extern priv:name=foo.rlib`.
925    pub is_private_dep: bool,
926    /// Add the extern entry to the extern prelude.
927    ///
928    /// This can be disabled with the `noprelude` option like
929    /// `--extern noprelude:name`.
930    pub add_prelude: bool,
931    /// The extern entry shouldn't be considered for unused dependency warnings.
932    ///
933    /// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to
934    /// suppress `unused-crate-dependencies` warnings.
935    pub nounused_dep: bool,
936    /// If the extern entry is not referenced in the crate, force it to be resolved anyway.
937    ///
938    /// Allows a dependency satisfying, for instance, a missing panic handler to be injected
939    /// without modifying source:
940    /// `--extern force:extras=/path/to/lib/libstd.rlib`
941    pub force: bool,
942}
943
944#[derive(#[automatically_derived]
impl ::core::clone::Clone for ExternLocation {
    #[inline]
    fn clone(&self) -> ExternLocation {
        match self {
            ExternLocation::FoundInLibrarySearchDirectories =>
                ExternLocation::FoundInLibrarySearchDirectories,
            ExternLocation::ExactPaths(__self_0) =>
                ExternLocation::ExactPaths(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for ExternLocation {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            ExternLocation::FoundInLibrarySearchDirectories =>
                ::core::fmt::Formatter::write_str(f,
                    "FoundInLibrarySearchDirectories"),
            ExternLocation::ExactPaths(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ExactPaths", &__self_0),
        }
    }
}Debug)]
945pub enum ExternLocation {
946    /// Indicates to look for the library in the search paths.
947    ///
948    /// Added via `--extern name`.
949    FoundInLibrarySearchDirectories,
950    /// The locations where this extern entry must be found.
951    ///
952    /// The `CrateLoader` is responsible for loading these and figuring out
953    /// which one to use.
954    ///
955    /// Added via `--extern prelude_name=some_file.rlib`
956    ExactPaths(BTreeSet<CanonicalizedPath>),
957}
958
959impl Externs {
960    /// Used for testing.
961    pub fn new(data: BTreeMap<String, ExternEntry>) -> Externs {
962        Externs(data)
963    }
964
965    pub fn get(&self, key: &str) -> Option<&ExternEntry> {
966        self.0.get(key)
967    }
968
969    pub fn iter(&self) -> BTreeMapIter<'_, String, ExternEntry> {
970        self.0.iter()
971    }
972}
973
974impl ExternEntry {
975    fn new(location: ExternLocation) -> ExternEntry {
976        ExternEntry {
977            location,
978            is_private_dep: false,
979            add_prelude: false,
980            nounused_dep: false,
981            force: false,
982        }
983    }
984
985    pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
986        match &self.location {
987            ExternLocation::ExactPaths(set) => Some(set.iter()),
988            _ => None,
989        }
990    }
991}
992
993#[derive(#[automatically_derived]
impl ::core::fmt::Debug for NextSolverConfig {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "NextSolverConfig", "coherence", &self.coherence, "globally",
            &&self.globally)
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for NextSolverConfig { }Copy, #[automatically_derived]
impl ::core::clone::Clone for NextSolverConfig {
    #[inline]
    fn clone(&self) -> NextSolverConfig {
        let _: ::core::clone::AssertParamIsClone<bool>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for NextSolverConfig {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.coherence, state);
        ::core::hash::Hash::hash(&self.globally, state)
    }
}Hash, #[automatically_derived]
impl ::core::cmp::PartialEq for NextSolverConfig {
    #[inline]
    fn eq(&self, other: &NextSolverConfig) -> bool {
        self.coherence == other.coherence && self.globally == other.globally
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for NextSolverConfig {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::default::Default for NextSolverConfig {
    #[inline]
    fn default() -> NextSolverConfig {
        NextSolverConfig { coherence: const true, globally: const false }
    }
}Default)]
994pub struct NextSolverConfig {
995    /// Whether the new trait solver should be enabled in coherence.
996    pub coherence: bool = true,
997    /// Whether the new trait solver should be enabled everywhere.
998    /// This is only `true` if `coherence` is also enabled.
999    pub globally: bool = false,
1000}
1001
1002#[derive(#[automatically_derived]
impl ::core::clone::Clone for Input {
    #[inline]
    fn clone(&self) -> Input {
        match self {
            Input::File(__self_0) =>
                Input::File(::core::clone::Clone::clone(__self_0)),
            Input::Str { name: __self_0, input: __self_1 } =>
                Input::Str {
                    name: ::core::clone::Clone::clone(__self_0),
                    input: ::core::clone::Clone::clone(__self_1),
                },
        }
    }
}Clone)]
1003pub enum Input {
1004    /// Load source code from a file.
1005    File(PathBuf),
1006    /// Load source code from a string.
1007    Str {
1008        /// A string that is shown in place of a filename.
1009        name: FileName,
1010        /// An anonymous string containing the source code.
1011        input: String,
1012    },
1013}
1014
1015impl Input {
1016    pub fn filestem(&self) -> &str {
1017        if let Input::File(ifile) = self {
1018            // If for some reason getting the file stem as a UTF-8 string fails,
1019            // then fallback to a fixed name.
1020            if let Some(name) = ifile.file_stem().and_then(OsStr::to_str) {
1021                return name;
1022            }
1023        }
1024        "rust_out"
1025    }
1026
1027    pub fn file_name(&self, session: &Session) -> FileName {
1028        match *self {
1029            Input::File(ref ifile) => FileName::Real(
1030                session
1031                    .psess
1032                    .source_map()
1033                    .path_mapping()
1034                    .to_real_filename(session.psess.source_map().working_dir(), ifile.as_path()),
1035            ),
1036            Input::Str { ref name, .. } => name.clone(),
1037        }
1038    }
1039
1040    pub fn opt_path(&self) -> Option<&Path> {
1041        match self {
1042            Input::File(file) => Some(file),
1043            Input::Str { name, .. } => match name {
1044                FileName::Real(real) => real.local_path(),
1045                FileName::CfgSpec(_) => None,
1046                FileName::Anon(_) => None,
1047                FileName::MacroExpansion(_) => None,
1048                FileName::ProcMacroSourceCode(_) => None,
1049                FileName::CliCrateAttr(_) => None,
1050                FileName::Custom(_) => None,
1051                FileName::DocTest(path, _) => Some(path),
1052                FileName::InlineAsm(_) => None,
1053            },
1054        }
1055    }
1056}
1057
1058#[derive(#[automatically_derived]
impl ::core::clone::Clone for OutFileName {
    #[inline]
    fn clone(&self) -> OutFileName {
        match self {
            OutFileName::Real(__self_0) =>
                OutFileName::Real(::core::clone::Clone::clone(__self_0)),
            OutFileName::Stdout => OutFileName::Stdout,
        }
    }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for OutFileName {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            OutFileName::Real(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for OutFileName {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            OutFileName::Real(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Real",
                    &__self_0),
            OutFileName::Stdout =>
                ::core::fmt::Formatter::write_str(f, "Stdout"),
        }
    }
}Debug, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for OutFileName where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    OutFileName::Real(ref __binding_0) => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                    OutFileName::Stdout => {}
                }
            }
        }
    };HashStable_Generic, #[automatically_derived]
impl ::core::cmp::PartialEq for OutFileName {
    #[inline]
    fn eq(&self, other: &OutFileName) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (OutFileName::Real(__self_0), OutFileName::Real(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for OutFileName {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<PathBuf>;
    }
}Eq, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for OutFileName {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        OutFileName::Real(ref __binding_0) => { 0usize }
                        OutFileName::Stdout => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    OutFileName::Real(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    OutFileName::Stdout => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for OutFileName {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        OutFileName::Real(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => { OutFileName::Stdout }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `OutFileName`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
1059pub enum OutFileName {
1060    Real(PathBuf),
1061    Stdout,
1062}
1063
1064impl OutFileName {
1065    pub fn parent(&self) -> Option<&Path> {
1066        match *self {
1067            OutFileName::Real(ref path) => path.parent(),
1068            OutFileName::Stdout => None,
1069        }
1070    }
1071
1072    pub fn filestem(&self) -> Option<&OsStr> {
1073        match *self {
1074            OutFileName::Real(ref path) => path.file_stem(),
1075            OutFileName::Stdout => Some(OsStr::new("stdout")),
1076        }
1077    }
1078
1079    pub fn is_stdout(&self) -> bool {
1080        match *self {
1081            OutFileName::Real(_) => false,
1082            OutFileName::Stdout => true,
1083        }
1084    }
1085
1086    pub fn is_tty(&self) -> bool {
1087        use std::io::IsTerminal;
1088        match *self {
1089            OutFileName::Real(_) => false,
1090            OutFileName::Stdout => std::io::stdout().is_terminal(),
1091        }
1092    }
1093
1094    pub fn as_path(&self) -> &Path {
1095        match *self {
1096            OutFileName::Real(ref path) => path.as_ref(),
1097            OutFileName::Stdout => Path::new("stdout"),
1098        }
1099    }
1100
1101    /// For a given output filename, return the actual name of the file that
1102    /// can be used to write codegen data of type `flavor`. For real-path
1103    /// output filenames, this would be trivial as we can just use the path.
1104    /// Otherwise for stdout, return a temporary path so that the codegen data
1105    /// may be later copied to stdout.
1106    pub fn file_for_writing(
1107        &self,
1108        outputs: &OutputFilenames,
1109        flavor: OutputType,
1110        codegen_unit_name: &str,
1111        invocation_temp: Option<&str>,
1112    ) -> PathBuf {
1113        match *self {
1114            OutFileName::Real(ref path) => path.clone(),
1115            OutFileName::Stdout => {
1116                outputs.temp_path_for_cgu(flavor, codegen_unit_name, invocation_temp)
1117            }
1118        }
1119    }
1120
1121    pub fn overwrite(&self, content: &str, sess: &Session) {
1122        match self {
1123            OutFileName::Stdout => { ::std::io::_print(format_args!("{0}", content)); }print!("{content}"),
1124            OutFileName::Real(path) => {
1125                if let Err(e) = fs::write(path, content) {
1126                    sess.dcx().emit_fatal(FileWriteFail { path, err: e.to_string() });
1127                }
1128            }
1129        }
1130    }
1131}
1132
1133#[derive(#[automatically_derived]
impl ::core::clone::Clone for OutputFilenames {
    #[inline]
    fn clone(&self) -> OutputFilenames {
        OutputFilenames {
            out_directory: ::core::clone::Clone::clone(&self.out_directory),
            crate_stem: ::core::clone::Clone::clone(&self.crate_stem),
            filestem: ::core::clone::Clone::clone(&self.filestem),
            single_output_file: ::core::clone::Clone::clone(&self.single_output_file),
            temps_directory: ::core::clone::Clone::clone(&self.temps_directory),
            explicit_dwo_out_directory: ::core::clone::Clone::clone(&self.explicit_dwo_out_directory),
            outputs: ::core::clone::Clone::clone(&self.outputs),
        }
    }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for OutputFilenames {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.out_directory, state);
        ::core::hash::Hash::hash(&self.crate_stem, state);
        ::core::hash::Hash::hash(&self.filestem, state);
        ::core::hash::Hash::hash(&self.single_output_file, state);
        ::core::hash::Hash::hash(&self.temps_directory, state);
        ::core::hash::Hash::hash(&self.explicit_dwo_out_directory, state);
        ::core::hash::Hash::hash(&self.outputs, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for OutputFilenames {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["out_directory", "crate_stem", "filestem", "single_output_file",
                        "temps_directory", "explicit_dwo_out_directory", "outputs"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.out_directory, &self.crate_stem, &self.filestem,
                        &self.single_output_file, &self.temps_directory,
                        &self.explicit_dwo_out_directory, &&self.outputs];
        ::core::fmt::Formatter::debug_struct_fields_finish(f,
            "OutputFilenames", names, values)
    }
}Debug, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for OutputFilenames where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    OutputFilenames {
                        out_directory: ref __binding_0,
                        crate_stem: ref __binding_1,
                        filestem: ref __binding_2,
                        single_output_file: ref __binding_3,
                        temps_directory: ref __binding_4,
                        explicit_dwo_out_directory: ref __binding_5,
                        outputs: ref __binding_6 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                        { __binding_1.hash_stable(__hcx, __hasher); }
                        { __binding_2.hash_stable(__hcx, __hasher); }
                        { __binding_3.hash_stable(__hcx, __hasher); }
                        { __binding_4.hash_stable(__hcx, __hasher); }
                        { __binding_5.hash_stable(__hcx, __hasher); }
                        { __binding_6.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for OutputFilenames {
            fn encode(&self, __encoder: &mut __E) {
                match *self {
                    OutputFilenames {
                        out_directory: ref __binding_0,
                        crate_stem: ref __binding_1,
                        filestem: ref __binding_2,
                        single_output_file: ref __binding_3,
                        temps_directory: ref __binding_4,
                        explicit_dwo_out_directory: ref __binding_5,
                        outputs: ref __binding_6 } => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_2,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_3,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_4,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_5,
                            __encoder);
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_6,
                            __encoder);
                    }
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for OutputFilenames {
            fn decode(__decoder: &mut __D) -> Self {
                OutputFilenames {
                    out_directory: ::rustc_serialize::Decodable::decode(__decoder),
                    crate_stem: ::rustc_serialize::Decodable::decode(__decoder),
                    filestem: ::rustc_serialize::Decodable::decode(__decoder),
                    single_output_file: ::rustc_serialize::Decodable::decode(__decoder),
                    temps_directory: ::rustc_serialize::Decodable::decode(__decoder),
                    explicit_dwo_out_directory: ::rustc_serialize::Decodable::decode(__decoder),
                    outputs: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };Decodable)]
1134pub struct OutputFilenames {
1135    pub(crate) out_directory: PathBuf,
1136    /// Crate name. Never contains '-'.
1137    crate_stem: String,
1138    /// Typically based on `.rs` input file name. Any '-' is preserved.
1139    filestem: String,
1140    pub single_output_file: Option<OutFileName>,
1141    temps_directory: Option<PathBuf>,
1142    explicit_dwo_out_directory: Option<PathBuf>,
1143    pub outputs: OutputTypes,
1144}
1145
1146pub const RLINK_EXT: &str = "rlink";
1147pub const RUST_CGU_EXT: &str = "rcgu";
1148pub const DWARF_OBJECT_EXT: &str = "dwo";
1149pub const MAX_FILENAME_LENGTH: usize = 143; // ecryptfs limits filenames to 143 bytes see #49914
1150
1151/// Ensure the filename is not too long, as some filesystems have a limit.
1152/// If the filename is too long, hash part of it and append the hash to the filename.
1153/// This is a workaround for long crate names generating overly long filenames.
1154fn maybe_strip_file_name(mut path: PathBuf) -> PathBuf {
1155    if path.file_name().map_or(0, |name| name.len()) > MAX_FILENAME_LENGTH {
1156        let filename = path.file_name().unwrap().to_string_lossy();
1157        let hash_len = 64 / 4; // Hash64 is 64 bits encoded in hex
1158        let hyphen_len = 1; // the '-' we insert between hash and suffix
1159
1160        // number of bytes of suffix we can keep so that "hash-<suffix>" fits
1161        let allowed_suffix = MAX_FILENAME_LENGTH.saturating_sub(hash_len + hyphen_len);
1162
1163        // number of bytes to remove from the start
1164        let stripped_bytes = filename.len().saturating_sub(allowed_suffix);
1165
1166        // ensure we don't cut in a middle of a char
1167        let split_at = filename.ceil_char_boundary(stripped_bytes);
1168
1169        let mut hasher = StableHasher::new();
1170        filename[..split_at].hash(&mut hasher);
1171        let hash = hasher.finish::<Hash64>();
1172
1173        path.set_file_name(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0:x}-{1}", hash,
                &filename[split_at..]))
    })format!("{:x}-{}", hash, &filename[split_at..]));
1174    }
1175    path
1176}
1177impl OutputFilenames {
1178    pub fn new(
1179        out_directory: PathBuf,
1180        out_crate_name: String,
1181        out_filestem: String,
1182        single_output_file: Option<OutFileName>,
1183        temps_directory: Option<PathBuf>,
1184        explicit_dwo_out_directory: Option<PathBuf>,
1185        extra: String,
1186        outputs: OutputTypes,
1187    ) -> Self {
1188        OutputFilenames {
1189            out_directory,
1190            single_output_file,
1191            temps_directory,
1192            explicit_dwo_out_directory,
1193            outputs,
1194            crate_stem: ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}", out_crate_name, extra))
    })format!("{out_crate_name}{extra}"),
1195            filestem: ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}", out_filestem, extra))
    })format!("{out_filestem}{extra}"),
1196        }
1197    }
1198
1199    pub fn path(&self, flavor: OutputType) -> OutFileName {
1200        self.outputs
1201            .get(&flavor)
1202            .and_then(|p| p.to_owned())
1203            .or_else(|| self.single_output_file.clone())
1204            .unwrap_or_else(|| OutFileName::Real(self.output_path(flavor)))
1205    }
1206
1207    pub fn interface_path(&self) -> PathBuf {
1208        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_session/src/config.rs:1208",
                        "rustc_session::config", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_session/src/config.rs"),
                        ::tracing_core::__macro_support::Option::Some(1208u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_session::config"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("using crate_name={0} for interface_path",
                                                    self.crate_stem) as &dyn Value))])
            });
    } else { ; }
};debug!("using crate_name={} for interface_path", self.crate_stem);
1209        self.out_directory.join(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("lib{0}.rs", self.crate_stem))
    })format!("lib{}.rs", self.crate_stem))
1210    }
1211
1212    /// Gets the output path where a compilation artifact of the given type
1213    /// should be placed on disk.
1214    fn output_path(&self, flavor: OutputType) -> PathBuf {
1215        let extension = flavor.extension();
1216        match flavor {
1217            OutputType::Metadata => {
1218                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_session/src/config.rs:1218",
                        "rustc_session::config", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_session/src/config.rs"),
                        ::tracing_core::__macro_support::Option::Some(1218u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_session::config"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("using crate_name={0} for {1}",
                                                    self.crate_stem, extension) as &dyn Value))])
            });
    } else { ; }
};debug!("using crate_name={} for {extension}", self.crate_stem);
1219                self.out_directory.join(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("lib{0}.{1}", self.crate_stem,
                extension))
    })format!("lib{}.{}", self.crate_stem, extension))
1220            }
1221            _ => self.with_directory_and_extension(&self.out_directory, extension),
1222        }
1223    }
1224
1225    /// Gets the path where a compilation artifact of the given type for the
1226    /// given codegen unit should be placed on disk. If codegen_unit_name is
1227    /// None, a path distinct from those of any codegen unit will be generated.
1228    pub fn temp_path_for_cgu(
1229        &self,
1230        flavor: OutputType,
1231        codegen_unit_name: &str,
1232        invocation_temp: Option<&str>,
1233    ) -> PathBuf {
1234        let extension = flavor.extension();
1235        self.temp_path_ext_for_cgu(extension, codegen_unit_name, invocation_temp)
1236    }
1237
1238    /// Like `temp_path`, but specifically for dwarf objects.
1239    pub fn temp_path_dwo_for_cgu(
1240        &self,
1241        codegen_unit_name: &str,
1242        invocation_temp: Option<&str>,
1243    ) -> PathBuf {
1244        let p = self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name, invocation_temp);
1245        if let Some(dwo_out) = &self.explicit_dwo_out_directory {
1246            let mut o = dwo_out.clone();
1247            o.push(p.file_name().unwrap());
1248            o
1249        } else {
1250            p
1251        }
1252    }
1253
1254    /// Like `temp_path`, but also supports things where there is no corresponding
1255    /// OutputType, like noopt-bitcode or lto-bitcode.
1256    pub fn temp_path_ext_for_cgu(
1257        &self,
1258        ext: &str,
1259        codegen_unit_name: &str,
1260        invocation_temp: Option<&str>,
1261    ) -> PathBuf {
1262        let mut extension = codegen_unit_name.to_string();
1263
1264        // Append `.{invocation_temp}` to ensure temporary files are unique.
1265        if let Some(rng) = invocation_temp {
1266            extension.push('.');
1267            extension.push_str(rng);
1268        }
1269
1270        // FIXME: This is sketchy that we're not appending `.rcgu` when the ext is empty.
1271        // Append `.rcgu.{ext}`.
1272        if !ext.is_empty() {
1273            extension.push('.');
1274            extension.push_str(RUST_CGU_EXT);
1275            extension.push('.');
1276            extension.push_str(ext);
1277        }
1278
1279        let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory);
1280        maybe_strip_file_name(self.with_directory_and_extension(temps_directory, &extension))
1281    }
1282
1283    pub fn temp_path_for_diagnostic(&self, ext: &str) -> PathBuf {
1284        let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory);
1285        self.with_directory_and_extension(temps_directory, &ext)
1286    }
1287
1288    pub fn with_extension(&self, extension: &str) -> PathBuf {
1289        self.with_directory_and_extension(&self.out_directory, extension)
1290    }
1291
1292    pub fn with_directory_and_extension(&self, directory: &Path, extension: &str) -> PathBuf {
1293        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_session/src/config.rs:1293",
                        "rustc_session::config", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_session/src/config.rs"),
                        ::tracing_core::__macro_support::Option::Some(1293u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_session::config"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("using filestem={0} for {1}",
                                                    self.filestem, extension) as &dyn Value))])
            });
    } else { ; }
};debug!("using filestem={} for {extension}", self.filestem);
1294        let mut path = directory.join(&self.filestem);
1295        path.set_extension(extension);
1296        path
1297    }
1298
1299    /// Returns the path for the Split DWARF file - this can differ depending on which Split DWARF
1300    /// mode is being used, which is the logic that this function is intended to encapsulate.
1301    pub fn split_dwarf_path(
1302        &self,
1303        split_debuginfo_kind: SplitDebuginfo,
1304        split_dwarf_kind: SplitDwarfKind,
1305        cgu_name: &str,
1306        invocation_temp: Option<&str>,
1307    ) -> Option<PathBuf> {
1308        let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp);
1309        let dwo_out = self.temp_path_dwo_for_cgu(cgu_name, invocation_temp);
1310        match (split_debuginfo_kind, split_dwarf_kind) {
1311            (SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None,
1312            // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes
1313            // (pointing at the path which is being determined here). Use the path to the current
1314            // object file.
1315            (SplitDebuginfo::Packed | SplitDebuginfo::Unpacked, SplitDwarfKind::Single) => {
1316                Some(obj_out)
1317            }
1318            // Split mode emits the DWARF into a different file, use that path.
1319            (SplitDebuginfo::Packed | SplitDebuginfo::Unpacked, SplitDwarfKind::Split) => {
1320                Some(dwo_out)
1321            }
1322        }
1323    }
1324}
1325
1326// pub for rustdoc
1327pub fn parse_remap_path_scope(
1328    early_dcx: &EarlyDiagCtxt,
1329    matches: &getopts::Matches,
1330    unstable_opts: &UnstableOptions,
1331) -> RemapPathScopeComponents {
1332    if let Some(v) = matches.opt_str("remap-path-scope") {
1333        let mut slot = RemapPathScopeComponents::empty();
1334        for s in v.split(',') {
1335            slot |= match s {
1336                "macro" => RemapPathScopeComponents::MACRO,
1337                "diagnostics" => RemapPathScopeComponents::DIAGNOSTICS,
1338                "documentation" => {
1339                    if !unstable_opts.unstable_options {
1340                        early_dcx.early_fatal("remapping `documentation` path scope requested but `-Zunstable-options` not specified");
1341                    }
1342
1343                    RemapPathScopeComponents::DOCUMENTATION
1344                },
1345                "debuginfo" => RemapPathScopeComponents::DEBUGINFO,
1346                "coverage" => RemapPathScopeComponents::COVERAGE,
1347                "object" => RemapPathScopeComponents::OBJECT,
1348                "all" => RemapPathScopeComponents::all(),
1349                _ => early_dcx.early_fatal("argument for `--remap-path-scope` must be a comma separated list of scopes: `macro`, `diagnostics`, `documentation`, `debuginfo`, `coverage`, `object`, `all`"),
1350            }
1351        }
1352        slot
1353    } else {
1354        RemapPathScopeComponents::all()
1355    }
1356}
1357
1358#[derive(#[automatically_derived]
impl ::core::clone::Clone for Sysroot {
    #[inline]
    fn clone(&self) -> Sysroot {
        Sysroot {
            explicit: ::core::clone::Clone::clone(&self.explicit),
            default: ::core::clone::Clone::clone(&self.default),
        }
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for Sysroot {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "Sysroot",
            "explicit", &self.explicit, "default", &&self.default)
    }
}Debug)]
1359pub struct Sysroot {
1360    pub explicit: Option<PathBuf>,
1361    pub default: PathBuf,
1362}
1363
1364impl Sysroot {
1365    pub fn new(explicit: Option<PathBuf>) -> Sysroot {
1366        Sysroot { explicit, default: filesearch::default_sysroot() }
1367    }
1368
1369    /// Return explicit sysroot if it was passed with `--sysroot`, or default sysroot otherwise.
1370    pub fn path(&self) -> &Path {
1371        self.explicit.as_deref().unwrap_or(&self.default)
1372    }
1373
1374    /// Returns both explicit sysroot if it was passed with `--sysroot` and the default sysroot.
1375    pub fn all_paths(&self) -> impl Iterator<Item = &Path> {
1376        self.explicit.as_deref().into_iter().chain(iter::once(&*self.default))
1377    }
1378}
1379
1380pub fn host_tuple() -> &'static str {
1381    // Get the host triple out of the build environment. This ensures that our
1382    // idea of the host triple is the same as for the set of libraries we've
1383    // actually built. We can't just take LLVM's host triple because they
1384    // normalize all ix86 architectures to i386.
1385    //
1386    // Instead of grabbing the host triple (for the current host), we grab (at
1387    // compile time) the target triple that this rustc is built with and
1388    // calling that (at runtime) the host triple.
1389    (::core::option::Option::Some("x86_64-unknown-linux-gnu")option_env!("CFG_COMPILER_HOST_TRIPLE")).expect("CFG_COMPILER_HOST_TRIPLE")
1390}
1391
1392fn file_path_mapping(
1393    remap_path_prefix: Vec<(PathBuf, PathBuf)>,
1394    remap_path_scope: RemapPathScopeComponents,
1395) -> FilePathMapping {
1396    FilePathMapping::new(remap_path_prefix.clone(), remap_path_scope)
1397}
1398
1399impl Default for Options {
1400    fn default() -> Options {
1401        let unstable_opts = UnstableOptions::default();
1402
1403        // FIXME(Urgau): This is a hack that ideally shouldn't exist, but rustdoc
1404        // currently uses this `Default` implementation, so we have no choice but
1405        // to create a default working directory.
1406        let working_dir = {
1407            let working_dir = std::env::current_dir().unwrap();
1408            let file_mapping = file_path_mapping(Vec::new(), RemapPathScopeComponents::empty());
1409            file_mapping.to_real_filename(&RealFileName::empty(), &working_dir)
1410        };
1411
1412        Options {
1413            crate_types: Vec::new(),
1414            optimize: OptLevel::No,
1415            debuginfo: DebugInfo::None,
1416            lint_opts: Vec::new(),
1417            lint_cap: None,
1418            describe_lints: false,
1419            output_types: OutputTypes(BTreeMap::new()),
1420            search_paths: ::alloc::vec::Vec::new()vec![],
1421            sysroot: Sysroot::new(None),
1422            target_triple: TargetTuple::from_tuple(host_tuple()),
1423            test: false,
1424            incremental: None,
1425            unstable_opts,
1426            prints: Vec::new(),
1427            cg: Default::default(),
1428            error_format: ErrorOutputType::default(),
1429            diagnostic_width: None,
1430            externs: Externs(BTreeMap::new()),
1431            crate_name: None,
1432            libs: Vec::new(),
1433            unstable_features: UnstableFeatures::Disallow,
1434            debug_assertions: true,
1435            actually_rustdoc: false,
1436            resolve_doc_links: ResolveDocLinks::None,
1437            trimmed_def_paths: false,
1438            cli_forced_codegen_units: None,
1439            cli_forced_local_thinlto_off: false,
1440            remap_path_prefix: Vec::new(),
1441            remap_path_scope: RemapPathScopeComponents::all(),
1442            real_rust_source_base_dir: None,
1443            real_rustc_dev_source_base_dir: None,
1444            edition: DEFAULT_EDITION,
1445            json_artifact_notifications: false,
1446            json_timings: false,
1447            json_unused_externs: JsonUnusedExterns::No,
1448            json_future_incompat: false,
1449            pretty: None,
1450            working_dir,
1451            color: ColorConfig::Auto,
1452            logical_env: FxIndexMap::default(),
1453            verbose: false,
1454            target_modifiers: BTreeMap::default(),
1455            mitigation_coverage_map: Default::default(),
1456        }
1457    }
1458}
1459
1460impl Options {
1461    /// Returns `true` if there is a reason to build the dep graph.
1462    pub fn build_dep_graph(&self) -> bool {
1463        self.incremental.is_some()
1464            || self.unstable_opts.dump_dep_graph
1465            || self.unstable_opts.query_dep_graph
1466    }
1467
1468    pub fn file_path_mapping(&self) -> FilePathMapping {
1469        file_path_mapping(self.remap_path_prefix.clone(), self.remap_path_scope)
1470    }
1471
1472    /// Returns `true` if there will be an output file generated.
1473    pub fn will_create_output_file(&self) -> bool {
1474        !self.unstable_opts.parse_crate_root_only && // The file is just being parsed
1475            self.unstable_opts.ls.is_empty() // The file is just being queried
1476    }
1477
1478    #[inline]
1479    pub fn share_generics(&self) -> bool {
1480        match self.unstable_opts.share_generics {
1481            Some(setting) => setting,
1482            None => match self.optimize {
1483                OptLevel::No | OptLevel::Less | OptLevel::Size | OptLevel::SizeMin => true,
1484                OptLevel::More | OptLevel::Aggressive => false,
1485            },
1486        }
1487    }
1488
1489    pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion {
1490        self.cg.symbol_mangling_version.unwrap_or(if self.unstable_features.is_nightly_build() {
1491            SymbolManglingVersion::V0
1492        } else {
1493            SymbolManglingVersion::Legacy
1494        })
1495    }
1496
1497    #[inline]
1498    pub fn autodiff_enabled(&self) -> bool {
1499        self.unstable_opts.autodiff.contains(&AutoDiff::Enable)
1500    }
1501}
1502
1503impl UnstableOptions {
1504    pub fn dcx_flags(&self, can_emit_warnings: bool) -> DiagCtxtFlags {
1505        DiagCtxtFlags {
1506            can_emit_warnings,
1507            treat_err_as_bug: self.treat_err_as_bug,
1508            eagerly_emit_delayed_bugs: self.eagerly_emit_delayed_bugs,
1509            macro_backtrace: self.macro_backtrace,
1510            deduplicate_diagnostics: self.deduplicate_diagnostics,
1511            track_diagnostics: self.track_diagnostics,
1512        }
1513    }
1514
1515    pub fn src_hash_algorithm(&self, target: &Target) -> SourceFileHashAlgorithm {
1516        self.src_hash_algorithm.unwrap_or_else(|| {
1517            if target.is_like_msvc {
1518                SourceFileHashAlgorithm::Sha256
1519            } else {
1520                SourceFileHashAlgorithm::Md5
1521            }
1522        })
1523    }
1524
1525    pub fn checksum_hash_algorithm(&self) -> Option<SourceFileHashAlgorithm> {
1526        self.checksum_hash_algorithm
1527    }
1528}
1529
1530// The type of entry function, so users can have their own entry functions
1531#[derive(#[automatically_derived]
impl ::core::marker::Copy for EntryFnType { }Copy, #[automatically_derived]
impl ::core::clone::Clone for EntryFnType {
    #[inline]
    fn clone(&self) -> EntryFnType {
        let _: ::core::clone::AssertParamIsClone<u8>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for EntryFnType {
    #[inline]
    fn eq(&self, other: &EntryFnType) -> bool {
        match (self, other) {
            (EntryFnType::Main { sigpipe: __self_0 }, EntryFnType::Main {
                sigpipe: __arg1_0 }) => __self_0 == __arg1_0,
        }
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for EntryFnType {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        match self {
            EntryFnType::Main { sigpipe: __self_0 } =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for EntryFnType {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            EntryFnType::Main { sigpipe: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Main",
                    "sigpipe", &__self_0),
        }
    }
}Debug, const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for EntryFnType where __CTX: ::rustc_span::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    EntryFnType::Main { sigpipe: ref __binding_0 } => {
                        { __binding_0.hash_stable(__hcx, __hasher); }
                    }
                }
            }
        }
    };HashStable_Generic)]
1532pub enum EntryFnType {
1533    Main {
1534        /// Specifies what to do with `SIGPIPE` before calling `fn main()`.
1535        ///
1536        /// What values that are valid and what they mean must be in sync
1537        /// across rustc and libstd, but we don't want it public in libstd,
1538        /// so we take a bit of an unusual approach with simple constants
1539        /// and an `include!()`.
1540        sigpipe: u8,
1541    },
1542}
1543
1544pub use rustc_hir::attrs::CrateType;
1545
1546#[derive(#[automatically_derived]
impl ::core::clone::Clone for Passes {
    #[inline]
    fn clone(&self) -> Passes {
        match self {
            Passes::Some(__self_0) =>
                Passes::Some(::core::clone::Clone::clone(__self_0)),
            Passes::All => Passes::All,
        }
    }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for Passes {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            Passes::Some(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Passes {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Passes::Some(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Some",
                    &__self_0),
            Passes::All => ::core::fmt::Formatter::write_str(f, "All"),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Passes {
    #[inline]
    fn eq(&self, other: &Passes) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (Passes::Some(__self_0), Passes::Some(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Passes {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Vec<String>>;
    }
}Eq, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for Passes {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        Passes::Some(ref __binding_0) => { 0usize }
                        Passes::All => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    Passes::Some(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    Passes::All => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for Passes {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        Passes::Some(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => { Passes::All }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Passes`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
1547pub enum Passes {
1548    Some(Vec<String>),
1549    All,
1550}
1551
1552impl Passes {
1553    fn is_empty(&self) -> bool {
1554        match *self {
1555            Passes::Some(ref v) => v.is_empty(),
1556            Passes::All => false,
1557        }
1558    }
1559
1560    pub(crate) fn extend(&mut self, passes: impl IntoIterator<Item = String>) {
1561        match *self {
1562            Passes::Some(ref mut v) => v.extend(passes),
1563            Passes::All => {}
1564        }
1565    }
1566}
1567
1568#[derive(#[automatically_derived]
impl ::core::clone::Clone for PAuthKey {
    #[inline]
    fn clone(&self) -> PAuthKey { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for PAuthKey { }Copy, #[automatically_derived]
impl ::core::hash::Hash for PAuthKey {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for PAuthKey {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self { PAuthKey::A => "A", PAuthKey::B => "B", })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for PAuthKey {
    #[inline]
    fn eq(&self, other: &PAuthKey) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq)]
1569pub enum PAuthKey {
1570    A,
1571    B,
1572}
1573
1574#[derive(#[automatically_derived]
impl ::core::clone::Clone for PacRet {
    #[inline]
    fn clone(&self) -> PacRet {
        let _: ::core::clone::AssertParamIsClone<bool>;
        let _: ::core::clone::AssertParamIsClone<PAuthKey>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for PacRet { }Copy, #[automatically_derived]
impl ::core::hash::Hash for PacRet {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.leaf, state);
        ::core::hash::Hash::hash(&self.pc, state);
        ::core::hash::Hash::hash(&self.key, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for PacRet {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f, "PacRet",
            "leaf", &self.leaf, "pc", &self.pc, "key", &&self.key)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for PacRet {
    #[inline]
    fn eq(&self, other: &PacRet) -> bool {
        self.leaf == other.leaf && self.pc == other.pc &&
            self.key == other.key
    }
}PartialEq)]
1575pub struct PacRet {
1576    pub leaf: bool,
1577    pub pc: bool,
1578    pub key: PAuthKey,
1579}
1580
1581#[derive(#[automatically_derived]
impl ::core::clone::Clone for BranchProtection {
    #[inline]
    fn clone(&self) -> BranchProtection {
        let _: ::core::clone::AssertParamIsClone<bool>;
        let _: ::core::clone::AssertParamIsClone<Option<PacRet>>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for BranchProtection { }Copy, #[automatically_derived]
impl ::core::hash::Hash for BranchProtection {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.bti, state);
        ::core::hash::Hash::hash(&self.pac_ret, state);
        ::core::hash::Hash::hash(&self.gcs, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for BranchProtection {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "BranchProtection", "bti", &self.bti, "pac_ret", &self.pac_ret,
            "gcs", &&self.gcs)
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for BranchProtection {
    #[inline]
    fn eq(&self, other: &BranchProtection) -> bool {
        self.bti == other.bti && self.gcs == other.gcs &&
            self.pac_ret == other.pac_ret
    }
}PartialEq, #[automatically_derived]
impl ::core::default::Default for BranchProtection {
    #[inline]
    fn default() -> BranchProtection {
        BranchProtection {
            bti: ::core::default::Default::default(),
            pac_ret: ::core::default::Default::default(),
            gcs: ::core::default::Default::default(),
        }
    }
}Default)]
1582pub struct BranchProtection {
1583    pub bti: bool,
1584    pub pac_ret: Option<PacRet>,
1585    pub gcs: bool,
1586}
1587
1588pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
1589    // First disallow some configuration given on the command line
1590    cfg::disallow_cfgs(sess, &user_cfg);
1591
1592    // Then combine the configuration requested by the session (command line) with
1593    // some default and generated configuration items.
1594    user_cfg.extend(cfg::default_configuration(sess));
1595    user_cfg
1596}
1597
1598pub fn build_target_config(
1599    early_dcx: &EarlyDiagCtxt,
1600    target: &TargetTuple,
1601    sysroot: &Path,
1602    unstable_options: bool,
1603) -> Target {
1604    match Target::search(target, sysroot, unstable_options) {
1605        Ok((target, warnings)) => {
1606            for warning in warnings.warning_messages() {
1607                early_dcx.early_warn(warning)
1608            }
1609
1610            if !#[allow(non_exhaustive_omitted_patterns)] match target.pointer_width {
    16 | 32 | 64 => true,
    _ => false,
}matches!(target.pointer_width, 16 | 32 | 64) {
1611                early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("target specification was invalid: unrecognized target-pointer-width {0}",
                target.pointer_width))
    })format!(
1612                    "target specification was invalid: unrecognized target-pointer-width {}",
1613                    target.pointer_width
1614                ))
1615            }
1616            target
1617        }
1618        Err(e) => {
1619            let mut err =
1620                early_dcx.early_struct_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("error loading target specification: {0}",
                e))
    })format!("error loading target specification: {e}"));
1621            err.help("run `rustc --print target-list` for a list of built-in targets");
1622            let typed = target.tuple();
1623            let limit = typed.len() / 3 + 1;
1624            if let Some(suggestion) = rustc_target::spec::TARGETS
1625                .iter()
1626                .filter_map(|&t| {
1627                    rustc_span::edit_distance::edit_distance_with_substrings(typed, t, limit)
1628                        .map(|d| (d, t))
1629                })
1630                .min_by_key(|(d, _)| *d)
1631                .map(|(_, t)| t)
1632            {
1633                err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("did you mean `{0}`?", suggestion))
    })format!("did you mean `{suggestion}`?"));
1634            }
1635            err.emit()
1636        }
1637    }
1638}
1639
1640#[derive(#[automatically_derived]
impl ::core::marker::Copy for OptionStability { }Copy, #[automatically_derived]
impl ::core::clone::Clone for OptionStability {
    #[inline]
    fn clone(&self) -> OptionStability { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for OptionStability {
    #[inline]
    fn eq(&self, other: &OptionStability) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for OptionStability {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for OptionStability {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                OptionStability::Stable => "Stable",
                OptionStability::Unstable => "Unstable",
            })
    }
}Debug)]
1641pub enum OptionStability {
1642    Stable,
1643    Unstable,
1644}
1645
1646#[derive(#[automatically_derived]
impl ::core::marker::Copy for OptionKind { }Copy, #[automatically_derived]
impl ::core::clone::Clone for OptionKind {
    #[inline]
    fn clone(&self) -> OptionKind { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for OptionKind {
    #[inline]
    fn eq(&self, other: &OptionKind) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for OptionKind {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for OptionKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                OptionKind::Opt => "Opt",
                OptionKind::Multi => "Multi",
                OptionKind::Flag => "Flag",
                OptionKind::FlagMulti => "FlagMulti",
            })
    }
}Debug)]
1647pub enum OptionKind {
1648    /// An option that takes a value, and cannot appear more than once (e.g. `--out-dir`).
1649    ///
1650    /// Corresponds to [`getopts::Options::optopt`].
1651    Opt,
1652
1653    /// An option that takes a value, and can appear multiple times (e.g. `--emit`).
1654    ///
1655    /// Corresponds to [`getopts::Options::optmulti`].
1656    Multi,
1657
1658    /// An option that does not take a value, and cannot appear more than once (e.g. `--help`).
1659    ///
1660    /// Corresponds to [`getopts::Options::optflag`].
1661    /// The `hint` string must be empty.
1662    Flag,
1663
1664    /// An option that does not take a value, and can appear multiple times (e.g. `-O`).
1665    ///
1666    /// Corresponds to [`getopts::Options::optflagmulti`].
1667    /// The `hint` string must be empty.
1668    FlagMulti,
1669}
1670
1671pub struct RustcOptGroup {
1672    /// The "primary" name for this option. Normally equal to `long_name`,
1673    /// except for options that don't have a long name, in which case
1674    /// `short_name` is used.
1675    ///
1676    /// This is needed when interacting with `getopts` in some situations,
1677    /// because if an option has both forms, that library treats the long name
1678    /// as primary and the short name as an alias.
1679    pub name: &'static str,
1680    stability: OptionStability,
1681    kind: OptionKind,
1682
1683    short_name: &'static str,
1684    long_name: &'static str,
1685    desc: &'static str,
1686    value_hint: &'static str,
1687
1688    /// If true, this option should not be printed by `rustc --help`, but
1689    /// should still be printed by `rustc --help -v`.
1690    pub is_verbose_help_only: bool,
1691}
1692
1693impl RustcOptGroup {
1694    pub fn is_stable(&self) -> bool {
1695        self.stability == OptionStability::Stable
1696    }
1697
1698    pub fn apply(&self, options: &mut getopts::Options) {
1699        let &Self { short_name, long_name, desc, value_hint, .. } = self;
1700        match self.kind {
1701            OptionKind::Opt => options.optopt(short_name, long_name, desc, value_hint),
1702            OptionKind::Multi => options.optmulti(short_name, long_name, desc, value_hint),
1703            OptionKind::Flag => options.optflag(short_name, long_name, desc),
1704            OptionKind::FlagMulti => options.optflagmulti(short_name, long_name, desc),
1705        };
1706    }
1707
1708    /// This is for diagnostics-only.
1709    pub fn long_name(&self) -> &str {
1710        self.long_name
1711    }
1712}
1713
1714pub fn make_opt(
1715    stability: OptionStability,
1716    kind: OptionKind,
1717    short_name: &'static str,
1718    long_name: &'static str,
1719    desc: &'static str,
1720    value_hint: &'static str,
1721) -> RustcOptGroup {
1722    // "Flag" options don't have a value, and therefore don't have a value hint.
1723    match kind {
1724        OptionKind::Opt | OptionKind::Multi => {}
1725        OptionKind::Flag | OptionKind::FlagMulti => match (&value_hint, &"") {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
}assert_eq!(value_hint, ""),
1726    }
1727    RustcOptGroup {
1728        name: cmp::max_by_key(short_name, long_name, |s| s.len()),
1729        stability,
1730        kind,
1731        short_name,
1732        long_name,
1733        desc,
1734        value_hint,
1735        is_verbose_help_only: false,
1736    }
1737}
1738
1739static EDITION_STRING: LazyLock<String> = LazyLock::new(|| {
1740    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Specify which edition of the compiler to use when compiling code. The default is {0} and the latest stable edition is {1}.",
                DEFAULT_EDITION, LATEST_STABLE_EDITION))
    })format!(
1741        "Specify which edition of the compiler to use when compiling code. \
1742The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE_EDITION}."
1743    )
1744});
1745
1746static EMIT_HELP: LazyLock<String> = LazyLock::new(|| {
1747    let mut result =
1748        String::from("Comma separated list of types of output for the compiler to emit.\n");
1749    result.push_str("Each TYPE has the default FILE name:\n");
1750
1751    for output in OutputType::iter_all() {
1752        result.push_str(&::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("*  {0} - {1}\n",
                output.shorthand(), output.default_filename()))
    })format!("*  {} - {}\n", output.shorthand(), output.default_filename()));
1753    }
1754
1755    result
1756});
1757
1758/// Returns all rustc command line options, including metadata for
1759/// each option, such as whether the option is stable.
1760///
1761/// # Option style guidelines
1762///
1763/// - `<param>`: Indicates a required parameter
1764/// - `[param]`: Indicates an optional parameter
1765/// - `|`: Indicates a mutually exclusive option
1766/// - `*`: a list element with description
1767pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
1768    use OptionKind::{Flag, FlagMulti, Multi, Opt};
1769    use OptionStability::{Stable, Unstable};
1770
1771    use self::make_opt as opt;
1772
1773    let mut options = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [opt(Stable, Flag, "h", "help", "Display this message", ""),
                opt(Stable, Multi, "", "cfg",
                    "Configure the compilation environment.\n\
                SPEC supports the syntax `<NAME>[=\"<VALUE>\"]`.",
                    "<SPEC>"),
                opt(Stable, Multi, "", "check-cfg",
                    "Provide list of expected cfgs for checking", "<SPEC>"),
                opt(Stable, Multi, "L", "",
                    "Add a directory to the library search path. \
                The optional KIND can be one of <dependency|crate|native|framework|all> (default: all).",
                    "[<KIND>=]<PATH>"),
                opt(Stable, Multi, "l", "",
                    "Link the generated crate(s) to the specified native\n\
                library NAME. The optional KIND can be one of\n\
                <static|framework|dylib> (default: dylib).\n\
                Optional comma separated MODIFIERS\n\
                <bundle|verbatim|whole-archive|as-needed>\n\
                may be specified each with a prefix of either '+' to\n\
                enable or '-' to disable.",
                    "[<KIND>[:<MODIFIERS>]=]<NAME>[:<RENAME>]"),
                make_crate_type_option(),
                opt(Stable, Opt, "", "crate-name",
                    "Specify the name of the crate being built", "<NAME>"),
                opt(Stable, Opt, "", "edition", &EDITION_STRING,
                    EDITION_NAME_LIST),
                opt(Stable, Multi, "", "emit", &EMIT_HELP, "<TYPE>[=<FILE>]"),
                opt(Stable, Multi, "", "print", &print_request::PRINT_HELP,
                    "<INFO>[=<FILE>]"),
                opt(Stable, FlagMulti, "g", "",
                    "Equivalent to -C debuginfo=2", ""),
                opt(Stable, FlagMulti, "O", "",
                    "Equivalent to -C opt-level=3", ""),
                opt(Stable, Opt, "o", "", "Write output to FILENAME",
                    "<FILENAME>"),
                opt(Stable, Opt, "", "out-dir",
                    "Write output to compiler-chosen filename in DIR", "<DIR>"),
                opt(Stable, Opt, "", "explain",
                    "Provide a detailed explanation of an error message",
                    "<OPT>"),
                opt(Stable, Flag, "", "test", "Build a test harness", ""),
                opt(Stable, Opt, "", "target",
                    "Target tuple for which the code is compiled", "<TARGET>"),
                opt(Stable, Multi, "A", "allow", "Set lint allowed",
                    "<LINT>"),
                opt(Stable, Multi, "W", "warn", "Set lint warnings",
                    "<LINT>"),
                opt(Stable, Multi, "", "force-warn", "Set lint force-warn",
                    "<LINT>"),
                opt(Stable, Multi, "D", "deny", "Set lint denied", "<LINT>"),
                opt(Stable, Multi, "F", "forbid", "Set lint forbidden",
                    "<LINT>"),
                opt(Stable, Multi, "", "cap-lints",
                    "Set the most restrictive lint level. More restrictive lints are capped at this level",
                    "<LEVEL>"),
                opt(Stable, Multi, "C", "codegen", "Set a codegen option",
                    "<OPT>[=<VALUE>]"),
                opt(Stable, Flag, "V", "version",
                    "Print version info and exit", ""),
                opt(Stable, Flag, "v", "verbose", "Use verbose output", "")]))vec![
1774        opt(Stable, Flag, "h", "help", "Display this message", ""),
1775        opt(
1776            Stable,
1777            Multi,
1778            "",
1779            "cfg",
1780            "Configure the compilation environment.\n\
1781                SPEC supports the syntax `<NAME>[=\"<VALUE>\"]`.",
1782            "<SPEC>",
1783        ),
1784        opt(Stable, Multi, "", "check-cfg", "Provide list of expected cfgs for checking", "<SPEC>"),
1785        opt(
1786            Stable,
1787            Multi,
1788            "L",
1789            "",
1790            "Add a directory to the library search path. \
1791                The optional KIND can be one of <dependency|crate|native|framework|all> (default: all).",
1792            "[<KIND>=]<PATH>",
1793        ),
1794        opt(
1795            Stable,
1796            Multi,
1797            "l",
1798            "",
1799            "Link the generated crate(s) to the specified native\n\
1800                library NAME. The optional KIND can be one of\n\
1801                <static|framework|dylib> (default: dylib).\n\
1802                Optional comma separated MODIFIERS\n\
1803                <bundle|verbatim|whole-archive|as-needed>\n\
1804                may be specified each with a prefix of either '+' to\n\
1805                enable or '-' to disable.",
1806            "[<KIND>[:<MODIFIERS>]=]<NAME>[:<RENAME>]",
1807        ),
1808        make_crate_type_option(),
1809        opt(Stable, Opt, "", "crate-name", "Specify the name of the crate being built", "<NAME>"),
1810        opt(Stable, Opt, "", "edition", &EDITION_STRING, EDITION_NAME_LIST),
1811        opt(Stable, Multi, "", "emit", &EMIT_HELP, "<TYPE>[=<FILE>]"),
1812        opt(Stable, Multi, "", "print", &print_request::PRINT_HELP, "<INFO>[=<FILE>]"),
1813        opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""),
1814        opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""),
1815        opt(Stable, Opt, "o", "", "Write output to FILENAME", "<FILENAME>"),
1816        opt(Stable, Opt, "", "out-dir", "Write output to compiler-chosen filename in DIR", "<DIR>"),
1817        opt(
1818            Stable,
1819            Opt,
1820            "",
1821            "explain",
1822            "Provide a detailed explanation of an error message",
1823            "<OPT>",
1824        ),
1825        opt(Stable, Flag, "", "test", "Build a test harness", ""),
1826        opt(Stable, Opt, "", "target", "Target tuple for which the code is compiled", "<TARGET>"),
1827        opt(Stable, Multi, "A", "allow", "Set lint allowed", "<LINT>"),
1828        opt(Stable, Multi, "W", "warn", "Set lint warnings", "<LINT>"),
1829        opt(Stable, Multi, "", "force-warn", "Set lint force-warn", "<LINT>"),
1830        opt(Stable, Multi, "D", "deny", "Set lint denied", "<LINT>"),
1831        opt(Stable, Multi, "F", "forbid", "Set lint forbidden", "<LINT>"),
1832        opt(
1833            Stable,
1834            Multi,
1835            "",
1836            "cap-lints",
1837            "Set the most restrictive lint level. More restrictive lints are capped at this level",
1838            "<LEVEL>",
1839        ),
1840        opt(Stable, Multi, "C", "codegen", "Set a codegen option", "<OPT>[=<VALUE>]"),
1841        opt(Stable, Flag, "V", "version", "Print version info and exit", ""),
1842        opt(Stable, Flag, "v", "verbose", "Use verbose output", ""),
1843    ];
1844
1845    // Options in this list are hidden from `rustc --help` by default, but are
1846    // shown by `rustc --help -v`.
1847    let verbose_only = [
1848        opt(
1849            Stable,
1850            Multi,
1851            "",
1852            "extern",
1853            "Specify where an external rust library is located",
1854            "<NAME>[=<PATH>]",
1855        ),
1856        opt(Stable, Opt, "", "sysroot", "Override the system root", "<PATH>"),
1857        opt(Unstable, Multi, "Z", "", "Set unstable / perma-unstable options", "<FLAG>"),
1858        opt(
1859            Stable,
1860            Opt,
1861            "",
1862            "error-format",
1863            "How errors and other messages are produced",
1864            "<human|json|short>",
1865        ),
1866        opt(Stable, Multi, "", "json", "Configure the JSON output of the compiler", "<CONFIG>"),
1867        opt(
1868            Stable,
1869            Opt,
1870            "",
1871            "color",
1872            "Configure coloring of output:
1873                * auto   = colorize, if output goes to a tty (default);
1874                * always = always colorize output;
1875                * never  = never colorize output",
1876            "<auto|always|never>",
1877        ),
1878        opt(
1879            Stable,
1880            Opt,
1881            "",
1882            "diagnostic-width",
1883            "Inform rustc of the width of the output so that diagnostics can be truncated to fit",
1884            "<WIDTH>",
1885        ),
1886        opt(
1887            Stable,
1888            Multi,
1889            "",
1890            "remap-path-prefix",
1891            "Remap source names in all output (compiler messages and output files)",
1892            "<FROM>=<TO>",
1893        ),
1894        opt(
1895            Stable,
1896            Opt,
1897            "",
1898            "remap-path-scope",
1899            "Defines which scopes of paths should be remapped by `--remap-path-prefix`",
1900            "<macro,diagnostics,debuginfo,coverage,object,all>",
1901        ),
1902        opt(Unstable, Multi, "", "env-set", "Inject an environment variable", "<VAR>=<VALUE>"),
1903    ];
1904    options.extend(verbose_only.into_iter().map(|mut opt| {
1905        opt.is_verbose_help_only = true;
1906        opt
1907    }));
1908
1909    options
1910}
1911
1912pub fn get_cmd_lint_options(
1913    early_dcx: &EarlyDiagCtxt,
1914    matches: &getopts::Matches,
1915) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
1916    let mut lint_opts_with_position = ::alloc::vec::Vec::new()vec![];
1917    let mut describe_lints = false;
1918
1919    for level in [lint::Allow, lint::Warn, lint::ForceWarn, lint::Deny, lint::Forbid] {
1920        for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
1921            if lint_name == "help" {
1922                describe_lints = true;
1923            } else {
1924                lint_opts_with_position.push((arg_pos, lint_name.replace('-', "_"), level));
1925            }
1926        }
1927    }
1928
1929    lint_opts_with_position.sort_by_key(|x| x.0);
1930    let lint_opts = lint_opts_with_position
1931        .iter()
1932        .cloned()
1933        .map(|(_, lint_name, level)| (lint_name, level))
1934        .collect();
1935
1936    let lint_cap = matches.opt_str("cap-lints").map(|cap| {
1937        lint::Level::from_str(&cap)
1938            .unwrap_or_else(|| early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unknown lint level: `{0}`", cap))
    })format!("unknown lint level: `{cap}`")))
1939    });
1940
1941    (lint_opts, describe_lints, lint_cap)
1942}
1943
1944/// Parses the `--color` flag.
1945pub fn parse_color(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> ColorConfig {
1946    match matches.opt_str("color").as_deref() {
1947        Some("auto") => ColorConfig::Auto,
1948        Some("always") => ColorConfig::Always,
1949        Some("never") => ColorConfig::Never,
1950
1951        None => ColorConfig::Auto,
1952
1953        Some(arg) => early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("argument for `--color` must be auto, always or never (instead was `{0}`)",
                arg))
    })format!(
1954            "argument for `--color` must be auto, \
1955                 always or never (instead was `{arg}`)"
1956        )),
1957    }
1958}
1959
1960/// Possible json config files
1961pub struct JsonConfig {
1962    pub json_rendered: HumanReadableErrorType,
1963    pub json_color: ColorConfig,
1964    json_artifact_notifications: bool,
1965    /// Output start and end timestamps of several high-level compilation sections
1966    /// (frontend, backend, linker).
1967    json_timings: bool,
1968    pub json_unused_externs: JsonUnusedExterns,
1969    json_future_incompat: bool,
1970}
1971
1972/// Report unused externs in event stream
1973#[derive(#[automatically_derived]
impl ::core::marker::Copy for JsonUnusedExterns { }Copy, #[automatically_derived]
impl ::core::clone::Clone for JsonUnusedExterns {
    #[inline]
    fn clone(&self) -> JsonUnusedExterns { *self }
}Clone)]
1974pub enum JsonUnusedExterns {
1975    /// Do not
1976    No,
1977    /// Report, but do not exit with failure status for deny/forbid
1978    Silent,
1979    /// Report, and also exit with failure status for deny/forbid
1980    Loud,
1981}
1982
1983impl JsonUnusedExterns {
1984    pub fn is_enabled(&self) -> bool {
1985        match self {
1986            JsonUnusedExterns::No => false,
1987            JsonUnusedExterns::Loud | JsonUnusedExterns::Silent => true,
1988        }
1989    }
1990
1991    pub fn is_loud(&self) -> bool {
1992        match self {
1993            JsonUnusedExterns::No | JsonUnusedExterns::Silent => false,
1994            JsonUnusedExterns::Loud => true,
1995        }
1996    }
1997}
1998
1999/// Parse the `--json` flag.
2000///
2001/// The first value returned is how to render JSON diagnostics, and the second
2002/// is whether or not artifact notifications are enabled.
2003pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> JsonConfig {
2004    let mut json_rendered = HumanReadableErrorType { short: false, unicode: false };
2005    let mut json_color = ColorConfig::Never;
2006    let mut json_artifact_notifications = false;
2007    let mut json_unused_externs = JsonUnusedExterns::No;
2008    let mut json_future_incompat = false;
2009    let mut json_timings = false;
2010    for option in matches.opt_strs("json") {
2011        // For now conservatively forbid `--color` with `--json` since `--json`
2012        // won't actually be emitting any colors and anything colorized is
2013        // embedded in a diagnostic message anyway.
2014        if matches.opt_str("color").is_some() {
2015            early_dcx.early_fatal("cannot specify the `--color` option with `--json`");
2016        }
2017
2018        for sub_option in option.split(',') {
2019            match sub_option {
2020                "diagnostic-short" => {
2021                    json_rendered = HumanReadableErrorType { short: true, unicode: false };
2022                }
2023                "diagnostic-unicode" => {
2024                    json_rendered = HumanReadableErrorType { short: false, unicode: true };
2025                }
2026                "diagnostic-rendered-ansi" => json_color = ColorConfig::Always,
2027                "artifacts" => json_artifact_notifications = true,
2028                "timings" => json_timings = true,
2029                "unused-externs" => json_unused_externs = JsonUnusedExterns::Loud,
2030                "unused-externs-silent" => json_unused_externs = JsonUnusedExterns::Silent,
2031                "future-incompat" => json_future_incompat = true,
2032                s => early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unknown `--json` option `{0}`", s))
    })format!("unknown `--json` option `{s}`")),
2033            }
2034        }
2035    }
2036
2037    JsonConfig {
2038        json_rendered,
2039        json_color,
2040        json_artifact_notifications,
2041        json_timings,
2042        json_unused_externs,
2043        json_future_incompat,
2044    }
2045}
2046
2047/// Parses the `--error-format` flag.
2048pub fn parse_error_format(
2049    early_dcx: &mut EarlyDiagCtxt,
2050    matches: &getopts::Matches,
2051    color_config: ColorConfig,
2052    json_color: ColorConfig,
2053    json_rendered: HumanReadableErrorType,
2054) -> ErrorOutputType {
2055    let default_kind = HumanReadableErrorType { short: false, unicode: false };
2056    // We need the `opts_present` check because the driver will send us Matches
2057    // with only stable options if no unstable options are used. Since error-format
2058    // is unstable, it will not be present. We have to use `opts_present` not
2059    // `opt_present` because the latter will panic.
2060    let error_format = if matches.opts_present(&["error-format".to_owned()]) {
2061        match matches.opt_str("error-format").as_deref() {
2062            None | Some("human") => {
2063                ErrorOutputType::HumanReadable { color_config, kind: default_kind }
2064            }
2065            Some("json") => {
2066                ErrorOutputType::Json { pretty: false, json_rendered, color_config: json_color }
2067            }
2068            Some("pretty-json") => {
2069                ErrorOutputType::Json { pretty: true, json_rendered, color_config: json_color }
2070            }
2071            Some("short") => ErrorOutputType::HumanReadable {
2072                kind: HumanReadableErrorType { short: true, unicode: false },
2073                color_config,
2074            },
2075            Some("human-unicode") => ErrorOutputType::HumanReadable {
2076                kind: HumanReadableErrorType { short: false, unicode: true },
2077                color_config,
2078            },
2079            Some(arg) => {
2080                early_dcx.set_error_format(ErrorOutputType::HumanReadable {
2081                    color_config,
2082                    kind: default_kind,
2083                });
2084                early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("argument for `--error-format` must be `human`, `human-unicode`, `json`, `pretty-json` or `short` (instead was `{0}`)",
                arg))
    })format!(
2085                    "argument for `--error-format` must be `human`, `human-unicode`, \
2086                    `json`, `pretty-json` or `short` (instead was `{arg}`)"
2087                ))
2088            }
2089        }
2090    } else {
2091        ErrorOutputType::HumanReadable { color_config, kind: default_kind }
2092    };
2093
2094    match error_format {
2095        ErrorOutputType::Json { .. } => {}
2096
2097        // Conservatively require that the `--json` argument is coupled with
2098        // `--error-format=json`. This means that `--json` is specified we
2099        // should actually be emitting JSON blobs.
2100        _ if !matches.opt_strs("json").is_empty() => {
2101            early_dcx.early_fatal("using `--json` requires also using `--error-format=json`");
2102        }
2103
2104        _ => {}
2105    }
2106
2107    error_format
2108}
2109
2110pub fn parse_crate_edition(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Edition {
2111    let edition = match matches.opt_str("edition") {
2112        Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| {
2113            early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("argument for `--edition` must be one of: {0}. (instead was `{1}`)",
                EDITION_NAME_LIST, arg))
    })format!(
2114                "argument for `--edition` must be one of: \
2115                     {EDITION_NAME_LIST}. (instead was `{arg}`)"
2116            ))
2117        }),
2118        None => DEFAULT_EDITION,
2119    };
2120
2121    if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) {
2122        let is_nightly = nightly_options::match_is_nightly_build(matches);
2123        let msg = if !is_nightly {
2124            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the crate requires edition {0}, but the latest edition supported by this Rust version is {1}",
                edition, LATEST_STABLE_EDITION))
    })format!(
2125                "the crate requires edition {edition}, but the latest edition supported by this Rust version is {LATEST_STABLE_EDITION}"
2126            )
2127        } else {
2128            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("edition {0} is unstable and only available with -Z unstable-options",
                edition))
    })format!("edition {edition} is unstable and only available with -Z unstable-options")
2129        };
2130        early_dcx.early_fatal(msg)
2131    }
2132
2133    edition
2134}
2135
2136fn check_error_format_stability(
2137    early_dcx: &EarlyDiagCtxt,
2138    unstable_opts: &UnstableOptions,
2139    is_nightly_build: bool,
2140    format: ErrorOutputType,
2141) {
2142    if unstable_opts.unstable_options || is_nightly_build {
2143        return;
2144    }
2145    let format = match format {
2146        ErrorOutputType::Json { pretty: true, .. } => "pretty-json",
2147        ErrorOutputType::HumanReadable { kind, .. } => match kind {
2148            HumanReadableErrorType { unicode: true, .. } => "human-unicode",
2149            _ => return,
2150        },
2151        _ => return,
2152    };
2153    early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`--error-format={0}` is unstable",
                format))
    })format!("`--error-format={format}` is unstable"))
2154}
2155
2156fn parse_output_types(
2157    early_dcx: &EarlyDiagCtxt,
2158    unstable_opts: &UnstableOptions,
2159    matches: &getopts::Matches,
2160) -> OutputTypes {
2161    let mut output_types = BTreeMap::new();
2162    if !unstable_opts.parse_crate_root_only {
2163        for list in matches.opt_strs("emit") {
2164            for output_type in list.split(',') {
2165                let (shorthand, path) = split_out_file_name(output_type);
2166                let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| {
2167                    early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unknown emission type: `{1}` - expected one of: {0}",
                OutputType::shorthands_display(), shorthand))
    })format!(
2168                        "unknown emission type: `{shorthand}` - expected one of: {display}",
2169                        display = OutputType::shorthands_display(),
2170                    ))
2171                });
2172                if output_type == OutputType::ThinLinkBitcode && !unstable_opts.unstable_options {
2173                    early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} requested but -Zunstable-options not specified",
                OutputType::ThinLinkBitcode.shorthand()))
    })format!(
2174                        "{} requested but -Zunstable-options not specified",
2175                        OutputType::ThinLinkBitcode.shorthand()
2176                    ));
2177                }
2178                output_types.insert(output_type, path);
2179            }
2180        }
2181    };
2182    if output_types.is_empty() {
2183        output_types.insert(OutputType::Exe, None);
2184    }
2185    OutputTypes(output_types)
2186}
2187
2188fn split_out_file_name(arg: &str) -> (&str, Option<OutFileName>) {
2189    match arg.split_once('=') {
2190        None => (arg, None),
2191        Some((kind, "-")) => (kind, Some(OutFileName::Stdout)),
2192        Some((kind, path)) => (kind, Some(OutFileName::Real(PathBuf::from(path)))),
2193    }
2194}
2195
2196fn should_override_cgus_and_disable_thinlto(
2197    early_dcx: &EarlyDiagCtxt,
2198    output_types: &OutputTypes,
2199    matches: &getopts::Matches,
2200    mut codegen_units: Option<usize>,
2201) -> (bool, Option<usize>) {
2202    let mut disable_local_thinlto = false;
2203    // Issue #30063: if user requests LLVM-related output to one
2204    // particular path, disable codegen-units.
2205    let incompatible: Vec<_> = output_types
2206        .0
2207        .iter()
2208        .map(|ot_path| ot_path.0)
2209        .filter(|ot| !ot.is_compatible_with_codegen_units_and_single_output_file())
2210        .map(|ot| ot.shorthand())
2211        .collect();
2212    if !incompatible.is_empty() {
2213        match codegen_units {
2214            Some(n) if n > 1 => {
2215                if matches.opt_present("o") {
2216                    for ot in &incompatible {
2217                        early_dcx.early_warn(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`--emit={0}` with `-o` incompatible with `-C codegen-units=N` for N > 1",
                ot))
    })format!(
2218                            "`--emit={ot}` with `-o` incompatible with \
2219                                 `-C codegen-units=N` for N > 1",
2220                        ));
2221                    }
2222                    early_dcx.early_warn("resetting to default -C codegen-units=1");
2223                    codegen_units = Some(1);
2224                    disable_local_thinlto = true;
2225                }
2226            }
2227            _ => {
2228                codegen_units = Some(1);
2229                disable_local_thinlto = true;
2230            }
2231        }
2232    }
2233
2234    if codegen_units == Some(0) {
2235        early_dcx.early_fatal("value for codegen units must be a positive non-zero integer");
2236    }
2237
2238    (disable_local_thinlto, codegen_units)
2239}
2240
2241pub fn parse_target_triple(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> TargetTuple {
2242    match matches.opt_str("target") {
2243        Some(target) if target.ends_with(".json") => {
2244            let path = Path::new(&target);
2245            TargetTuple::from_path(path).unwrap_or_else(|_| {
2246                early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("target file {0:?} does not exist",
                path))
    })format!("target file {path:?} does not exist"))
2247            })
2248        }
2249        Some(target) => TargetTuple::TargetTuple(target),
2250        _ => TargetTuple::from_tuple(host_tuple()),
2251    }
2252}
2253
2254fn parse_opt_level(
2255    early_dcx: &EarlyDiagCtxt,
2256    matches: &getopts::Matches,
2257    cg: &CodegenOptions,
2258) -> OptLevel {
2259    // The `-O` and `-C opt-level` flags specify the same setting, so we want to be able
2260    // to use them interchangeably. However, because they're technically different flags,
2261    // we need to work out manually which should take precedence if both are supplied (i.e.
2262    // the rightmost flag). We do this by finding the (rightmost) position of both flags and
2263    // comparing them. Note that if a flag is not found, its position will be `None`, which
2264    // always compared less than `Some(_)`.
2265    let max_o = matches.opt_positions("O").into_iter().max();
2266    let max_c = matches
2267        .opt_strs_pos("C")
2268        .into_iter()
2269        .flat_map(|(i, s)| {
2270            // NB: This can match a string without `=`.
2271            if let Some("opt-level") = s.split('=').next() { Some(i) } else { None }
2272        })
2273        .max();
2274    if max_o > max_c {
2275        OptLevel::Aggressive
2276    } else {
2277        match cg.opt_level.as_ref() {
2278            "0" => OptLevel::No,
2279            "1" => OptLevel::Less,
2280            "2" => OptLevel::More,
2281            "3" => OptLevel::Aggressive,
2282            "s" => OptLevel::Size,
2283            "z" => OptLevel::SizeMin,
2284            arg => {
2285                early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("optimization level needs to be between 0-3, s or z (instead was `{0}`)",
                arg))
    })format!(
2286                    "optimization level needs to be \
2287                            between 0-3, s or z (instead was `{arg}`)"
2288                ));
2289            }
2290        }
2291    }
2292}
2293
2294fn select_debuginfo(matches: &getopts::Matches, cg: &CodegenOptions) -> DebugInfo {
2295    let max_g = matches.opt_positions("g").into_iter().max();
2296    let max_c = matches
2297        .opt_strs_pos("C")
2298        .into_iter()
2299        .flat_map(|(i, s)| {
2300            // NB: This can match a string without `=`.
2301            if let Some("debuginfo") = s.split('=').next() { Some(i) } else { None }
2302        })
2303        .max();
2304    if max_g > max_c { DebugInfo::Full } else { cg.debuginfo }
2305}
2306
2307pub fn parse_externs(
2308    early_dcx: &EarlyDiagCtxt,
2309    matches: &getopts::Matches,
2310    unstable_opts: &UnstableOptions,
2311) -> Externs {
2312    let is_unstable_enabled = unstable_opts.unstable_options;
2313    let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new();
2314    for arg in matches.opt_strs("extern") {
2315        let ExternOpt { crate_name: name, path, options } =
2316            split_extern_opt(early_dcx, unstable_opts, &arg).unwrap_or_else(|e| e.emit());
2317
2318        let entry = externs.entry(name.to_owned());
2319
2320        use std::collections::btree_map::Entry;
2321
2322        let entry = if let Some(path) = path {
2323            // --extern prelude_name=some_file.rlib
2324            let path = CanonicalizedPath::new(path);
2325            match entry {
2326                Entry::Vacant(vacant) => {
2327                    let files = BTreeSet::from_iter(iter::once(path));
2328                    vacant.insert(ExternEntry::new(ExternLocation::ExactPaths(files)))
2329                }
2330                Entry::Occupied(occupied) => {
2331                    let ext_ent = occupied.into_mut();
2332                    match ext_ent {
2333                        ExternEntry { location: ExternLocation::ExactPaths(files), .. } => {
2334                            files.insert(path);
2335                        }
2336                        ExternEntry {
2337                            location: location @ ExternLocation::FoundInLibrarySearchDirectories,
2338                            ..
2339                        } => {
2340                            // Exact paths take precedence over search directories.
2341                            let files = BTreeSet::from_iter(iter::once(path));
2342                            *location = ExternLocation::ExactPaths(files);
2343                        }
2344                    }
2345                    ext_ent
2346                }
2347            }
2348        } else {
2349            // --extern prelude_name
2350            match entry {
2351                Entry::Vacant(vacant) => {
2352                    vacant.insert(ExternEntry::new(ExternLocation::FoundInLibrarySearchDirectories))
2353                }
2354                Entry::Occupied(occupied) => {
2355                    // Ignore if already specified.
2356                    occupied.into_mut()
2357                }
2358            }
2359        };
2360
2361        let mut is_private_dep = false;
2362        let mut add_prelude = true;
2363        let mut nounused_dep = false;
2364        let mut force = false;
2365        if let Some(opts) = options {
2366            if !is_unstable_enabled {
2367                early_dcx.early_fatal(
2368                    "the `-Z unstable-options` flag must also be passed to \
2369                     enable `--extern` options",
2370                );
2371            }
2372            for opt in opts.split(',') {
2373                match opt {
2374                    "priv" => is_private_dep = true,
2375                    "noprelude" => {
2376                        if let ExternLocation::ExactPaths(_) = &entry.location {
2377                            add_prelude = false;
2378                        } else {
2379                            early_dcx.early_fatal(
2380                                "the `noprelude` --extern option requires a file path",
2381                            );
2382                        }
2383                    }
2384                    "nounused" => nounused_dep = true,
2385                    "force" => force = true,
2386                    _ => early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unknown --extern option `{0}`",
                opt))
    })format!("unknown --extern option `{opt}`")),
2387                }
2388            }
2389        }
2390
2391        // Crates start out being not private, and go to being private `priv`
2392        // is specified.
2393        entry.is_private_dep |= is_private_dep;
2394        // likewise `nounused`
2395        entry.nounused_dep |= nounused_dep;
2396        // and `force`
2397        entry.force |= force;
2398        // If any flag is missing `noprelude`, then add to the prelude.
2399        entry.add_prelude |= add_prelude;
2400    }
2401    Externs(externs)
2402}
2403
2404fn parse_remap_path_prefix(
2405    early_dcx: &EarlyDiagCtxt,
2406    matches: &getopts::Matches,
2407    unstable_opts: &UnstableOptions,
2408) -> Vec<(PathBuf, PathBuf)> {
2409    let mut mapping: Vec<(PathBuf, PathBuf)> = matches
2410        .opt_strs("remap-path-prefix")
2411        .into_iter()
2412        .map(|remap| match remap.rsplit_once('=') {
2413            None => {
2414                early_dcx.early_fatal("--remap-path-prefix must contain '=' between FROM and TO")
2415            }
2416            Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)),
2417        })
2418        .collect();
2419    match &unstable_opts.remap_cwd_prefix {
2420        Some(to) => match std::env::current_dir() {
2421            Ok(cwd) => mapping.push((cwd, to.clone())),
2422            Err(_) => (),
2423        },
2424        None => (),
2425    };
2426    mapping
2427}
2428
2429fn parse_logical_env(
2430    early_dcx: &EarlyDiagCtxt,
2431    matches: &getopts::Matches,
2432) -> FxIndexMap<String, String> {
2433    let mut vars = FxIndexMap::default();
2434
2435    for arg in matches.opt_strs("env-set") {
2436        if let Some((name, val)) = arg.split_once('=') {
2437            vars.insert(name.to_string(), val.to_string());
2438        } else {
2439            early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`--env-set`: specify value for variable `{0}`",
                arg))
    })format!("`--env-set`: specify value for variable `{arg}`"));
2440        }
2441    }
2442
2443    vars
2444}
2445
2446// JUSTIFICATION: before wrapper fn is available
2447#[allow(rustc::bad_opt_access)]
2448pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches) -> Options {
2449    let color = parse_color(early_dcx, matches);
2450
2451    let edition = parse_crate_edition(early_dcx, matches);
2452
2453    let crate_name = matches.opt_str("crate-name");
2454    let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref());
2455    let JsonConfig {
2456        json_rendered,
2457        json_color,
2458        json_artifact_notifications,
2459        json_timings,
2460        json_unused_externs,
2461        json_future_incompat,
2462    } = parse_json(early_dcx, matches);
2463
2464    let error_format = parse_error_format(early_dcx, matches, color, json_color, json_rendered);
2465
2466    early_dcx.set_error_format(error_format);
2467
2468    let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| {
2469        early_dcx.early_fatal("`--diagnostic-width` must be an positive integer");
2470    });
2471
2472    let unparsed_crate_types = matches.opt_strs("crate-type");
2473    let crate_types = parse_crate_types_from_list(unparsed_crate_types)
2474        .unwrap_or_else(|e| early_dcx.early_fatal(e));
2475
2476    let mut collected_options = Default::default();
2477
2478    let mut unstable_opts = UnstableOptions::build(early_dcx, matches, &mut collected_options);
2479    let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches);
2480
2481    if !unstable_opts.unstable_options && json_timings {
2482        early_dcx.early_fatal("--json=timings is unstable and requires using `-Zunstable-options`");
2483    }
2484
2485    check_error_format_stability(
2486        early_dcx,
2487        &unstable_opts,
2488        unstable_features.is_nightly_build(),
2489        error_format,
2490    );
2491
2492    let output_types = parse_output_types(early_dcx, &unstable_opts, matches);
2493
2494    let mut cg = CodegenOptions::build(early_dcx, matches, &mut collected_options);
2495    let (disable_local_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto(
2496        early_dcx,
2497        &output_types,
2498        matches,
2499        cg.codegen_units,
2500    );
2501
2502    if unstable_opts.threads == 0 {
2503        early_dcx.early_fatal("value for threads must be a positive non-zero integer");
2504    }
2505
2506    if unstable_opts.threads == parse::MAX_THREADS_CAP {
2507        early_dcx.early_warn(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("number of threads was capped at {0}",
                parse::MAX_THREADS_CAP))
    })format!("number of threads was capped at {}", parse::MAX_THREADS_CAP));
2508    }
2509
2510    let incremental = cg.incremental.as_ref().map(PathBuf::from);
2511
2512    if cg.profile_generate.enabled() && cg.profile_use.is_some() {
2513        early_dcx.early_fatal("options `-C profile-generate` and `-C profile-use` are exclusive");
2514    }
2515
2516    if unstable_opts.profile_sample_use.is_some()
2517        && (cg.profile_generate.enabled() || cg.profile_use.is_some())
2518    {
2519        early_dcx.early_fatal(
2520            "option `-Z profile-sample-use` cannot be used with `-C profile-generate` or `-C profile-use`",
2521        );
2522    }
2523
2524    // Check for unstable values of `-C symbol-mangling-version`.
2525    // This is what prevents them from being used on stable compilers.
2526    match cg.symbol_mangling_version {
2527        // Stable values:
2528        None | Some(SymbolManglingVersion::V0) => {}
2529
2530        // Unstable values:
2531        Some(SymbolManglingVersion::Legacy) => {
2532            if !unstable_opts.unstable_options {
2533                early_dcx.early_fatal(
2534                    "`-C symbol-mangling-version=legacy` requires `-Z unstable-options`",
2535                );
2536            }
2537        }
2538        Some(SymbolManglingVersion::Hashed) => {
2539            if !unstable_opts.unstable_options {
2540                early_dcx.early_fatal(
2541                    "`-C symbol-mangling-version=hashed` requires `-Z unstable-options`",
2542                );
2543            }
2544        }
2545    }
2546
2547    if cg.instrument_coverage != InstrumentCoverage::No {
2548        if cg.profile_generate.enabled() || cg.profile_use.is_some() {
2549            early_dcx.early_fatal(
2550                "option `-C instrument-coverage` is not compatible with either `-C profile-use` \
2551                or `-C profile-generate`",
2552            );
2553        }
2554
2555        // `-C instrument-coverage` implies `-C symbol-mangling-version=v0` - to ensure consistent
2556        // and reversible name mangling. Note, LLVM coverage tools can analyze coverage over
2557        // multiple runs, including some changes to source code; so mangled names must be consistent
2558        // across compilations.
2559        match cg.symbol_mangling_version {
2560            None => cg.symbol_mangling_version = Some(SymbolManglingVersion::V0),
2561            Some(SymbolManglingVersion::Legacy) => {
2562                early_dcx.early_warn(
2563                    "-C instrument-coverage requires symbol mangling version `v0`, \
2564                    but `-C symbol-mangling-version=legacy` was specified",
2565                );
2566            }
2567            Some(SymbolManglingVersion::V0) => {}
2568            Some(SymbolManglingVersion::Hashed) => {
2569                early_dcx.early_warn(
2570                    "-C instrument-coverage requires symbol mangling version `v0`, \
2571                    but `-C symbol-mangling-version=hashed` was specified",
2572                );
2573            }
2574        }
2575    }
2576
2577    if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") {
2578        // FIXME: this is only mutation of UnstableOptions here, move into
2579        // UnstableOptions::build?
2580        unstable_opts.graphviz_font = graphviz_font;
2581    }
2582
2583    if !cg.embed_bitcode {
2584        match cg.lto {
2585            LtoCli::No | LtoCli::Unspecified => {}
2586            LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => {
2587                early_dcx.early_fatal("options `-C embed-bitcode=no` and `-C lto` are incompatible")
2588            }
2589        }
2590    }
2591
2592    let unstable_options_enabled = nightly_options::is_unstable_enabled(matches);
2593    if !unstable_options_enabled && cg.force_frame_pointers == FramePointer::NonLeaf {
2594        early_dcx.early_fatal(
2595            "`-Cforce-frame-pointers=non-leaf` or `always` also requires `-Zunstable-options` \
2596                and a nightly compiler",
2597        )
2598    }
2599
2600    if !nightly_options::is_unstable_enabled(matches) && !unstable_opts.offload.is_empty() {
2601        early_dcx.early_fatal(
2602            "`-Zoffload=Enable` also requires `-Zunstable-options` \
2603                and a nightly compiler",
2604        )
2605    }
2606
2607    let target_triple = parse_target_triple(early_dcx, matches);
2608
2609    // Ensure `-Z unstable-options` is required when using the unstable `-C link-self-contained` and
2610    // `-C linker-flavor` options.
2611    if !unstable_options_enabled {
2612        if let Err(error) = cg.link_self_contained.check_unstable_variants(&target_triple) {
2613            early_dcx.early_fatal(error);
2614        }
2615
2616        if let Some(flavor) = cg.linker_flavor {
2617            if flavor.is_unstable() {
2618                early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the linker flavor `{0}` is unstable, the `-Z unstable-options` flag must also be passed to use the unstable values",
                flavor.desc()))
    })format!(
2619                    "the linker flavor `{}` is unstable, the `-Z unstable-options` \
2620                        flag must also be passed to use the unstable values",
2621                    flavor.desc()
2622                ));
2623            }
2624        }
2625    }
2626
2627    // Check `-C link-self-contained` for consistency: individual components cannot be both enabled
2628    // and disabled at the same time.
2629    if let Some(erroneous_components) = cg.link_self_contained.check_consistency() {
2630        let names: String = erroneous_components
2631            .into_iter()
2632            .map(|c| c.as_str().unwrap())
2633            .intersperse(", ")
2634            .collect();
2635        early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("some `-C link-self-contained` components were both enabled and disabled: {0}",
                names))
    })format!(
2636            "some `-C link-self-contained` components were both enabled and disabled: {names}"
2637        ));
2638    }
2639
2640    let prints = print_request::collect_print_requests(early_dcx, &mut cg, &unstable_opts, matches);
2641
2642    // -Zretpoline-external-thunk also requires -Zretpoline
2643    if unstable_opts.retpoline_external_thunk {
2644        unstable_opts.retpoline = true;
2645        collected_options.target_modifiers.insert(
2646            OptionsTargetModifiers::UnstableOptions(UnstableOptionsTargetModifiers::Retpoline),
2647            "true".to_string(),
2648        );
2649    }
2650
2651    let cg = cg;
2652
2653    let opt_level = parse_opt_level(early_dcx, matches, &cg);
2654    // The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
2655    // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`)
2656    // for more details.
2657    let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No);
2658    let debuginfo = select_debuginfo(matches, &cg);
2659
2660    if !unstable_options_enabled {
2661        if let Err(error) = cg.linker_features.check_unstable_variants(&target_triple) {
2662            early_dcx.early_fatal(error);
2663        }
2664    }
2665
2666    if !unstable_options_enabled && cg.panic == Some(PanicStrategy::ImmediateAbort) {
2667        early_dcx.early_fatal(
2668            "`-Cpanic=immediate-abort` requires `-Zunstable-options` and a nightly compiler",
2669        )
2670    }
2671
2672    // Parse any `-l` flags, which link to native libraries.
2673    let libs = parse_native_libs(early_dcx, &unstable_opts, unstable_features, matches);
2674
2675    let test = matches.opt_present("test");
2676
2677    if !cg.remark.is_empty() && debuginfo == DebugInfo::None {
2678        early_dcx.early_warn("-C remark requires \"-C debuginfo=n\" to show source locations");
2679    }
2680
2681    if cg.remark.is_empty() && unstable_opts.remark_dir.is_some() {
2682        early_dcx
2683            .early_warn("using -Z remark-dir without enabling remarks using e.g. -C remark=all");
2684    }
2685
2686    let externs = parse_externs(early_dcx, matches, &unstable_opts);
2687
2688    let remap_path_prefix = parse_remap_path_prefix(early_dcx, matches, &unstable_opts);
2689    let remap_path_scope = parse_remap_path_scope(early_dcx, matches, &unstable_opts);
2690
2691    let pretty = parse_pretty(early_dcx, &unstable_opts);
2692
2693    // query-dep-graph is required if dump-dep-graph is given #106736
2694    if unstable_opts.dump_dep_graph && !unstable_opts.query_dep_graph {
2695        early_dcx.early_fatal("can't dump dependency graph without `-Z query-dep-graph`");
2696    }
2697
2698    let logical_env = parse_logical_env(early_dcx, matches);
2699
2700    let sysroot = Sysroot::new(matches.opt_str("sysroot").map(PathBuf::from));
2701
2702    let real_source_base_dir = |suffix: &str, confirm: &str| {
2703        let mut candidate = sysroot.path().join(suffix);
2704        if let Ok(metadata) = candidate.symlink_metadata() {
2705            // Replace the symlink bootstrap creates, with its destination.
2706            // We could try to use `fs::canonicalize` instead, but that might
2707            // produce unnecessarily verbose path.
2708            if metadata.file_type().is_symlink() {
2709                if let Ok(symlink_dest) = std::fs::read_link(&candidate) {
2710                    candidate = symlink_dest;
2711                }
2712            }
2713        }
2714
2715        // Only use this directory if it has a file we can expect to always find.
2716        candidate.join(confirm).is_file().then_some(candidate)
2717    };
2718
2719    let real_rust_source_base_dir =
2720        // This is the location used by the `rust-src` `rustup` component.
2721        real_source_base_dir("lib/rustlib/src/rust", "library/std/src/lib.rs");
2722
2723    let real_rustc_dev_source_base_dir =
2724        // This is the location used by the `rustc-dev` `rustup` component.
2725        real_source_base_dir("lib/rustlib/rustc-src/rust", "compiler/rustc/src/main.rs");
2726
2727    // We eagerly scan all files in each passed -L path. If the same directory is passed multiple
2728    // times, and the directory contains a lot of files, this can take a lot of time.
2729    // So we remove -L paths that were passed multiple times, and keep only the first occurrence.
2730    // We still have to keep the original order of the -L arguments.
2731    let search_paths: Vec<SearchPath> = {
2732        let mut seen_search_paths = FxHashSet::default();
2733        let search_path_matches: Vec<String> = matches.opt_strs("L");
2734        search_path_matches
2735            .iter()
2736            .filter(|p| seen_search_paths.insert(*p))
2737            .map(|path| {
2738                SearchPath::from_cli_opt(
2739                    sysroot.path(),
2740                    &target_triple,
2741                    early_dcx,
2742                    &path,
2743                    unstable_opts.unstable_options,
2744                )
2745            })
2746            .collect()
2747    };
2748
2749    // Ideally we would use `SourceMap::working_dir` instead, but we don't have access to it
2750    // so we manually create the potentially-remapped working directory
2751    let working_dir = {
2752        let working_dir = std::env::current_dir().unwrap_or_else(|e| {
2753            early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Current directory is invalid: {0}",
                e))
    })format!("Current directory is invalid: {e}"));
2754        });
2755
2756        let file_mapping = file_path_mapping(remap_path_prefix.clone(), remap_path_scope);
2757        file_mapping.to_real_filename(&RealFileName::empty(), &working_dir)
2758    };
2759
2760    let verbose = matches.opt_present("verbose") || unstable_opts.verbose_internals;
2761
2762    Options {
2763        crate_types,
2764        optimize: opt_level,
2765        debuginfo,
2766        lint_opts,
2767        lint_cap,
2768        describe_lints,
2769        output_types,
2770        search_paths,
2771        sysroot,
2772        target_triple,
2773        test,
2774        incremental,
2775        unstable_opts,
2776        prints,
2777        cg,
2778        error_format,
2779        diagnostic_width,
2780        externs,
2781        unstable_features,
2782        crate_name,
2783        libs,
2784        debug_assertions,
2785        actually_rustdoc: false,
2786        resolve_doc_links: ResolveDocLinks::ExportedMetadata,
2787        trimmed_def_paths: false,
2788        cli_forced_codegen_units: codegen_units,
2789        cli_forced_local_thinlto_off: disable_local_thinlto,
2790        remap_path_prefix,
2791        remap_path_scope,
2792        real_rust_source_base_dir,
2793        real_rustc_dev_source_base_dir,
2794        edition,
2795        json_artifact_notifications,
2796        json_timings,
2797        json_unused_externs,
2798        json_future_incompat,
2799        pretty,
2800        working_dir,
2801        color,
2802        logical_env,
2803        verbose,
2804        target_modifiers: collected_options.target_modifiers,
2805        mitigation_coverage_map: collected_options.mitigations,
2806    }
2807}
2808
2809fn parse_pretty(early_dcx: &EarlyDiagCtxt, unstable_opts: &UnstableOptions) -> Option<PpMode> {
2810    use PpMode::*;
2811
2812    let first = match unstable_opts.unpretty.as_deref()? {
2813        "normal" => Source(PpSourceMode::Normal),
2814        "identified" => Source(PpSourceMode::Identified),
2815        "expanded" => Source(PpSourceMode::Expanded),
2816        "expanded,identified" => Source(PpSourceMode::ExpandedIdentified),
2817        "expanded,hygiene" => Source(PpSourceMode::ExpandedHygiene),
2818        "ast-tree" => AstTree,
2819        "ast-tree,expanded" => AstTreeExpanded,
2820        "hir" => Hir(PpHirMode::Normal),
2821        "hir,identified" => Hir(PpHirMode::Identified),
2822        "hir,typed" => Hir(PpHirMode::Typed),
2823        "hir-tree" => HirTree,
2824        "thir-tree" => ThirTree,
2825        "thir-flat" => ThirFlat,
2826        "mir" => Mir,
2827        "stable-mir" => StableMir,
2828        "mir-cfg" => MirCFG,
2829        name => early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("argument to `unpretty` must be one of `normal`, `identified`, `expanded`, `expanded,identified`, `expanded,hygiene`, `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, `hir,typed`, `hir-tree`, `thir-tree`, `thir-flat`, `mir`, `stable-mir`, or `mir-cfg`; got {0}",
                name))
    })format!(
2830            "argument to `unpretty` must be one of `normal`, `identified`, \
2831                            `expanded`, `expanded,identified`, `expanded,hygiene`, \
2832                            `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
2833                            `hir,typed`, `hir-tree`, `thir-tree`, `thir-flat`, `mir`, `stable-mir`, or \
2834                            `mir-cfg`; got {name}"
2835        )),
2836    };
2837    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_session/src/config.rs:2837",
                        "rustc_session::config", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_session/src/config.rs"),
                        ::tracing_core::__macro_support::Option::Some(2837u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_session::config"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("got unpretty option: {0:?}",
                                                    first) as &dyn Value))])
            });
    } else { ; }
};debug!("got unpretty option: {first:?}");
2838    Some(first)
2839}
2840
2841pub fn make_crate_type_option() -> RustcOptGroup {
2842    make_opt(
2843        OptionStability::Stable,
2844        OptionKind::Multi,
2845        "",
2846        "crate-type",
2847        "Comma separated list of types of crates
2848                                for the compiler to emit",
2849        "<bin|lib|rlib|dylib|cdylib|staticlib|proc-macro>",
2850    )
2851}
2852
2853pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> {
2854    let mut crate_types: Vec<CrateType> = Vec::new();
2855    for unparsed_crate_type in &list_list {
2856        for part in unparsed_crate_type.split(',') {
2857            let new_part = match part {
2858                "lib" => CrateType::default(),
2859                "rlib" => CrateType::Rlib,
2860                "staticlib" => CrateType::StaticLib,
2861                "dylib" => CrateType::Dylib,
2862                "cdylib" => CrateType::Cdylib,
2863                "bin" => CrateType::Executable,
2864                "proc-macro" => CrateType::ProcMacro,
2865                "sdylib" => CrateType::Sdylib,
2866                _ => {
2867                    return Err(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unknown crate type: `{0}`, expected one of: `lib`, `rlib`, `staticlib`, `dylib`, `cdylib`, `bin`, `proc-macro`",
                part))
    })format!(
2868                        "unknown crate type: `{part}`, expected one of: \
2869                        `lib`, `rlib`, `staticlib`, `dylib`, `cdylib`, `bin`, `proc-macro`",
2870                    ));
2871                }
2872            };
2873            if !crate_types.contains(&new_part) {
2874                crate_types.push(new_part)
2875            }
2876        }
2877    }
2878
2879    Ok(crate_types)
2880}
2881
2882pub mod nightly_options {
2883    use rustc_feature::UnstableFeatures;
2884
2885    use super::{OptionStability, RustcOptGroup};
2886    use crate::EarlyDiagCtxt;
2887
2888    pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
2889        match_is_nightly_build(matches)
2890            && matches.opt_strs("Z").iter().any(|x| *x == "unstable-options")
2891    }
2892
2893    pub fn match_is_nightly_build(matches: &getopts::Matches) -> bool {
2894        is_nightly_build(matches.opt_str("crate-name").as_deref())
2895    }
2896
2897    fn is_nightly_build(krate: Option<&str>) -> bool {
2898        UnstableFeatures::from_environment(krate).is_nightly_build()
2899    }
2900
2901    pub fn check_nightly_options(
2902        early_dcx: &EarlyDiagCtxt,
2903        matches: &getopts::Matches,
2904        flags: &[RustcOptGroup],
2905    ) {
2906        let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options");
2907        let really_allows_unstable_options = match_is_nightly_build(matches);
2908        let mut nightly_options_on_stable = 0;
2909
2910        for opt in flags.iter() {
2911            if opt.stability == OptionStability::Stable {
2912                continue;
2913            }
2914            if !matches.opt_present(opt.name) {
2915                continue;
2916            }
2917            if opt.name != "Z" && !has_z_unstable_option {
2918                early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the `-Z unstable-options` flag must also be passed to enable the flag `{0}`",
                opt.name))
    })format!(
2919                    "the `-Z unstable-options` flag must also be passed to enable \
2920                         the flag `{}`",
2921                    opt.name
2922                ));
2923            }
2924            if really_allows_unstable_options {
2925                continue;
2926            }
2927            match opt.stability {
2928                OptionStability::Unstable => {
2929                    nightly_options_on_stable += 1;
2930                    let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the option `{0}` is only accepted on the nightly compiler",
                opt.name))
    })format!(
2931                        "the option `{}` is only accepted on the nightly compiler",
2932                        opt.name
2933                    );
2934                    // The non-zero nightly_options_on_stable will force an early_fatal eventually.
2935                    let _ = early_dcx.early_err(msg);
2936                }
2937                OptionStability::Stable => {}
2938            }
2939        }
2940        if nightly_options_on_stable > 0 {
2941            early_dcx
2942                .early_help("consider switching to a nightly toolchain: `rustup default nightly`");
2943            early_dcx.early_note("selecting a toolchain with `+toolchain` arguments require a rustup proxy; see <https://rust-lang.github.io/rustup/concepts/index.html>");
2944            early_dcx.early_note("for more information about Rust's stability policy, see <https://doc.rust-lang.org/book/appendix-07-nightly-rust.html#unstable-features>");
2945            early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} nightly option{1} were parsed",
                nightly_options_on_stable,
                if nightly_options_on_stable > 1 { "s" } else { "" }))
    })format!(
2946                "{} nightly option{} were parsed",
2947                nightly_options_on_stable,
2948                if nightly_options_on_stable > 1 { "s" } else { "" }
2949            ));
2950        }
2951    }
2952}
2953
2954#[derive(#[automatically_derived]
impl ::core::marker::Copy for PpSourceMode { }Copy, #[automatically_derived]
impl ::core::clone::Clone for PpSourceMode {
    #[inline]
    fn clone(&self) -> PpSourceMode { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for PpSourceMode {
    #[inline]
    fn eq(&self, other: &PpSourceMode) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for PpSourceMode {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                PpSourceMode::Normal => "Normal",
                PpSourceMode::Expanded => "Expanded",
                PpSourceMode::Identified => "Identified",
                PpSourceMode::ExpandedIdentified => "ExpandedIdentified",
                PpSourceMode::ExpandedHygiene => "ExpandedHygiene",
            })
    }
}Debug)]
2955pub enum PpSourceMode {
2956    /// `-Zunpretty=normal`
2957    Normal,
2958    /// `-Zunpretty=expanded`
2959    Expanded,
2960    /// `-Zunpretty=identified`
2961    Identified,
2962    /// `-Zunpretty=expanded,identified`
2963    ExpandedIdentified,
2964    /// `-Zunpretty=expanded,hygiene`
2965    ExpandedHygiene,
2966}
2967
2968#[derive(#[automatically_derived]
impl ::core::marker::Copy for PpHirMode { }Copy, #[automatically_derived]
impl ::core::clone::Clone for PpHirMode {
    #[inline]
    fn clone(&self) -> PpHirMode { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for PpHirMode {
    #[inline]
    fn eq(&self, other: &PpHirMode) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for PpHirMode {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                PpHirMode::Normal => "Normal",
                PpHirMode::Identified => "Identified",
                PpHirMode::Typed => "Typed",
            })
    }
}Debug)]
2969pub enum PpHirMode {
2970    /// `-Zunpretty=hir`
2971    Normal,
2972    /// `-Zunpretty=hir,identified`
2973    Identified,
2974    /// `-Zunpretty=hir,typed`
2975    Typed,
2976}
2977
2978#[derive(#[automatically_derived]
impl ::core::marker::Copy for PpMode { }Copy, #[automatically_derived]
impl ::core::clone::Clone for PpMode {
    #[inline]
    fn clone(&self) -> PpMode {
        let _: ::core::clone::AssertParamIsClone<PpSourceMode>;
        let _: ::core::clone::AssertParamIsClone<PpHirMode>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for PpMode {
    #[inline]
    fn eq(&self, other: &PpMode) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (PpMode::Source(__self_0), PpMode::Source(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (PpMode::Hir(__self_0), PpMode::Hir(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for PpMode {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            PpMode::Source(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Source",
                    &__self_0),
            PpMode::AstTree =>
                ::core::fmt::Formatter::write_str(f, "AstTree"),
            PpMode::AstTreeExpanded =>
                ::core::fmt::Formatter::write_str(f, "AstTreeExpanded"),
            PpMode::Hir(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Hir",
                    &__self_0),
            PpMode::HirTree =>
                ::core::fmt::Formatter::write_str(f, "HirTree"),
            PpMode::ThirTree =>
                ::core::fmt::Formatter::write_str(f, "ThirTree"),
            PpMode::ThirFlat =>
                ::core::fmt::Formatter::write_str(f, "ThirFlat"),
            PpMode::Mir => ::core::fmt::Formatter::write_str(f, "Mir"),
            PpMode::MirCFG => ::core::fmt::Formatter::write_str(f, "MirCFG"),
            PpMode::StableMir =>
                ::core::fmt::Formatter::write_str(f, "StableMir"),
        }
    }
}Debug)]
2979/// Pretty print mode
2980pub enum PpMode {
2981    /// Options that print the source code, i.e.
2982    /// `-Zunpretty=normal` and `-Zunpretty=expanded`
2983    Source(PpSourceMode),
2984    /// `-Zunpretty=ast-tree`
2985    AstTree,
2986    /// `-Zunpretty=ast-tree,expanded`
2987    AstTreeExpanded,
2988    /// Options that print the HIR, i.e. `-Zunpretty=hir`
2989    Hir(PpHirMode),
2990    /// `-Zunpretty=hir-tree`
2991    HirTree,
2992    /// `-Zunpretty=thir-tree`
2993    ThirTree,
2994    /// `-Zunpretty=thir-flat`
2995    ThirFlat,
2996    /// `-Zunpretty=mir`
2997    Mir,
2998    /// `-Zunpretty=mir-cfg`
2999    MirCFG,
3000    /// `-Zunpretty=stable-mir`
3001    StableMir,
3002}
3003
3004impl PpMode {
3005    pub fn needs_ast_map(&self) -> bool {
3006        use PpMode::*;
3007        use PpSourceMode::*;
3008        match *self {
3009            Source(Normal | Identified) | AstTree => false,
3010
3011            Source(Expanded | ExpandedIdentified | ExpandedHygiene)
3012            | AstTreeExpanded
3013            | Hir(_)
3014            | HirTree
3015            | ThirTree
3016            | ThirFlat
3017            | Mir
3018            | MirCFG
3019            | StableMir => true,
3020        }
3021    }
3022
3023    pub fn needs_analysis(&self) -> bool {
3024        use PpMode::*;
3025        #[allow(non_exhaustive_omitted_patterns)] match *self {
    Hir(PpHirMode::Typed) | Mir | StableMir | MirCFG | ThirTree | ThirFlat =>
        true,
    _ => false,
}matches!(*self, Hir(PpHirMode::Typed) | Mir | StableMir | MirCFG | ThirTree | ThirFlat)
3026    }
3027}
3028
3029#[derive(#[automatically_derived]
impl ::core::clone::Clone for WasiExecModel {
    #[inline]
    fn clone(&self) -> WasiExecModel {
        match self {
            WasiExecModel::Command => WasiExecModel::Command,
            WasiExecModel::Reactor => WasiExecModel::Reactor,
        }
    }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for WasiExecModel {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::cmp::PartialEq for WasiExecModel {
    #[inline]
    fn eq(&self, other: &WasiExecModel) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for WasiExecModel {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for WasiExecModel {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                WasiExecModel::Command => "Command",
                WasiExecModel::Reactor => "Reactor",
            })
    }
}Debug)]
3030pub enum WasiExecModel {
3031    Command,
3032    Reactor,
3033}
3034
3035/// Command-line arguments passed to the compiler have to be incorporated with
3036/// the dependency tracking system for incremental compilation. This module
3037/// provides some utilities to make this more convenient.
3038///
3039/// The values of all command-line arguments that are relevant for dependency
3040/// tracking are hashed into a single value that determines whether the
3041/// incremental compilation cache can be re-used or not. This hashing is done
3042/// via the `DepTrackingHash` trait defined below, since the standard `Hash`
3043/// implementation might not be suitable (e.g., arguments are stored in a `Vec`,
3044/// the hash of which is order dependent, but we might not want the order of
3045/// arguments to make a difference for the hash).
3046///
3047/// However, since the value provided by `Hash::hash` often *is* suitable,
3048/// especially for primitive types, there is the
3049/// `impl_dep_tracking_hash_via_hash!()` macro that allows to simply reuse the
3050/// `Hash` implementation for `DepTrackingHash`. It's important though that
3051/// we have an opt-in scheme here, so one is hopefully forced to think about
3052/// how the hash should be calculated when adding a new command-line argument.
3053pub(crate) mod dep_tracking {
3054    use std::collections::BTreeMap;
3055    use std::hash::Hash;
3056    use std::num::NonZero;
3057    use std::path::PathBuf;
3058
3059    use rustc_abi::Align;
3060    use rustc_data_structures::fx::FxIndexMap;
3061    use rustc_data_structures::stable_hasher::StableHasher;
3062    use rustc_errors::LanguageIdentifier;
3063    use rustc_feature::UnstableFeatures;
3064    use rustc_hashes::Hash64;
3065    use rustc_hir::attrs::CollapseMacroDebuginfo;
3066    use rustc_span::edition::Edition;
3067    use rustc_span::{RealFileName, RemapPathScopeComponents};
3068    use rustc_target::spec::{
3069        CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel,
3070        RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility, TargetTuple,
3071        TlsModel,
3072    };
3073
3074    use super::{
3075        AnnotateMoves, AutoDiff, BranchProtection, CFGuard, CFProtection, CoverageOptions,
3076        CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn,
3077        InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
3078        LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OptLevel, OutFileName, OutputType,
3079        OutputTypes, PatchableFunctionEntry, Polonius, ResolveDocLinks, SourceFileHashAlgorithm,
3080        SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
3081    };
3082    use crate::lint;
3083    use crate::utils::NativeLib;
3084
3085    pub(crate) trait DepTrackingHash {
3086        fn hash(
3087            &self,
3088            hasher: &mut StableHasher,
3089            error_format: ErrorOutputType,
3090            for_crate_hash: bool,
3091        );
3092    }
3093
3094    macro_rules! impl_dep_tracking_hash_via_hash {
3095        ($($t:ty),+ $(,)?) => {$(
3096            impl DepTrackingHash for $t {
3097                fn hash(&self, hasher: &mut StableHasher, _: ErrorOutputType, _for_crate_hash: bool) {
3098                    Hash::hash(self, hasher);
3099                }
3100            }
3101        )+};
3102    }
3103
3104    impl<T: DepTrackingHash> DepTrackingHash for Option<T> {
3105        fn hash(
3106            &self,
3107            hasher: &mut StableHasher,
3108            error_format: ErrorOutputType,
3109            for_crate_hash: bool,
3110        ) {
3111            match self {
3112                Some(x) => {
3113                    Hash::hash(&1, hasher);
3114                    DepTrackingHash::hash(x, hasher, error_format, for_crate_hash);
3115                }
3116                None => Hash::hash(&0, hasher),
3117            }
3118        }
3119    }
3120
3121    impl DepTrackingHash for Align {
    fn hash(&self, hasher: &mut StableHasher, _: ErrorOutputType,
        _for_crate_hash: bool) {
        Hash::hash(self, hasher);
    }
}impl_dep_tracking_hash_via_hash!(
3122        (),
3123        AnnotateMoves,
3124        AutoDiff,
3125        Offload,
3126        bool,
3127        usize,
3128        NonZero<usize>,
3129        u64,
3130        Hash64,
3131        String,
3132        PathBuf,
3133        lint::Level,
3134        WasiExecModel,
3135        u32,
3136        FramePointer,
3137        RelocModel,
3138        CodeModel,
3139        TlsModel,
3140        InstrumentCoverage,
3141        CoverageOptions,
3142        InstrumentXRay,
3143        CrateType,
3144        MergeFunctions,
3145        OnBrokenPipe,
3146        PanicStrategy,
3147        RelroLevel,
3148        OptLevel,
3149        LtoCli,
3150        DebugInfo,
3151        DebugInfoCompression,
3152        MirStripDebugInfo,
3153        CollapseMacroDebuginfo,
3154        UnstableFeatures,
3155        NativeLib,
3156        SanitizerSet,
3157        CFGuard,
3158        CFProtection,
3159        TargetTuple,
3160        Edition,
3161        LinkerPluginLto,
3162        ResolveDocLinks,
3163        SplitDebuginfo,
3164        SplitDwarfKind,
3165        StackProtector,
3166        SwitchWithOptPath,
3167        SymbolManglingVersion,
3168        SymbolVisibility,
3169        RemapPathScopeComponents,
3170        SourceFileHashAlgorithm,
3171        OutFileName,
3172        OutputType,
3173        RealFileName,
3174        LocationDetail,
3175        FmtDebug,
3176        BranchProtection,
3177        LanguageIdentifier,
3178        NextSolverConfig,
3179        PatchableFunctionEntry,
3180        Polonius,
3181        InliningThreshold,
3182        FunctionReturn,
3183        Align,
3184    );
3185
3186    impl<T1, T2> DepTrackingHash for (T1, T2)
3187    where
3188        T1: DepTrackingHash,
3189        T2: DepTrackingHash,
3190    {
3191        fn hash(
3192            &self,
3193            hasher: &mut StableHasher,
3194            error_format: ErrorOutputType,
3195            for_crate_hash: bool,
3196        ) {
3197            Hash::hash(&0, hasher);
3198            DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash);
3199            Hash::hash(&1, hasher);
3200            DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash);
3201        }
3202    }
3203
3204    impl<T1, T2, T3> DepTrackingHash for (T1, T2, T3)
3205    where
3206        T1: DepTrackingHash,
3207        T2: DepTrackingHash,
3208        T3: DepTrackingHash,
3209    {
3210        fn hash(
3211            &self,
3212            hasher: &mut StableHasher,
3213            error_format: ErrorOutputType,
3214            for_crate_hash: bool,
3215        ) {
3216            Hash::hash(&0, hasher);
3217            DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash);
3218            Hash::hash(&1, hasher);
3219            DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash);
3220            Hash::hash(&2, hasher);
3221            DepTrackingHash::hash(&self.2, hasher, error_format, for_crate_hash);
3222        }
3223    }
3224
3225    impl<T: DepTrackingHash> DepTrackingHash for Vec<T> {
3226        fn hash(
3227            &self,
3228            hasher: &mut StableHasher,
3229            error_format: ErrorOutputType,
3230            for_crate_hash: bool,
3231        ) {
3232            Hash::hash(&self.len(), hasher);
3233            for (index, elem) in self.iter().enumerate() {
3234                Hash::hash(&index, hasher);
3235                DepTrackingHash::hash(elem, hasher, error_format, for_crate_hash);
3236            }
3237        }
3238    }
3239
3240    impl<T: DepTrackingHash, V: DepTrackingHash> DepTrackingHash for FxIndexMap<T, V> {
3241        fn hash(
3242            &self,
3243            hasher: &mut StableHasher,
3244            error_format: ErrorOutputType,
3245            for_crate_hash: bool,
3246        ) {
3247            Hash::hash(&self.len(), hasher);
3248            for (key, value) in self.iter() {
3249                DepTrackingHash::hash(key, hasher, error_format, for_crate_hash);
3250                DepTrackingHash::hash(value, hasher, error_format, for_crate_hash);
3251            }
3252        }
3253    }
3254
3255    impl DepTrackingHash for OutputTypes {
3256        fn hash(
3257            &self,
3258            hasher: &mut StableHasher,
3259            error_format: ErrorOutputType,
3260            for_crate_hash: bool,
3261        ) {
3262            Hash::hash(&self.0.len(), hasher);
3263            for (key, val) in &self.0 {
3264                DepTrackingHash::hash(key, hasher, error_format, for_crate_hash);
3265                if !for_crate_hash {
3266                    DepTrackingHash::hash(val, hasher, error_format, for_crate_hash);
3267                }
3268            }
3269        }
3270    }
3271
3272    // This is a stable hash because BTreeMap is a sorted container
3273    pub(crate) fn stable_hash(
3274        sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>,
3275        hasher: &mut StableHasher,
3276        error_format: ErrorOutputType,
3277        for_crate_hash: bool,
3278    ) {
3279        for (key, sub_hash) in sub_hashes {
3280            // Using Hash::hash() instead of DepTrackingHash::hash() is fine for
3281            // the keys, as they are just plain strings
3282            Hash::hash(&key.len(), hasher);
3283            Hash::hash(key, hasher);
3284            sub_hash.hash(hasher, error_format, for_crate_hash);
3285        }
3286    }
3287}
3288
3289/// How to run proc-macro code when building this crate
3290#[derive(#[automatically_derived]
impl ::core::clone::Clone for ProcMacroExecutionStrategy {
    #[inline]
    fn clone(&self) -> ProcMacroExecutionStrategy { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for ProcMacroExecutionStrategy { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for ProcMacroExecutionStrategy {
    #[inline]
    fn eq(&self, other: &ProcMacroExecutionStrategy) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for ProcMacroExecutionStrategy {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for ProcMacroExecutionStrategy {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                ProcMacroExecutionStrategy::SameThread => "SameThread",
                ProcMacroExecutionStrategy::CrossThread => "CrossThread",
            })
    }
}Debug)]
3291pub enum ProcMacroExecutionStrategy {
3292    /// Run the proc-macro code on the same thread as the server.
3293    SameThread,
3294
3295    /// Run the proc-macro code on a different thread.
3296    CrossThread,
3297}
3298
3299/// Which format to use for `-Z dump-mono-stats`
3300#[derive(#[automatically_derived]
impl ::core::clone::Clone for DumpMonoStatsFormat {
    #[inline]
    fn clone(&self) -> DumpMonoStatsFormat { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for DumpMonoStatsFormat { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for DumpMonoStatsFormat {
    #[inline]
    fn eq(&self, other: &DumpMonoStatsFormat) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for DumpMonoStatsFormat {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for DumpMonoStatsFormat {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                DumpMonoStatsFormat::Markdown => "Markdown",
                DumpMonoStatsFormat::Json => "Json",
            })
    }
}Debug)]
3301pub enum DumpMonoStatsFormat {
3302    /// Pretty-print a markdown table
3303    Markdown,
3304    /// Emit structured JSON
3305    Json,
3306}
3307
3308impl DumpMonoStatsFormat {
3309    pub fn extension(self) -> &'static str {
3310        match self {
3311            Self::Markdown => "md",
3312            Self::Json => "json",
3313        }
3314    }
3315}
3316
3317/// `-Z patchable-function-entry` representation - how many nops to put before and after function
3318/// entry.
3319#[derive(#[automatically_derived]
impl ::core::clone::Clone for PatchableFunctionEntry {
    #[inline]
    fn clone(&self) -> PatchableFunctionEntry {
        let _: ::core::clone::AssertParamIsClone<u8>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for PatchableFunctionEntry { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for PatchableFunctionEntry {
    #[inline]
    fn eq(&self, other: &PatchableFunctionEntry) -> bool {
        self.prefix == other.prefix && self.entry == other.entry
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for PatchableFunctionEntry {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.prefix, state);
        ::core::hash::Hash::hash(&self.entry, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for PatchableFunctionEntry {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "PatchableFunctionEntry", "prefix", &self.prefix, "entry",
            &&self.entry)
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for PatchableFunctionEntry {
    #[inline]
    fn default() -> PatchableFunctionEntry {
        PatchableFunctionEntry {
            prefix: ::core::default::Default::default(),
            entry: ::core::default::Default::default(),
        }
    }
}Default)]
3320pub struct PatchableFunctionEntry {
3321    /// Nops before the entry
3322    prefix: u8,
3323    /// Nops after the entry
3324    entry: u8,
3325}
3326
3327impl PatchableFunctionEntry {
3328    pub fn from_total_and_prefix_nops(
3329        total_nops: u8,
3330        prefix_nops: u8,
3331    ) -> Option<PatchableFunctionEntry> {
3332        if total_nops < prefix_nops {
3333            None
3334        } else {
3335            Some(Self { prefix: prefix_nops, entry: total_nops - prefix_nops })
3336        }
3337    }
3338    pub fn prefix(&self) -> u8 {
3339        self.prefix
3340    }
3341    pub fn entry(&self) -> u8 {
3342        self.entry
3343    }
3344}
3345
3346/// `-Zpolonius` values, enabling the borrow checker polonius analysis, and which version: legacy,
3347/// or future prototype.
3348#[derive(#[automatically_derived]
impl ::core::clone::Clone for Polonius {
    #[inline]
    fn clone(&self) -> Polonius { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for Polonius { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for Polonius {
    #[inline]
    fn eq(&self, other: &Polonius) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for Polonius {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Polonius {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                Polonius::Off => "Off",
                Polonius::Legacy => "Legacy",
                Polonius::Next => "Next",
            })
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for Polonius {
    #[inline]
    fn default() -> Polonius { Self::Off }
}Default)]
3349pub enum Polonius {
3350    /// The default value: disabled.
3351    #[default]
3352    Off,
3353
3354    /// Legacy version, using datalog and the `polonius-engine` crate. Historical value for `-Zpolonius`.
3355    Legacy,
3356
3357    /// In-tree prototype, extending the NLL infrastructure.
3358    Next,
3359}
3360
3361impl Polonius {
3362    /// Returns whether the legacy version of polonius is enabled
3363    pub fn is_legacy_enabled(&self) -> bool {
3364        #[allow(non_exhaustive_omitted_patterns)] match self {
    Polonius::Legacy => true,
    _ => false,
}matches!(self, Polonius::Legacy)
3365    }
3366
3367    /// Returns whether the "next" version of polonius is enabled
3368    pub fn is_next_enabled(&self) -> bool {
3369        #[allow(non_exhaustive_omitted_patterns)] match self {
    Polonius::Next => true,
    _ => false,
}matches!(self, Polonius::Next)
3370    }
3371}
3372
3373#[derive(#[automatically_derived]
impl ::core::clone::Clone for InliningThreshold {
    #[inline]
    fn clone(&self) -> InliningThreshold {
        let _: ::core::clone::AssertParamIsClone<usize>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for InliningThreshold { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for InliningThreshold {
    #[inline]
    fn eq(&self, other: &InliningThreshold) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (InliningThreshold::Sometimes(__self_0),
                    InliningThreshold::Sometimes(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for InliningThreshold {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            InliningThreshold::Sometimes(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for InliningThreshold {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            InliningThreshold::Always =>
                ::core::fmt::Formatter::write_str(f, "Always"),
            InliningThreshold::Sometimes(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Sometimes", &__self_0),
            InliningThreshold::Never =>
                ::core::fmt::Formatter::write_str(f, "Never"),
        }
    }
}Debug)]
3374pub enum InliningThreshold {
3375    Always,
3376    Sometimes(usize),
3377    Never,
3378}
3379
3380impl Default for InliningThreshold {
3381    fn default() -> Self {
3382        Self::Sometimes(100)
3383    }
3384}
3385
3386/// The different settings that the `-Zfunction-return` flag can have.
3387#[derive(#[automatically_derived]
impl ::core::clone::Clone for FunctionReturn {
    #[inline]
    fn clone(&self) -> FunctionReturn { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for FunctionReturn { }Copy, #[automatically_derived]
impl ::core::cmp::PartialEq for FunctionReturn {
    #[inline]
    fn eq(&self, other: &FunctionReturn) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::hash::Hash for FunctionReturn {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for FunctionReturn {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                FunctionReturn::Keep => "Keep",
                FunctionReturn::ThunkExtern => "ThunkExtern",
            })
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for FunctionReturn {
    #[inline]
    fn default() -> FunctionReturn { Self::Keep }
}Default)]
3388pub enum FunctionReturn {
3389    /// Keep the function return unmodified.
3390    #[default]
3391    Keep,
3392
3393    /// Replace returns with jumps to thunk, without emitting the thunk.
3394    ThunkExtern,
3395}
3396
3397/// Whether extra span comments are included when dumping MIR, via the `-Z mir-include-spans` flag.
3398/// By default, only enabled in the NLL MIR dumps, and disabled in all other passes.
3399#[derive(#[automatically_derived]
impl ::core::clone::Clone for MirIncludeSpans {
    #[inline]
    fn clone(&self) -> MirIncludeSpans { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for MirIncludeSpans { }Copy, #[automatically_derived]
impl ::core::default::Default for MirIncludeSpans {
    #[inline]
    fn default() -> MirIncludeSpans { Self::Nll }
}Default, #[automatically_derived]
impl ::core::cmp::PartialEq for MirIncludeSpans {
    #[inline]
    fn eq(&self, other: &MirIncludeSpans) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for MirIncludeSpans {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                MirIncludeSpans::Off => "Off",
                MirIncludeSpans::On => "On",
                MirIncludeSpans::Nll => "Nll",
            })
    }
}Debug)]
3400pub enum MirIncludeSpans {
3401    Off,
3402    On,
3403    /// Default: include extra comments in NLL MIR dumps only. Can be ignored and considered as
3404    /// `Off` in all other cases.
3405    #[default]
3406    Nll,
3407}
3408
3409impl MirIncludeSpans {
3410    /// Unless opting into extra comments for all passes, they can be considered disabled.
3411    /// The cases where a distinction between on/off and a per-pass value can exist will be handled
3412    /// in the passes themselves: i.e. the `Nll` value is considered off for all intents and
3413    /// purposes, except for the NLL MIR dump pass.
3414    pub fn is_enabled(self) -> bool {
3415        self == MirIncludeSpans::On
3416    }
3417}