rustc_session/
config.rs

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