Skip to main content

rustc_session/
config.rs

1//! Contains infrastructure for configuring the compiler, including parsing
2//! command-line options.
3
4use std::collections::btree_map::{
5    Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
6};
7use std::collections::{BTreeMap, BTreeSet};
8use std::ffi::OsStr;
9use std::hash::Hash;
10use std::path::{Path, PathBuf};
11use std::str::{self, FromStr};
12use std::sync::LazyLock;
13use std::{cmp, fs, iter};
14
15use externs::{ExternOpt, split_extern_opt};
16use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
17use rustc_data_structures::stable_hasher::{StableHasher, StableOrd, ToStableHashKey};
18use rustc_errors::emitter::HumanReadableErrorType;
19use rustc_errors::{ColorConfig, DiagCtxtFlags};
20use rustc_feature::UnstableFeatures;
21use rustc_hashes::Hash64;
22use rustc_macros::{BlobDecodable, Decodable, Encodable, StableHash};
23use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION};
24use rustc_span::source_map::FilePathMapping;
25use rustc_span::{
26    FileName, RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm, Symbol, sym,
27};
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, 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 ::rustc_data_structures::stable_hasher::StableHash for OptLevel {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hasher::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    OptLevel::No => {}
                    OptLevel::Less => {}
                    OptLevel::More => {}
                    OptLevel::Aggressive => {}
                    OptLevel::Size => {}
                    OptLevel::SizeMin => {}
                }
            }
        }
    };StableHash, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for OptLevel {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        OptLevel::No => { 0usize }
                        OptLevel::Less => { 1usize }
                        OptLevel::More => { 2usize }
                        OptLevel::Aggressive => { 3usize }
                        OptLevel::Size => { 4usize }
                        OptLevel::SizeMin => { 5usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    OptLevel::No => {}
                    OptLevel::Less => {}
                    OptLevel::More => {}
                    OptLevel::Aggressive => {}
                    OptLevel::Size => {}
                    OptLevel::SizeMin => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for OptLevel {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { OptLevel::No }
                    1usize => { OptLevel::Less }
                    2usize => { OptLevel::More }
                    3usize => { OptLevel::Aggressive }
                    4usize => { OptLevel::Size }
                    5usize => { OptLevel::SizeMin }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `OptLevel`, expected 0..6, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
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, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for Lto {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        Lto::No => { 0usize }
                        Lto::Thin => { 1usize }
                        Lto::ThinLocal => { 2usize }
                        Lto::Fat => { 3usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    Lto::No => {}
                    Lto::Thin => {}
                    Lto::ThinLocal => {}
                    Lto::Fat => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for Lto {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { Lto::No }
                    1usize => { Lto::Thin }
                    2usize => { Lto::ThinLocal }
                    3usize => { Lto::Fat }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Lto`, expected 0..4, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
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_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<CoverageLevel>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for CoverageOptions {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.level, state);
        ::core::hash::Hash::hash(&self.discard_all_spans_in_codegen, state)
    }
}Hash, #[automatically_derived]
impl ::core::default::Default for CoverageOptions {
    #[inline]
    fn default() -> CoverageOptions {
        CoverageOptions {
            level: ::core::default::Default::default(),
            discard_all_spans_in_codegen: ::core::default::Default::default(),
        }
    }
}Default)]
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_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for CoverageLevel {
    #[inline]
    fn partial_cmp(&self, other: &CoverageLevel)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for CoverageLevel {
    #[inline]
    fn cmp(&self, other: &CoverageLevel) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for CoverageLevel {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for CoverageLevel {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                CoverageLevel::Block => "Block",
                CoverageLevel::Branch => "Branch",
                CoverageLevel::Condition => "Condition",
            })
    }
}Debug, #[automatically_derived]
impl ::core::default::Default for CoverageLevel {
    #[inline]
    fn default() -> CoverageLevel { Self::Block }
}Default)]
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, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for Offload {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        Offload::Device => { 0usize }
                        Offload::Host(ref __binding_0) => { 1usize }
                        Offload::Test => { 2usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    Offload::Device => {}
                    Offload::Host(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    Offload::Test => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for Offload {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { Offload::Device }
                    1usize => {
                        Offload::Host(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    2usize => { Offload::Test }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Offload`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
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, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for AutoDiff {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        AutoDiff::Enable => { 0usize }
                        AutoDiff::PrintTA => { 1usize }
                        AutoDiff::PrintTAFn(ref __binding_0) => { 2usize }
                        AutoDiff::PrintAA => { 3usize }
                        AutoDiff::PrintPerf => { 4usize }
                        AutoDiff::PrintSteps => { 5usize }
                        AutoDiff::PrintModBefore => { 6usize }
                        AutoDiff::PrintModAfter => { 7usize }
                        AutoDiff::PrintModFinal => { 8usize }
                        AutoDiff::PrintPasses => { 9usize }
                        AutoDiff::NoPostopt => { 10usize }
                        AutoDiff::LooseTypes => { 11usize }
                        AutoDiff::Inline => { 12usize }
                        AutoDiff::NoTT => { 13usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    AutoDiff::Enable => {}
                    AutoDiff::PrintTA => {}
                    AutoDiff::PrintTAFn(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    AutoDiff::PrintAA => {}
                    AutoDiff::PrintPerf => {}
                    AutoDiff::PrintSteps => {}
                    AutoDiff::PrintModBefore => {}
                    AutoDiff::PrintModAfter => {}
                    AutoDiff::PrintModFinal => {}
                    AutoDiff::PrintPasses => {}
                    AutoDiff::NoPostopt => {}
                    AutoDiff::LooseTypes => {}
                    AutoDiff::Inline => {}
                    AutoDiff::NoTT => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for AutoDiff {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { AutoDiff::Enable }
                    1usize => { AutoDiff::PrintTA }
                    2usize => {
                        AutoDiff::PrintTAFn(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    3usize => { AutoDiff::PrintAA }
                    4usize => { AutoDiff::PrintPerf }
                    5usize => { AutoDiff::PrintSteps }
                    6usize => { AutoDiff::PrintModBefore }
                    7usize => { AutoDiff::PrintModAfter }
                    8usize => { AutoDiff::PrintModFinal }
                    9usize => { AutoDiff::PrintPasses }
                    10usize => { AutoDiff::NoPostopt }
                    11usize => { AutoDiff::LooseTypes }
                    12usize => { AutoDiff::Inline }
                    13usize => { AutoDiff::NoTT }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `AutoDiff`, expected 0..14, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
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_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<bool>;
        let _: ::core::cmp::AssertParamIsEq<Option<usize>>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for InstrumentXRay {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.always, state);
        ::core::hash::Hash::hash(&self.never, state);
        ::core::hash::Hash::hash(&self.ignore_loops, state);
        ::core::hash::Hash::hash(&self.instruction_threshold, state);
        ::core::hash::Hash::hash(&self.skip_entry, state);
        ::core::hash::Hash::hash(&self.skip_exit, state)
    }
}Hash)]
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, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for SwitchWithOptPath {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        SwitchWithOptPath::Enabled(ref __binding_0) => { 0usize }
                        SwitchWithOptPath::Disabled => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    SwitchWithOptPath::Enabled(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    SwitchWithOptPath::Disabled => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for SwitchWithOptPath {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        SwitchWithOptPath::Enabled(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => { SwitchWithOptPath::Disabled }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `SwitchWithOptPath`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
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_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for SymbolManglingVersion {
    #[inline]
    fn partial_cmp(&self, other: &SymbolManglingVersion)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for SymbolManglingVersion {
    #[inline]
    fn cmp(&self, other: &SymbolManglingVersion) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for SymbolManglingVersion {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, const _: () =
    {
        impl ::rustc_data_structures::stable_hasher::StableHash for
            SymbolManglingVersion {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hasher::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    SymbolManglingVersion::Legacy => {}
                    SymbolManglingVersion::V0 => {}
                    SymbolManglingVersion::Hashed => {}
                }
            }
        }
    };StableHash)]
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, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for SplitDwarfKind {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        SplitDwarfKind::Single => { 0usize }
                        SplitDwarfKind::Split => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    SplitDwarfKind::Single => {}
                    SplitDwarfKind::Split => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for SplitDwarfKind {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { SplitDwarfKind::Single }
                    1usize => { SplitDwarfKind::Split }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `SplitDwarfKind`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
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, StableHash)]
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 ToStableHashKey for OutputType {
640            type KeyType = Self;
641
642            fn to_stable_hash_key<Hcx>(&self, _: &mut 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_fields_are_eq(&self) {}
}
#[automatically_derived]
impl ::core::hash::Hash for OutputType {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}
#[automatically_derived]
impl ::core::fmt::Debug for OutputType {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                OutputType::Assembly => "Assembly",
                OutputType::Bitcode => "Bitcode",
                OutputType::DepInfo => "DepInfo",
                OutputType::Exe => "Exe",
                OutputType::LlvmAssembly => "LlvmAssembly",
                OutputType::Metadata => "Metadata",
                OutputType::Mir => "Mir",
                OutputType::Object => "Object",
                OutputType::ThinLinkBitcode => "ThinLinkBitcode",
            })
    }
}
#[automatically_derived]
impl ::core::cmp::PartialOrd for OutputType {
    #[inline]
    fn partial_cmp(&self, other: &OutputType)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}
#[automatically_derived]
impl ::core::cmp::Ord for OutputType {
    #[inline]
    fn cmp(&self, other: &OutputType) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}
const _: () =
    {
        impl ::rustc_data_structures::stable_hasher::StableHash for OutputType
            {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hasher::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__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 ToStableHashKey for OutputType {
    type KeyType = Self;
    fn to_stable_hash_key<Hcx>(&self, _: &mut Hcx) -> Self::KeyType { *self }
}
impl OutputType {
    pub fn iter_all() -> impl Iterator<Item = OutputType> {
        static ALL_VARIANTS: &[OutputType] =
            &[OutputType::Assembly, OutputType::Bitcode, OutputType::DepInfo,
                        OutputType::Exe, OutputType::LlvmAssembly,
                        OutputType::Metadata, OutputType::Mir, OutputType::Object,
                        OutputType::ThinLinkBitcode];
        ALL_VARIANTS.iter().copied()
    }
    fn is_compatible_with_codegen_units_and_single_output_file(&self)
        -> bool {
        match *self {
            OutputType::Assembly => false,
            OutputType::Bitcode => false,
            OutputType::DepInfo => true,
            OutputType::Exe => true,
            OutputType::LlvmAssembly => false,
            OutputType::Metadata => true,
            OutputType::Mir => false,
            OutputType::Object => false,
            OutputType::ThinLinkBitcode => false,
        }
    }
    pub fn shorthand(&self) -> &'static str {
        match *self {
            OutputType::Assembly => "asm",
            OutputType::Bitcode => "llvm-bc",
            OutputType::DepInfo => "dep-info",
            OutputType::Exe => "link",
            OutputType::LlvmAssembly => "llvm-ir",
            OutputType::Metadata => "metadata",
            OutputType::Mir => "mir",
            OutputType::Object => "obj",
            OutputType::ThinLinkBitcode => "thin-link-bitcode",
        }
    }
    fn from_shorthand(shorthand: &str) -> Option<Self> {
        match shorthand {
            s if s == "asm" => Some(OutputType::Assembly),
            s if s == "llvm-bc" => Some(OutputType::Bitcode),
            s if s == "dep-info" => Some(OutputType::DepInfo),
            s if s == "link" => Some(OutputType::Exe),
            s if s == "llvm-ir" => Some(OutputType::LlvmAssembly),
            s if s == "metadata" => Some(OutputType::Metadata),
            s if s == "mir" => Some(OutputType::Mir),
            s if s == "obj" => Some(OutputType::Object),
            s if s == "thin-link-bitcode" =>
                Some(OutputType::ThinLinkBitcode),
            _ => None,
        }
    }
    fn shorthands_display() -> String {
        let shorthands =
            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                    [::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "asm"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "llvm-bc"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "dep-info"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "link"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "llvm-ir"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "metadata"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "mir"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`", "obj"))
                                }),
                            ::alloc::__export::must_use({
                                    ::alloc::fmt::format(format_args!("`{0}`",
                                            "thin-link-bitcode"))
                                })]));
        shorthands.join(", ")
    }
    pub fn extension(&self) -> &'static str {
        match *self {
            OutputType::Assembly => "s",
            OutputType::Bitcode => "bc",
            OutputType::DepInfo => "d",
            OutputType::Exe => "",
            OutputType::LlvmAssembly => "ll",
            OutputType::Metadata => "rmeta",
            OutputType::Mir => "mir",
            OutputType::Object => "o",
            OutputType::ThinLinkBitcode => "indexing.o",
        }
    }
    pub fn is_text_output(&self) -> bool {
        match *self {
            OutputType::Assembly => true,
            OutputType::Bitcode => false,
            OutputType::DepInfo => true,
            OutputType::Exe => false,
            OutputType::LlvmAssembly => true,
            OutputType::Metadata => false,
            OutputType::Mir => true,
            OutputType::Object => false,
            OutputType::ThinLinkBitcode => false,
        }
    }
    pub fn description(&self) -> &'static str {
        match *self {
            OutputType::Assembly =>
                "Generates a file with the crate's assembly code",
            OutputType::Bitcode =>
                "Generates a binary file containing the LLVM bitcode",
            OutputType::DepInfo =>
                "Generates a file with Makefile syntax that indicates all the source files that were loaded to generate the crate",
            OutputType::Exe =>
                "Generates the crates specified by --crate-type. This is the default if --emit is not specified",
            OutputType::LlvmAssembly => "Generates a file containing LLVM IR",
            OutputType::Metadata =>
                "Generates a file containing metadata about the crate",
            OutputType::Mir =>
                "Generates a file containing rustc's mid-level intermediate representation",
            OutputType::Object => "Generates a native object file",
            OutputType::ThinLinkBitcode =>
                "Generates the ThinLTO summary as bitcode",
        }
    }
    pub fn default_filename(&self) -> &'static str {
        match *self {
            OutputType::Assembly => "CRATE_NAME.s",
            OutputType::Bitcode => "CRATE_NAME.bc",
            OutputType::DepInfo => "CRATE_NAME.d",
            OutputType::Exe => "(platform and crate-type dependent)",
            OutputType::LlvmAssembly => "CRATE_NAME.ll",
            OutputType::Metadata => "libCRATE_NAME.rmeta",
            OutputType::Mir => "CRATE_NAME.mir",
            OutputType::Object => "CRATE_NAME.o",
            OutputType::ThinLinkBitcode => "CRATE_NAME.indexing.o",
        }
    }
}define_output_types! {
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_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<HumanReadableErrorType>;
        let _: ::core::cmp::AssertParamIsEq<ColorConfig>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::default::Default for ErrorOutputType {
    #[inline]
    fn default() -> ErrorOutputType {
        Self::HumanReadable {
            kind: const HumanReadableErrorType {
                        short: false,
                        unicode: false,
                    },
            color_config: const ColorConfig::Auto,
        }
    }
}Default)]
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 ::rustc_data_structures::stable_hasher::StableHash for
            OutputTypes {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hasher::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                match *self {
                    OutputTypes(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, 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_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl ::core::default::Default for NextSolverConfig {
    #[inline]
    fn default() -> NextSolverConfig {
        NextSolverConfig { coherence: const true, globally: const false }
    }
}Default)]
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 ::rustc_data_structures::stable_hasher::StableHash for
            OutFileName {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hasher::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    OutFileName::Real(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    OutFileName::Stdout => {}
                }
            }
        }
    };StableHash, #[automatically_derived]
impl ::core::cmp::PartialEq for OutFileName {
    #[inline]
    fn eq(&self, other: &OutFileName) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (OutFileName::Real(__self_0), OutFileName::Real(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for OutFileName {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<PathBuf>;
    }
}Eq, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for OutFileName {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        OutFileName::Real(ref __binding_0) => { 0usize }
                        OutFileName::Stdout => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    OutFileName::Real(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    OutFileName::Stdout => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for OutFileName {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        OutFileName::Real(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => { OutFileName::Stdout }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `OutFileName`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
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 ::rustc_data_structures::stable_hasher::StableHash for
            OutputFilenames {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hasher::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __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.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                        { __binding_3.stable_hash(__hcx, __hasher); }
                        { __binding_4.stable_hash(__hcx, __hasher); }
                        { __binding_5.stable_hash(__hcx, __hasher); }
                        { __binding_6.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, 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        {
    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:1207",
                        "rustc_session::config", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_session/src/config.rs"),
                        ::tracing_core::__macro_support::Option::Some(1207u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_session::config"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("using crate_name={0} for interface_path",
                                                    self.crate_stem) as &dyn Value))])
            });
    } else { ; }
};debug!("using crate_name={} for interface_path", self.crate_stem);
1208        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))
1209    }
1210
1211    /// Gets the output path where a compilation artifact of the given type
1212    /// should be placed on disk.
1213    fn output_path(&self, flavor: OutputType) -> PathBuf {
1214        let extension = flavor.extension();
1215        match flavor {
1216            OutputType::Metadata => {
1217                {
    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:1217",
                        "rustc_session::config", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_session/src/config.rs"),
                        ::tracing_core::__macro_support::Option::Some(1217u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_session::config"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("using crate_name={0} for {1}",
                                                    self.crate_stem, extension) as &dyn Value))])
            });
    } else { ; }
};debug!("using crate_name={} for {extension}", self.crate_stem);
1218                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))
1219            }
1220            _ => self.with_directory_and_extension(&self.out_directory, extension),
1221        }
1222    }
1223
1224    /// Gets the path where a compilation artifact of the given type for the
1225    /// given codegen unit should be placed on disk. If codegen_unit_name is
1226    /// None, a path distinct from those of any codegen unit will be generated.
1227    pub fn temp_path_for_cgu(
1228        &self,
1229        flavor: OutputType,
1230        codegen_unit_name: &str,
1231        invocation_temp: Option<&str>,
1232    ) -> PathBuf {
1233        let extension = flavor.extension();
1234        self.temp_path_ext_for_cgu(extension, codegen_unit_name, invocation_temp)
1235    }
1236
1237    /// Like `temp_path`, but specifically for dwarf objects.
1238    pub fn temp_path_dwo_for_cgu(
1239        &self,
1240        codegen_unit_name: &str,
1241        invocation_temp: Option<&str>,
1242    ) -> PathBuf {
1243        let p = self.temp_path_ext_for_cgu(DWARF_OBJECT_EXT, codegen_unit_name, invocation_temp);
1244        if let Some(dwo_out) = &self.explicit_dwo_out_directory {
1245            let mut o = dwo_out.clone();
1246            o.push(p.file_name().unwrap());
1247            o
1248        } else {
1249            p
1250        }
1251    }
1252
1253    /// Like `temp_path`, but also supports things where there is no corresponding
1254    /// OutputType, like noopt-bitcode or lto-bitcode.
1255    pub fn temp_path_ext_for_cgu(
1256        &self,
1257        ext: &str,
1258        codegen_unit_name: &str,
1259        invocation_temp: Option<&str>,
1260    ) -> PathBuf {
1261        let mut extension = codegen_unit_name.to_string();
1262
1263        // Append `.{invocation_temp}` to ensure temporary files are unique.
1264        if let Some(rng) = invocation_temp {
1265            extension.push('.');
1266            extension.push_str(rng);
1267        }
1268
1269        // FIXME: This is sketchy that we're not appending `.rcgu` when the ext is empty.
1270        // Append `.rcgu.{ext}`.
1271        if !ext.is_empty() {
1272            extension.push('.');
1273            extension.push_str(RUST_CGU_EXT);
1274            extension.push('.');
1275            extension.push_str(ext);
1276        }
1277
1278        let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory);
1279        maybe_strip_file_name(self.with_directory_and_extension(temps_directory, &extension))
1280    }
1281
1282    pub fn temp_path_for_diagnostic(&self, ext: &str) -> PathBuf {
1283        let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory);
1284        self.with_directory_and_extension(temps_directory, &ext)
1285    }
1286
1287    pub fn with_extension(&self, extension: &str) -> PathBuf {
1288        self.with_directory_and_extension(&self.out_directory, extension)
1289    }
1290
1291    pub fn with_directory_and_extension(&self, directory: &Path, extension: &str) -> PathBuf {
1292        {
    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:1292",
                        "rustc_session::config", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_session/src/config.rs"),
                        ::tracing_core::__macro_support::Option::Some(1292u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_session::config"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("using filestem={0} for {1}",
                                                    self.filestem, extension) as &dyn Value))])
            });
    } else { ; }
};debug!("using filestem={} for {extension}", self.filestem);
1293        let mut path = directory.join(&self.filestem);
1294        path.set_extension(extension);
1295        path
1296    }
1297
1298    /// Returns the path for the Split DWARF file - this can differ depending on which Split DWARF
1299    /// mode is being used, which is the logic that this function is intended to encapsulate.
1300    pub fn split_dwarf_path(
1301        &self,
1302        split_debuginfo_kind: SplitDebuginfo,
1303        split_dwarf_kind: SplitDwarfKind,
1304        cgu_name: &str,
1305        invocation_temp: Option<&str>,
1306    ) -> Option<PathBuf> {
1307        let obj_out = self.temp_path_for_cgu(OutputType::Object, cgu_name, invocation_temp);
1308        let dwo_out = self.temp_path_dwo_for_cgu(cgu_name, invocation_temp);
1309        match (split_debuginfo_kind, split_dwarf_kind) {
1310            (SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None,
1311            // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes
1312            // (pointing at the path which is being determined here). Use the path to the current
1313            // object file.
1314            (SplitDebuginfo::Packed | SplitDebuginfo::Unpacked, SplitDwarfKind::Single) => {
1315                Some(obj_out)
1316            }
1317            // Split mode emits the DWARF into a different file, use that path.
1318            (SplitDebuginfo::Packed | SplitDebuginfo::Unpacked, SplitDwarfKind::Split) => {
1319                Some(dwo_out)
1320            }
1321        }
1322    }
1323}
1324
1325// pub for rustdoc
1326pub fn parse_remap_path_scope(
1327    early_dcx: &EarlyDiagCtxt,
1328    matches: &getopts::Matches,
1329    unstable_opts: &UnstableOptions,
1330) -> RemapPathScopeComponents {
1331    if let Some(v) = matches.opt_str("remap-path-scope") {
1332        let mut slot = RemapPathScopeComponents::empty();
1333        for s in v.split(',') {
1334            slot |= match s {
1335                "macro" => RemapPathScopeComponents::MACRO,
1336                "diagnostics" => RemapPathScopeComponents::DIAGNOSTICS,
1337                "documentation" => {
1338                    if !unstable_opts.unstable_options {
1339                        early_dcx.early_fatal("remapping `documentation` path scope requested but `-Zunstable-options` not specified");
1340                    }
1341
1342                    RemapPathScopeComponents::DOCUMENTATION
1343                },
1344                "debuginfo" => RemapPathScopeComponents::DEBUGINFO,
1345                "coverage" => RemapPathScopeComponents::COVERAGE,
1346                "object" => RemapPathScopeComponents::OBJECT,
1347                "all" => RemapPathScopeComponents::all(),
1348                _ => early_dcx.early_fatal("argument for `--remap-path-scope` must be a comma separated list of scopes: `macro`, `diagnostics`, `documentation`, `debuginfo`, `coverage`, `object`, `all`"),
1349            }
1350        }
1351        slot
1352    } else {
1353        RemapPathScopeComponents::all()
1354    }
1355}
1356
1357#[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)]
1358pub struct Sysroot {
1359    pub explicit: Option<PathBuf>,
1360    pub default: PathBuf,
1361}
1362
1363impl Sysroot {
1364    pub fn new(explicit: Option<PathBuf>) -> Sysroot {
1365        Sysroot { explicit, default: filesearch::default_sysroot() }
1366    }
1367
1368    /// Return explicit sysroot if it was passed with `--sysroot`, or default sysroot otherwise.
1369    pub fn path(&self) -> &Path {
1370        self.explicit.as_deref().unwrap_or(&self.default)
1371    }
1372
1373    /// Returns both explicit sysroot if it was passed with `--sysroot` and the default sysroot.
1374    pub fn all_paths(&self) -> impl Iterator<Item = &Path> {
1375        self.explicit.as_deref().into_iter().chain(iter::once(&*self.default))
1376    }
1377}
1378
1379pub fn host_tuple() -> &'static str {
1380    // Get the host triple out of the build environment. This ensures that our
1381    // idea of the host triple is the same as for the set of libraries we've
1382    // actually built. We can't just take LLVM's host triple because they
1383    // normalize all ix86 architectures to i386.
1384    //
1385    // Instead of grabbing the host triple (for the current host), we grab (at
1386    // compile time) the target triple that this rustc is built with and
1387    // calling that (at runtime) the host triple.
1388    (::core::option::Option::Some("x86_64-unknown-linux-gnu")option_env!("CFG_COMPILER_HOST_TRIPLE")).expect("CFG_COMPILER_HOST_TRIPLE")
1389}
1390
1391fn file_path_mapping(
1392    remap_path_prefix: Vec<(PathBuf, PathBuf)>,
1393    remap_path_scope: RemapPathScopeComponents,
1394) -> FilePathMapping {
1395    FilePathMapping::new(remap_path_prefix.clone(), remap_path_scope)
1396}
1397
1398impl Default for Options {
1399    fn default() -> Options {
1400        let unstable_opts = UnstableOptions::default();
1401
1402        // FIXME(Urgau): This is a hack that ideally shouldn't exist, but rustdoc
1403        // currently uses this `Default` implementation, so we have no choice but
1404        // to create a default working directory.
1405        let working_dir = {
1406            let working_dir = std::env::current_dir().unwrap();
1407            let file_mapping = file_path_mapping(Vec::new(), RemapPathScopeComponents::empty());
1408            file_mapping.to_real_filename(&RealFileName::empty(), &working_dir)
1409        };
1410
1411        Options {
1412            crate_types: Vec::new(),
1413            optimize: OptLevel::No,
1414            debuginfo: DebugInfo::None,
1415            lint_opts: Vec::new(),
1416            lint_cap: None,
1417            describe_lints: false,
1418            output_types: OutputTypes(BTreeMap::new()),
1419            search_paths: ::alloc::vec::Vec::new()vec![],
1420            sysroot: Sysroot::new(None),
1421            target_triple: TargetTuple::from_tuple(host_tuple()),
1422            test: false,
1423            incremental: None,
1424            unstable_opts,
1425            prints: Vec::new(),
1426            cg: Default::default(),
1427            error_format: ErrorOutputType::default(),
1428            diagnostic_width: None,
1429            externs: Externs(BTreeMap::new()),
1430            crate_name: None,
1431            libs: Vec::new(),
1432            unstable_features: UnstableFeatures::Disallow,
1433            debug_assertions: true,
1434            actually_rustdoc: false,
1435            resolve_doc_links: ResolveDocLinks::None,
1436            trimmed_def_paths: false,
1437            cli_forced_codegen_units: None,
1438            cli_forced_local_thinlto_off: false,
1439            remap_path_prefix: Vec::new(),
1440            remap_path_scope: RemapPathScopeComponents::all(),
1441            real_rust_source_base_dir: None,
1442            real_rustc_dev_source_base_dir: None,
1443            edition: DEFAULT_EDITION,
1444            json_artifact_notifications: false,
1445            json_timings: false,
1446            json_unused_externs: JsonUnusedExterns::No,
1447            json_future_incompat: false,
1448            pretty: None,
1449            working_dir,
1450            color: ColorConfig::Auto,
1451            logical_env: FxIndexMap::default(),
1452            verbose: false,
1453            target_modifiers: BTreeMap::default(),
1454            mitigation_coverage_map: Default::default(),
1455        }
1456    }
1457}
1458
1459impl Options {
1460    /// Returns `true` if there is a reason to build the dep graph.
1461    pub fn build_dep_graph(&self) -> bool {
1462        self.incremental.is_some()
1463            || self.unstable_opts.dump_dep_graph
1464            || self.unstable_opts.query_dep_graph
1465    }
1466
1467    pub fn file_path_mapping(&self) -> FilePathMapping {
1468        file_path_mapping(self.remap_path_prefix.clone(), self.remap_path_scope)
1469    }
1470
1471    /// Returns `true` if there will be an output file generated.
1472    pub fn will_create_output_file(&self) -> bool {
1473        !self.unstable_opts.parse_crate_root_only && // The file is just being parsed
1474            self.unstable_opts.ls.is_empty() // The file is just being queried
1475    }
1476
1477    #[inline]
1478    pub fn share_generics(&self) -> bool {
1479        match self.unstable_opts.share_generics {
1480            Some(setting) => setting,
1481            None => match self.optimize {
1482                OptLevel::No | OptLevel::Less | OptLevel::Size | OptLevel::SizeMin => true,
1483                OptLevel::More | OptLevel::Aggressive => false,
1484            },
1485        }
1486    }
1487
1488    pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion {
1489        self.cg.symbol_mangling_version.unwrap_or(SymbolManglingVersion::V0)
1490    }
1491
1492    #[inline]
1493    pub fn autodiff_enabled(&self) -> bool {
1494        self.unstable_opts.autodiff.contains(&AutoDiff::Enable)
1495    }
1496}
1497
1498impl UnstableOptions {
1499    pub fn dcx_flags(&self, can_emit_warnings: bool) -> DiagCtxtFlags {
1500        DiagCtxtFlags {
1501            can_emit_warnings,
1502            treat_err_as_bug: self.treat_err_as_bug,
1503            eagerly_emit_delayed_bugs: self.eagerly_emit_delayed_bugs,
1504            macro_backtrace: self.macro_backtrace,
1505            deduplicate_diagnostics: self.deduplicate_diagnostics,
1506            track_diagnostics: self.track_diagnostics,
1507        }
1508    }
1509
1510    pub fn src_hash_algorithm(&self, target: &Target) -> SourceFileHashAlgorithm {
1511        self.src_hash_algorithm.unwrap_or_else(|| {
1512            if target.is_like_msvc {
1513                SourceFileHashAlgorithm::Sha256
1514            } else {
1515                SourceFileHashAlgorithm::Md5
1516            }
1517        })
1518    }
1519
1520    pub fn checksum_hash_algorithm(&self) -> Option<SourceFileHashAlgorithm> {
1521        self.checksum_hash_algorithm
1522    }
1523}
1524
1525// The type of entry function, so users can have their own entry functions
1526#[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 ::rustc_data_structures::stable_hasher::StableHash for
            EntryFnType {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hasher::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    EntryFnType::Main { sigpipe: ref __binding_0 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
1527pub enum EntryFnType {
1528    Main {
1529        /// Specifies what to do with `SIGPIPE` before calling `fn main()`.
1530        ///
1531        /// What values that are valid and what they mean must be in sync
1532        /// across rustc and libstd, but we don't want it public in libstd,
1533        /// so we take a bit of an unusual approach with simple constants
1534        /// and an `include!()`.
1535        sigpipe: u8,
1536    },
1537}
1538
1539pub use rustc_hir::attrs::CrateType;
1540
1541#[derive(#[automatically_derived]
impl ::core::clone::Clone for Passes {
    #[inline]
    fn clone(&self) -> Passes {
        match self {
            Passes::Some(__self_0) =>
                Passes::Some(::core::clone::Clone::clone(__self_0)),
            Passes::All => Passes::All,
        }
    }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for Passes {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            Passes::Some(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash, #[automatically_derived]
impl ::core::fmt::Debug for Passes {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Passes::Some(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Some",
                    &__self_0),
            Passes::All => ::core::fmt::Formatter::write_str(f, "All"),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Passes {
    #[inline]
    fn eq(&self, other: &Passes) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (Passes::Some(__self_0), Passes::Some(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Passes {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Vec<String>>;
    }
}Eq, const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for Passes {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        Passes::Some(ref __binding_0) => { 0usize }
                        Passes::All => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    Passes::Some(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    Passes::All => {}
                }
            }
        }
    };Encodable, const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for Passes {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        Passes::Some(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => { Passes::All }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `Passes`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };Decodable)]
1542pub enum Passes {
1543    Some(Vec<String>),
1544    All,
1545}
1546
1547impl Passes {
1548    fn is_empty(&self) -> bool {
1549        match *self {
1550            Passes::Some(ref v) => v.is_empty(),
1551            Passes::All => false,
1552        }
1553    }
1554
1555    pub(crate) fn extend(&mut self, passes: impl IntoIterator<Item = String>) {
1556        match *self {
1557            Passes::Some(ref mut v) => v.extend(passes),
1558            Passes::All => {}
1559        }
1560    }
1561}
1562
1563#[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)]
1564pub enum PAuthKey {
1565    A,
1566    B,
1567}
1568
1569#[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)]
1570pub struct PacRet {
1571    pub leaf: bool,
1572    pub pc: bool,
1573    pub key: PAuthKey,
1574}
1575
1576#[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)]
1577pub struct BranchProtection {
1578    pub bti: bool,
1579    pub pac_ret: Option<PacRet>,
1580    pub gcs: bool,
1581}
1582
1583pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
1584    // First disallow some configuration given on the command line
1585    cfg::disallow_cfgs(sess, &user_cfg);
1586
1587    // Then combine the configuration requested by the session (command line) with
1588    // some default and generated configuration items.
1589    user_cfg.extend(cfg::default_configuration(sess));
1590    user_cfg
1591}
1592
1593pub fn build_target_config(
1594    early_dcx: &EarlyDiagCtxt,
1595    target: &TargetTuple,
1596    sysroot: &Path,
1597    unstable_options: bool,
1598) -> Target {
1599    match Target::search(target, sysroot, unstable_options) {
1600        Ok((target, warnings)) => {
1601            for warning in warnings.warning_messages() {
1602                early_dcx.early_warn(warning)
1603            }
1604
1605            if !#[allow(non_exhaustive_omitted_patterns)] match target.pointer_width {
    16 | 32 | 64 => true,
    _ => false,
}matches!(target.pointer_width, 16 | 32 | 64) {
1606                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!(
1607                    "target specification was invalid: unrecognized target-pointer-width {}",
1608                    target.pointer_width
1609                ))
1610            }
1611            target
1612        }
1613        Err(e) => {
1614            let mut err =
1615                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}"));
1616            err.help("run `rustc --print target-list` for a list of built-in targets");
1617            let typed = target.tuple();
1618            let limit = typed.len() / 3 + 1;
1619            if let Some(suggestion) = rustc_target::spec::TARGETS
1620                .iter()
1621                .filter_map(|&t| {
1622                    rustc_span::edit_distance::edit_distance_with_substrings(typed, t, limit)
1623                        .map(|d| (d, t))
1624                })
1625                .min_by_key(|(d, _)| *d)
1626                .map(|(_, t)| t)
1627            {
1628                err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("did you mean `{0}`?", suggestion))
    })format!("did you mean `{suggestion}`?"));
1629            }
1630            err.emit()
1631        }
1632    }
1633}
1634
1635#[derive(#[automatically_derived]
impl ::core::marker::Copy for OptionStability { }Copy, #[automatically_derived]
impl ::core::clone::Clone for OptionStability {
    #[inline]
    fn clone(&self) -> OptionStability { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for OptionStability {
    #[inline]
    fn eq(&self, other: &OptionStability) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for OptionStability {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for OptionStability {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                OptionStability::Stable => "Stable",
                OptionStability::Unstable => "Unstable",
            })
    }
}Debug)]
1636pub enum OptionStability {
1637    Stable,
1638    Unstable,
1639}
1640
1641#[derive(#[automatically_derived]
impl ::core::marker::Copy for OptionKind { }Copy, #[automatically_derived]
impl ::core::clone::Clone for OptionKind {
    #[inline]
    fn clone(&self) -> OptionKind { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for OptionKind {
    #[inline]
    fn eq(&self, other: &OptionKind) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for OptionKind {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for OptionKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                OptionKind::Opt => "Opt",
                OptionKind::Multi => "Multi",
                OptionKind::Flag => "Flag",
                OptionKind::FlagMulti => "FlagMulti",
            })
    }
}Debug)]
1642pub enum OptionKind {
1643    /// An option that takes a value, and cannot appear more than once (e.g. `--out-dir`).
1644    ///
1645    /// Corresponds to [`getopts::Options::optopt`].
1646    Opt,
1647
1648    /// An option that takes a value, and can appear multiple times (e.g. `--emit`).
1649    ///
1650    /// Corresponds to [`getopts::Options::optmulti`].
1651    Multi,
1652
1653    /// An option that does not take a value, and cannot appear more than once (e.g. `--help`).
1654    ///
1655    /// Corresponds to [`getopts::Options::optflag`].
1656    /// The `hint` string must be empty.
1657    Flag,
1658
1659    /// An option that does not take a value, and can appear multiple times (e.g. `-O`).
1660    ///
1661    /// Corresponds to [`getopts::Options::optflagmulti`].
1662    /// The `hint` string must be empty.
1663    FlagMulti,
1664}
1665
1666pub struct RustcOptGroup {
1667    /// The "primary" name for this option. Normally equal to `long_name`,
1668    /// except for options that don't have a long name, in which case
1669    /// `short_name` is used.
1670    ///
1671    /// This is needed when interacting with `getopts` in some situations,
1672    /// because if an option has both forms, that library treats the long name
1673    /// as primary and the short name as an alias.
1674    pub name: &'static str,
1675    stability: OptionStability,
1676    kind: OptionKind,
1677
1678    short_name: &'static str,
1679    long_name: &'static str,
1680    desc: &'static str,
1681    value_hint: &'static str,
1682
1683    /// If true, this option should not be printed by `rustc --help`, but
1684    /// should still be printed by `rustc --help -v`.
1685    pub is_verbose_help_only: bool,
1686}
1687
1688impl RustcOptGroup {
1689    pub fn is_stable(&self) -> bool {
1690        self.stability == OptionStability::Stable
1691    }
1692
1693    pub fn apply(&self, options: &mut getopts::Options) {
1694        let &Self { short_name, long_name, desc, value_hint, .. } = self;
1695        match self.kind {
1696            OptionKind::Opt => options.optopt(short_name, long_name, desc, value_hint),
1697            OptionKind::Multi => options.optmulti(short_name, long_name, desc, value_hint),
1698            OptionKind::Flag => options.optflag(short_name, long_name, desc),
1699            OptionKind::FlagMulti => options.optflagmulti(short_name, long_name, desc),
1700        };
1701    }
1702
1703    /// This is for diagnostics-only.
1704    pub fn long_name(&self) -> &str {
1705        self.long_name
1706    }
1707}
1708
1709pub fn make_opt(
1710    stability: OptionStability,
1711    kind: OptionKind,
1712    short_name: &'static str,
1713    long_name: &'static str,
1714    desc: &'static str,
1715    value_hint: &'static str,
1716) -> RustcOptGroup {
1717    // "Flag" options don't have a value, and therefore don't have a value hint.
1718    match kind {
1719        OptionKind::Opt | OptionKind::Multi => {}
1720        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, ""),
1721    }
1722    RustcOptGroup {
1723        name: cmp::max_by_key(short_name, long_name, |s| s.len()),
1724        stability,
1725        kind,
1726        short_name,
1727        long_name,
1728        desc,
1729        value_hint,
1730        is_verbose_help_only: false,
1731    }
1732}
1733
1734static EDITION_STRING: LazyLock<String> = LazyLock::new(|| {
1735    ::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!(
1736        "Specify which edition of the compiler to use when compiling code. \
1737The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE_EDITION}."
1738    )
1739});
1740
1741static EMIT_HELP: LazyLock<String> = LazyLock::new(|| {
1742    let mut result =
1743        String::from("Comma separated list of types of output for the compiler to emit.\n");
1744    result.push_str("Each TYPE has the default FILE name:\n");
1745
1746    for output in OutputType::iter_all() {
1747        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()));
1748    }
1749
1750    result
1751});
1752
1753/// Returns all rustc command line options, including metadata for
1754/// each option, such as whether the option is stable.
1755///
1756/// # Option style guidelines
1757///
1758/// - `<param>`: Indicates a required parameter
1759/// - `[param]`: Indicates an optional parameter
1760/// - `|`: Indicates a mutually exclusive option
1761/// - `*`: a list element with description
1762pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
1763    use OptionKind::{Flag, FlagMulti, Multi, Opt};
1764    use OptionStability::{Stable, Unstable};
1765
1766    use self::make_opt as opt;
1767
1768    let mut options = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [opt(Stable, Flag, "h", "help", "Display this message", ""),
                opt(Stable, Multi, "", "cfg",
                    "Configure the compilation environment.\n\
                SPEC supports the syntax `<NAME>[=\"<VALUE>\"]`.",
                    "<SPEC>"),
                opt(Stable, Multi, "", "check-cfg",
                    "Provide list of expected cfgs for checking", "<SPEC>"),
                opt(Stable, Multi, "L", "",
                    "Add a directory to the library search path. \
                The optional KIND can be one of <dependency|crate|native|framework|all> (default: all).",
                    "[<KIND>=]<PATH>"),
                opt(Stable, Multi, "l", "",
                    "Link the generated crate(s) to the specified native\n\
                library NAME. The optional KIND can be one of\n\
                <static|framework|dylib> (default: dylib).\n\
                Optional comma separated MODIFIERS\n\
                <bundle|verbatim|whole-archive|as-needed>\n\
                may be specified each with a prefix of either '+' to\n\
                enable or '-' to disable.",
                    "[<KIND>[:<MODIFIERS>]=]<NAME>[:<RENAME>]"),
                make_crate_type_option(),
                opt(Stable, Opt, "", "crate-name",
                    "Specify the name of the crate being built", "<NAME>"),
                opt(Stable, Opt, "", "edition", &EDITION_STRING,
                    EDITION_NAME_LIST),
                opt(Stable, Multi, "", "emit", &EMIT_HELP, "<TYPE>[=<FILE>]"),
                opt(Stable, Multi, "", "print", &print_request::PRINT_HELP,
                    "<INFO>[=<FILE>]"),
                opt(Stable, FlagMulti, "g", "",
                    "Equivalent to -C debuginfo=2", ""),
                opt(Stable, FlagMulti, "O", "",
                    "Equivalent to -C opt-level=3", ""),
                opt(Stable, Opt, "o", "", "Write output to FILENAME",
                    "<FILENAME>"),
                opt(Stable, Opt, "", "out-dir",
                    "Write output to compiler-chosen filename in DIR", "<DIR>"),
                opt(Stable, Opt, "", "explain",
                    "Provide a detailed explanation of an error message",
                    "<OPT>"),
                opt(Stable, Flag, "", "test", "Build a test harness", ""),
                opt(Stable, Opt, "", "target",
                    "Target tuple for which the code is compiled", "<TARGET>"),
                opt(Stable, Multi, "A", "allow", "Set lint allowed",
                    "<LINT>"),
                opt(Stable, Multi, "W", "warn", "Set lint warnings",
                    "<LINT>"),
                opt(Stable, Multi, "", "force-warn", "Set lint force-warn",
                    "<LINT>"),
                opt(Stable, Multi, "D", "deny", "Set lint denied", "<LINT>"),
                opt(Stable, Multi, "F", "forbid", "Set lint forbidden",
                    "<LINT>"),
                opt(Stable, Multi, "", "cap-lints",
                    "Set the most restrictive lint level. More restrictive lints are capped at this level",
                    "<LEVEL>"),
                opt(Stable, Multi, "C", "codegen", "Set a codegen option",
                    "<OPT>[=<VALUE>]"),
                opt(Stable, Flag, "V", "version",
                    "Print version info and exit", ""),
                opt(Stable, Flag, "v", "verbose", "Use verbose output", "")]))vec![
1769        opt(Stable, Flag, "h", "help", "Display this message", ""),
1770        opt(
1771            Stable,
1772            Multi,
1773            "",
1774            "cfg",
1775            "Configure the compilation environment.\n\
1776                SPEC supports the syntax `<NAME>[=\"<VALUE>\"]`.",
1777            "<SPEC>",
1778        ),
1779        opt(Stable, Multi, "", "check-cfg", "Provide list of expected cfgs for checking", "<SPEC>"),
1780        opt(
1781            Stable,
1782            Multi,
1783            "L",
1784            "",
1785            "Add a directory to the library search path. \
1786                The optional KIND can be one of <dependency|crate|native|framework|all> (default: all).",
1787            "[<KIND>=]<PATH>",
1788        ),
1789        opt(
1790            Stable,
1791            Multi,
1792            "l",
1793            "",
1794            "Link the generated crate(s) to the specified native\n\
1795                library NAME. The optional KIND can be one of\n\
1796                <static|framework|dylib> (default: dylib).\n\
1797                Optional comma separated MODIFIERS\n\
1798                <bundle|verbatim|whole-archive|as-needed>\n\
1799                may be specified each with a prefix of either '+' to\n\
1800                enable or '-' to disable.",
1801            "[<KIND>[:<MODIFIERS>]=]<NAME>[:<RENAME>]",
1802        ),
1803        make_crate_type_option(),
1804        opt(Stable, Opt, "", "crate-name", "Specify the name of the crate being built", "<NAME>"),
1805        opt(Stable, Opt, "", "edition", &EDITION_STRING, EDITION_NAME_LIST),
1806        opt(Stable, Multi, "", "emit", &EMIT_HELP, "<TYPE>[=<FILE>]"),
1807        opt(Stable, Multi, "", "print", &print_request::PRINT_HELP, "<INFO>[=<FILE>]"),
1808        opt(Stable, FlagMulti, "g", "", "Equivalent to -C debuginfo=2", ""),
1809        opt(Stable, FlagMulti, "O", "", "Equivalent to -C opt-level=3", ""),
1810        opt(Stable, Opt, "o", "", "Write output to FILENAME", "<FILENAME>"),
1811        opt(Stable, Opt, "", "out-dir", "Write output to compiler-chosen filename in DIR", "<DIR>"),
1812        opt(
1813            Stable,
1814            Opt,
1815            "",
1816            "explain",
1817            "Provide a detailed explanation of an error message",
1818            "<OPT>",
1819        ),
1820        opt(Stable, Flag, "", "test", "Build a test harness", ""),
1821        opt(Stable, Opt, "", "target", "Target tuple for which the code is compiled", "<TARGET>"),
1822        opt(Stable, Multi, "A", "allow", "Set lint allowed", "<LINT>"),
1823        opt(Stable, Multi, "W", "warn", "Set lint warnings", "<LINT>"),
1824        opt(Stable, Multi, "", "force-warn", "Set lint force-warn", "<LINT>"),
1825        opt(Stable, Multi, "D", "deny", "Set lint denied", "<LINT>"),
1826        opt(Stable, Multi, "F", "forbid", "Set lint forbidden", "<LINT>"),
1827        opt(
1828            Stable,
1829            Multi,
1830            "",
1831            "cap-lints",
1832            "Set the most restrictive lint level. More restrictive lints are capped at this level",
1833            "<LEVEL>",
1834        ),
1835        opt(Stable, Multi, "C", "codegen", "Set a codegen option", "<OPT>[=<VALUE>]"),
1836        opt(Stable, Flag, "V", "version", "Print version info and exit", ""),
1837        opt(Stable, Flag, "v", "verbose", "Use verbose output", ""),
1838    ];
1839
1840    // Options in this list are hidden from `rustc --help` by default, but are
1841    // shown by `rustc --help -v`.
1842    let verbose_only = [
1843        opt(
1844            Stable,
1845            Multi,
1846            "",
1847            "extern",
1848            "Specify where an external rust library is located",
1849            "<NAME>[=<PATH>]",
1850        ),
1851        opt(Stable, Opt, "", "sysroot", "Override the system root", "<PATH>"),
1852        opt(Unstable, Multi, "Z", "", "Set unstable / perma-unstable options", "<FLAG>"),
1853        opt(
1854            Stable,
1855            Opt,
1856            "",
1857            "error-format",
1858            "How errors and other messages are produced",
1859            "<human|json|short>",
1860        ),
1861        opt(Stable, Multi, "", "json", "Configure the JSON output of the compiler", "<CONFIG>"),
1862        opt(
1863            Stable,
1864            Opt,
1865            "",
1866            "color",
1867            "Configure coloring of output:
1868                * auto   = colorize, if output goes to a tty (default);
1869                * always = always colorize output;
1870                * never  = never colorize output",
1871            "<auto|always|never>",
1872        ),
1873        opt(
1874            Stable,
1875            Opt,
1876            "",
1877            "diagnostic-width",
1878            "Inform rustc of the width of the output so that diagnostics can be truncated to fit",
1879            "<WIDTH>",
1880        ),
1881        opt(
1882            Stable,
1883            Multi,
1884            "",
1885            "remap-path-prefix",
1886            "Remap source names in all output (compiler messages and output files)",
1887            "<FROM>=<TO>",
1888        ),
1889        opt(
1890            Stable,
1891            Opt,
1892            "",
1893            "remap-path-scope",
1894            "Defines which scopes of paths should be remapped by `--remap-path-prefix`",
1895            "<macro,diagnostics,debuginfo,coverage,object,all>",
1896        ),
1897        opt(Unstable, Multi, "", "env-set", "Inject an environment variable", "<VAR>=<VALUE>"),
1898    ];
1899    options.extend(verbose_only.into_iter().map(|mut opt| {
1900        opt.is_verbose_help_only = true;
1901        opt
1902    }));
1903
1904    options
1905}
1906
1907pub fn get_cmd_lint_options(
1908    early_dcx: &EarlyDiagCtxt,
1909    matches: &getopts::Matches,
1910) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
1911    let mut lint_opts_with_position = ::alloc::vec::Vec::new()vec![];
1912    let mut describe_lints = false;
1913
1914    for level in [lint::Allow, lint::Warn, lint::ForceWarn, lint::Deny, lint::Forbid] {
1915        for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
1916            if lint_name == "help" {
1917                describe_lints = true;
1918            } else {
1919                lint_opts_with_position.push((arg_pos, lint_name.replace('-', "_"), level));
1920            }
1921        }
1922    }
1923
1924    lint_opts_with_position.sort_by_key(|x| x.0);
1925    let lint_opts = lint_opts_with_position
1926        .iter()
1927        .cloned()
1928        .map(|(_, lint_name, level)| (lint_name, level))
1929        .collect();
1930
1931    let lint_cap = matches.opt_str("cap-lints").map(|cap| {
1932        lint::Level::from_str(&cap)
1933            .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}`")))
1934    });
1935
1936    (lint_opts, describe_lints, lint_cap)
1937}
1938
1939/// Parses the `--color` flag.
1940pub fn parse_color(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> ColorConfig {
1941    match matches.opt_str("color").as_deref() {
1942        Some("auto") => ColorConfig::Auto,
1943        Some("always") => ColorConfig::Always,
1944        Some("never") => ColorConfig::Never,
1945
1946        None => ColorConfig::Auto,
1947
1948        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!(
1949            "argument for `--color` must be auto, \
1950                 always or never (instead was `{arg}`)"
1951        )),
1952    }
1953}
1954
1955/// Possible json config files
1956pub struct JsonConfig {
1957    pub json_rendered: HumanReadableErrorType,
1958    pub json_color: ColorConfig,
1959    json_artifact_notifications: bool,
1960    /// Output start and end timestamps of several high-level compilation sections
1961    /// (frontend, backend, linker).
1962    json_timings: bool,
1963    pub json_unused_externs: JsonUnusedExterns,
1964    json_future_incompat: bool,
1965}
1966
1967/// Report unused externs in event stream
1968#[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)]
1969pub enum JsonUnusedExterns {
1970    /// Do not
1971    No,
1972    /// Report, but do not exit with failure status for deny/forbid
1973    Silent,
1974    /// Report, and also exit with failure status for deny/forbid
1975    Loud,
1976}
1977
1978impl JsonUnusedExterns {
1979    pub fn is_enabled(&self) -> bool {
1980        match self {
1981            JsonUnusedExterns::No => false,
1982            JsonUnusedExterns::Loud | JsonUnusedExterns::Silent => true,
1983        }
1984    }
1985
1986    pub fn is_loud(&self) -> bool {
1987        match self {
1988            JsonUnusedExterns::No | JsonUnusedExterns::Silent => false,
1989            JsonUnusedExterns::Loud => true,
1990        }
1991    }
1992}
1993
1994/// Parse the `--json` flag.
1995///
1996/// The first value returned is how to render JSON diagnostics, and the second
1997/// is whether or not artifact notifications are enabled.
1998pub fn parse_json(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> JsonConfig {
1999    let mut json_rendered = HumanReadableErrorType { short: false, unicode: false };
2000    let mut json_color = ColorConfig::Never;
2001    let mut json_artifact_notifications = false;
2002    let mut json_unused_externs = JsonUnusedExterns::No;
2003    let mut json_future_incompat = false;
2004    let mut json_timings = false;
2005    for option in matches.opt_strs("json") {
2006        // For now conservatively forbid `--color` with `--json` since `--json`
2007        // won't actually be emitting any colors and anything colorized is
2008        // embedded in a diagnostic message anyway.
2009        if matches.opt_str("color").is_some() {
2010            early_dcx.early_fatal("cannot specify the `--color` option with `--json`");
2011        }
2012
2013        for sub_option in option.split(',') {
2014            match sub_option {
2015                "diagnostic-short" => {
2016                    json_rendered = HumanReadableErrorType { short: true, unicode: false };
2017                }
2018                "diagnostic-unicode" => {
2019                    json_rendered = HumanReadableErrorType { short: false, unicode: true };
2020                }
2021                "diagnostic-rendered-ansi" => json_color = ColorConfig::Always,
2022                "artifacts" => json_artifact_notifications = true,
2023                "timings" => json_timings = true,
2024                "unused-externs" => json_unused_externs = JsonUnusedExterns::Loud,
2025                "unused-externs-silent" => json_unused_externs = JsonUnusedExterns::Silent,
2026                "future-incompat" => json_future_incompat = true,
2027                s => early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unknown `--json` option `{0}`", s))
    })format!("unknown `--json` option `{s}`")),
2028            }
2029        }
2030    }
2031
2032    JsonConfig {
2033        json_rendered,
2034        json_color,
2035        json_artifact_notifications,
2036        json_timings,
2037        json_unused_externs,
2038        json_future_incompat,
2039    }
2040}
2041
2042/// Parses the `--error-format` flag.
2043pub fn parse_error_format(
2044    early_dcx: &mut EarlyDiagCtxt,
2045    matches: &getopts::Matches,
2046    color_config: ColorConfig,
2047    json_color: ColorConfig,
2048    json_rendered: HumanReadableErrorType,
2049) -> ErrorOutputType {
2050    let default_kind = HumanReadableErrorType { short: false, unicode: false };
2051    // We need the `opts_present` check because the driver will send us Matches
2052    // with only stable options if no unstable options are used. Since error-format
2053    // is unstable, it will not be present. We have to use `opts_present` not
2054    // `opt_present` because the latter will panic.
2055    let error_format = if matches.opts_present(&["error-format".to_owned()]) {
2056        match matches.opt_str("error-format").as_deref() {
2057            None | Some("human") => {
2058                ErrorOutputType::HumanReadable { color_config, kind: default_kind }
2059            }
2060            Some("json") => {
2061                ErrorOutputType::Json { pretty: false, json_rendered, color_config: json_color }
2062            }
2063            Some("pretty-json") => {
2064                ErrorOutputType::Json { pretty: true, json_rendered, color_config: json_color }
2065            }
2066            Some("short") => ErrorOutputType::HumanReadable {
2067                kind: HumanReadableErrorType { short: true, unicode: false },
2068                color_config,
2069            },
2070            Some("human-unicode") => ErrorOutputType::HumanReadable {
2071                kind: HumanReadableErrorType { short: false, unicode: true },
2072                color_config,
2073            },
2074            Some(arg) => {
2075                early_dcx.set_error_format(ErrorOutputType::HumanReadable {
2076                    color_config,
2077                    kind: default_kind,
2078                });
2079                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!(
2080                    "argument for `--error-format` must be `human`, `human-unicode`, \
2081                    `json`, `pretty-json` or `short` (instead was `{arg}`)"
2082                ))
2083            }
2084        }
2085    } else {
2086        ErrorOutputType::HumanReadable { color_config, kind: default_kind }
2087    };
2088
2089    match error_format {
2090        ErrorOutputType::Json { .. } => {}
2091
2092        // Conservatively require that the `--json` argument is coupled with
2093        // `--error-format=json`. This means that `--json` is specified we
2094        // should actually be emitting JSON blobs.
2095        _ if !matches.opt_strs("json").is_empty() => {
2096            early_dcx.early_fatal("using `--json` requires also using `--error-format=json`");
2097        }
2098
2099        _ => {}
2100    }
2101
2102    error_format
2103}
2104
2105pub fn parse_crate_edition(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Edition {
2106    let edition = match matches.opt_str("edition") {
2107        Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| {
2108            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!(
2109                "argument for `--edition` must be one of: \
2110                     {EDITION_NAME_LIST}. (instead was `{arg}`)"
2111            ))
2112        }),
2113        None => DEFAULT_EDITION,
2114    };
2115
2116    if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) {
2117        let is_nightly = nightly_options::match_is_nightly_build(matches);
2118        let msg = if !is_nightly {
2119            ::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!(
2120                "the crate requires edition {edition}, but the latest edition supported by this Rust version is {LATEST_STABLE_EDITION}"
2121            )
2122        } else {
2123            ::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")
2124        };
2125        early_dcx.early_fatal(msg)
2126    }
2127
2128    edition
2129}
2130
2131fn check_error_format_stability(
2132    early_dcx: &EarlyDiagCtxt,
2133    unstable_opts: &UnstableOptions,
2134    is_nightly_build: bool,
2135    format: ErrorOutputType,
2136) {
2137    if unstable_opts.unstable_options || is_nightly_build {
2138        return;
2139    }
2140    let format = match format {
2141        ErrorOutputType::Json { pretty: true, .. } => "pretty-json",
2142        ErrorOutputType::HumanReadable { kind, .. } => match kind {
2143            HumanReadableErrorType { unicode: true, .. } => "human-unicode",
2144            _ => return,
2145        },
2146        _ => return,
2147    };
2148    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"))
2149}
2150
2151fn parse_output_types(
2152    early_dcx: &EarlyDiagCtxt,
2153    unstable_opts: &UnstableOptions,
2154    matches: &getopts::Matches,
2155) -> OutputTypes {
2156    let mut output_types = BTreeMap::new();
2157    if !unstable_opts.parse_crate_root_only {
2158        for list in matches.opt_strs("emit") {
2159            for output_type in list.split(',') {
2160                let (shorthand, path) = split_out_file_name(output_type);
2161                let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| {
2162                    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!(
2163                        "unknown emission type: `{shorthand}` - expected one of: {display}",
2164                        display = OutputType::shorthands_display(),
2165                    ))
2166                });
2167                if output_type == OutputType::ThinLinkBitcode && !unstable_opts.unstable_options {
2168                    early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} requested but -Zunstable-options not specified",
                OutputType::ThinLinkBitcode.shorthand()))
    })format!(
2169                        "{} requested but -Zunstable-options not specified",
2170                        OutputType::ThinLinkBitcode.shorthand()
2171                    ));
2172                }
2173                output_types.insert(output_type, path);
2174            }
2175        }
2176    };
2177    if output_types.is_empty() {
2178        output_types.insert(OutputType::Exe, None);
2179    }
2180    OutputTypes(output_types)
2181}
2182
2183fn split_out_file_name(arg: &str) -> (&str, Option<OutFileName>) {
2184    match arg.split_once('=') {
2185        None => (arg, None),
2186        Some((kind, "-")) => (kind, Some(OutFileName::Stdout)),
2187        Some((kind, path)) => (kind, Some(OutFileName::Real(PathBuf::from(path)))),
2188    }
2189}
2190
2191fn should_override_cgus_and_disable_thinlto(
2192    early_dcx: &EarlyDiagCtxt,
2193    output_types: &OutputTypes,
2194    matches: &getopts::Matches,
2195    mut codegen_units: Option<usize>,
2196) -> (bool, Option<usize>) {
2197    let mut disable_local_thinlto = false;
2198    // Issue #30063: if user requests LLVM-related output to one
2199    // particular path, disable codegen-units.
2200    let incompatible: Vec<_> = output_types
2201        .0
2202        .iter()
2203        .map(|ot_path| ot_path.0)
2204        .filter(|ot| !ot.is_compatible_with_codegen_units_and_single_output_file())
2205        .map(|ot| ot.shorthand())
2206        .collect();
2207    if !incompatible.is_empty() {
2208        match codegen_units {
2209            Some(n) if n > 1 => {
2210                if matches.opt_present("o") {
2211                    for ot in &incompatible {
2212                        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!(
2213                            "`--emit={ot}` with `-o` incompatible with \
2214                                 `-C codegen-units=N` for N > 1",
2215                        ));
2216                    }
2217                    early_dcx.early_warn("resetting to default -C codegen-units=1");
2218                    codegen_units = Some(1);
2219                    disable_local_thinlto = true;
2220                }
2221            }
2222            _ => {
2223                codegen_units = Some(1);
2224                disable_local_thinlto = true;
2225            }
2226        }
2227    }
2228
2229    if codegen_units == Some(0) {
2230        early_dcx.early_fatal("value for codegen units must be a positive non-zero integer");
2231    }
2232
2233    (disable_local_thinlto, codegen_units)
2234}
2235
2236pub fn parse_target_triple(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> TargetTuple {
2237    match matches.opt_str("target") {
2238        Some(target) if target.ends_with(".json") => {
2239            let path = Path::new(&target);
2240            TargetTuple::from_path(path).unwrap_or_else(|_| {
2241                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"))
2242            })
2243        }
2244        Some(target) => TargetTuple::TargetTuple(target),
2245        _ => TargetTuple::from_tuple(host_tuple()),
2246    }
2247}
2248
2249fn parse_opt_level(
2250    early_dcx: &EarlyDiagCtxt,
2251    matches: &getopts::Matches,
2252    cg: &CodegenOptions,
2253) -> OptLevel {
2254    // The `-O` and `-C opt-level` flags specify the same setting, so we want to be able
2255    // to use them interchangeably. However, because they're technically different flags,
2256    // we need to work out manually which should take precedence if both are supplied (i.e.
2257    // the rightmost flag). We do this by finding the (rightmost) position of both flags and
2258    // comparing them. Note that if a flag is not found, its position will be `None`, which
2259    // always compared less than `Some(_)`.
2260    let max_o = matches.opt_positions("O").into_iter().max();
2261    let max_c = matches
2262        .opt_strs_pos("C")
2263        .into_iter()
2264        .flat_map(|(i, s)| {
2265            // NB: This can match a string without `=`.
2266            if let Some("opt-level") = s.split('=').next() { Some(i) } else { None }
2267        })
2268        .max();
2269    if max_o > max_c {
2270        OptLevel::Aggressive
2271    } else {
2272        match cg.opt_level.as_ref() {
2273            "0" => OptLevel::No,
2274            "1" => OptLevel::Less,
2275            "2" => OptLevel::More,
2276            "3" => OptLevel::Aggressive,
2277            "s" => OptLevel::Size,
2278            "z" => OptLevel::SizeMin,
2279            arg => {
2280                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!(
2281                    "optimization level needs to be \
2282                            between 0-3, s or z (instead was `{arg}`)"
2283                ));
2284            }
2285        }
2286    }
2287}
2288
2289fn select_debuginfo(matches: &getopts::Matches, cg: &CodegenOptions) -> DebugInfo {
2290    let max_g = matches.opt_positions("g").into_iter().max();
2291    let max_c = matches
2292        .opt_strs_pos("C")
2293        .into_iter()
2294        .flat_map(|(i, s)| {
2295            // NB: This can match a string without `=`.
2296            if let Some("debuginfo") = s.split('=').next() { Some(i) } else { None }
2297        })
2298        .max();
2299    if max_g > max_c { DebugInfo::Full } else { cg.debuginfo }
2300}
2301
2302pub fn parse_externs(
2303    early_dcx: &EarlyDiagCtxt,
2304    matches: &getopts::Matches,
2305    unstable_opts: &UnstableOptions,
2306) -> Externs {
2307    let is_unstable_enabled = unstable_opts.unstable_options;
2308    let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new();
2309    for arg in matches.opt_strs("extern") {
2310        let ExternOpt { crate_name: name, path, options } =
2311            split_extern_opt(early_dcx, unstable_opts, &arg).unwrap_or_else(|e| e.emit());
2312
2313        let entry = externs.entry(name.to_owned());
2314
2315        use std::collections::btree_map::Entry;
2316
2317        let entry = if let Some(path) = path {
2318            // --extern prelude_name=some_file.rlib
2319            let path = CanonicalizedPath::new(path);
2320            match entry {
2321                Entry::Vacant(vacant) => {
2322                    let files = BTreeSet::from_iter(iter::once(path));
2323                    vacant.insert(ExternEntry::new(ExternLocation::ExactPaths(files)))
2324                }
2325                Entry::Occupied(occupied) => {
2326                    let ext_ent = occupied.into_mut();
2327                    match ext_ent {
2328                        ExternEntry { location: ExternLocation::ExactPaths(files), .. } => {
2329                            files.insert(path);
2330                        }
2331                        ExternEntry {
2332                            location: location @ ExternLocation::FoundInLibrarySearchDirectories,
2333                            ..
2334                        } => {
2335                            // Exact paths take precedence over search directories.
2336                            let files = BTreeSet::from_iter(iter::once(path));
2337                            *location = ExternLocation::ExactPaths(files);
2338                        }
2339                    }
2340                    ext_ent
2341                }
2342            }
2343        } else {
2344            // --extern prelude_name
2345            match entry {
2346                Entry::Vacant(vacant) => {
2347                    vacant.insert(ExternEntry::new(ExternLocation::FoundInLibrarySearchDirectories))
2348                }
2349                Entry::Occupied(occupied) => {
2350                    // Ignore if already specified.
2351                    occupied.into_mut()
2352                }
2353            }
2354        };
2355
2356        let mut is_private_dep = false;
2357        let mut add_prelude = true;
2358        let mut nounused_dep = false;
2359        let mut force = false;
2360        if let Some(opts) = options {
2361            if !is_unstable_enabled {
2362                early_dcx.early_fatal(
2363                    "the `-Z unstable-options` flag must also be passed to \
2364                     enable `--extern` options",
2365                );
2366            }
2367            for opt in opts.split(',') {
2368                match opt {
2369                    "priv" => is_private_dep = true,
2370                    "noprelude" => {
2371                        if let ExternLocation::ExactPaths(_) = &entry.location {
2372                            add_prelude = false;
2373                        } else {
2374                            early_dcx.early_fatal(
2375                                "the `noprelude` --extern option requires a file path",
2376                            );
2377                        }
2378                    }
2379                    "nounused" => nounused_dep = true,
2380                    "force" => force = true,
2381                    _ => early_dcx.early_fatal(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unknown --extern option `{0}`",
                opt))
    })format!("unknown --extern option `{opt}`")),
2382                }
2383            }
2384        }
2385
2386        // Crates start out being not private, and go to being private `priv`
2387        // is specified.
2388        entry.is_private_dep |= is_private_dep;
2389        // likewise `nounused`
2390        entry.nounused_dep |= nounused_dep;
2391        // and `force`
2392        entry.force |= force;
2393        // If any flag is missing `noprelude`, then add to the prelude.
2394        entry.add_prelude |= add_prelude;
2395    }
2396    Externs(externs)
2397}
2398
2399fn parse_remap_path_prefix(
2400    early_dcx: &EarlyDiagCtxt,
2401    matches: &getopts::Matches,
2402    unstable_opts: &UnstableOptions,
2403) -> Vec<(PathBuf, PathBuf)> {
2404    let mut mapping: Vec<(PathBuf, PathBuf)> = matches
2405        .opt_strs("remap-path-prefix")
2406        .into_iter()
2407        .map(|remap| match remap.rsplit_once('=') {
2408            None => {
2409                early_dcx.early_fatal("--remap-path-prefix must contain '=' between FROM and TO")
2410            }
2411            Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)),
2412        })
2413        .collect();
2414    match &unstable_opts.remap_cwd_prefix {
2415        Some(to) => match std::env::current_dir() {
2416            Ok(cwd) => mapping.push((cwd, to.clone())),
2417            Err(_) => (),
2418        },
2419        None => (),
2420    };
2421    mapping
2422}
2423
2424fn parse_logical_env(
2425    early_dcx: &EarlyDiagCtxt,
2426    matches: &getopts::Matches,
2427) -> FxIndexMap<String, String> {
2428    let mut vars = FxIndexMap::default();
2429
2430    for arg in matches.opt_strs("env-set") {
2431        if let Some((name, val)) = arg.split_once('=') {
2432            vars.insert(name.to_string(), val.to_string());
2433        } else {
2434            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}`"));
2435        }
2436    }
2437
2438    vars
2439}
2440
2441// JUSTIFICATION: before wrapper fn is available
2442#[allow(rustc::bad_opt_access)]
2443pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches) -> Options {
2444    let color = parse_color(early_dcx, matches);
2445
2446    let edition = parse_crate_edition(early_dcx, matches);
2447
2448    let crate_name = matches.opt_str("crate-name");
2449    let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref());
2450    let JsonConfig {
2451        json_rendered,
2452        json_color,
2453        json_artifact_notifications,
2454        json_timings,
2455        json_unused_externs,
2456        json_future_incompat,
2457    } = parse_json(early_dcx, matches);
2458
2459    let error_format = parse_error_format(early_dcx, matches, color, json_color, json_rendered);
2460
2461    early_dcx.set_error_format(error_format);
2462
2463    let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| {
2464        early_dcx.early_fatal("`--diagnostic-width` must be an positive integer");
2465    });
2466
2467    let unparsed_crate_types = matches.opt_strs("crate-type");
2468    let crate_types = parse_crate_types_from_list(unparsed_crate_types)
2469        .unwrap_or_else(|e| early_dcx.early_fatal(e));
2470
2471    let mut collected_options = Default::default();
2472
2473    let mut unstable_opts = UnstableOptions::build(early_dcx, matches, &mut collected_options);
2474    let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(early_dcx, matches);
2475
2476    if !unstable_opts.unstable_options && json_timings {
2477        early_dcx.early_fatal("--json=timings is unstable and requires using `-Zunstable-options`");
2478    }
2479
2480    check_error_format_stability(
2481        early_dcx,
2482        &unstable_opts,
2483        unstable_features.is_nightly_build(),
2484        error_format,
2485    );
2486
2487    let output_types = parse_output_types(early_dcx, &unstable_opts, matches);
2488
2489    let mut cg = CodegenOptions::build(early_dcx, matches, &mut collected_options);
2490    let (disable_local_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto(
2491        early_dcx,
2492        &output_types,
2493        matches,
2494        cg.codegen_units,
2495    );
2496
2497    if unstable_opts.threads == 0 {
2498        early_dcx.early_fatal("value for threads must be a positive non-zero integer");
2499    }
2500
2501    if unstable_opts.threads == parse::MAX_THREADS_CAP {
2502        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));
2503    }
2504
2505    let incremental = cg.incremental.as_ref().map(PathBuf::from);
2506
2507    if cg.profile_generate.enabled() && cg.profile_use.is_some() {
2508        early_dcx.early_fatal("options `-C profile-generate` and `-C profile-use` are exclusive");
2509    }
2510
2511    if unstable_opts.profile_sample_use.is_some()
2512        && (cg.profile_generate.enabled() || cg.profile_use.is_some())
2513    {
2514        early_dcx.early_fatal(
2515            "option `-Z profile-sample-use` cannot be used with `-C profile-generate` or `-C profile-use`",
2516        );
2517    }
2518
2519    // Check for unstable values of `-C symbol-mangling-version`.
2520    // This is what prevents them from being used on stable compilers.
2521    match cg.symbol_mangling_version {
2522        // Stable values:
2523        None | Some(SymbolManglingVersion::V0) => {}
2524
2525        // Unstable values:
2526        Some(SymbolManglingVersion::Legacy) => {
2527            if !unstable_opts.unstable_options {
2528                early_dcx.early_fatal(
2529                    "`-C symbol-mangling-version=legacy` requires `-Z unstable-options`",
2530                );
2531            }
2532        }
2533        Some(SymbolManglingVersion::Hashed) => {
2534            if !unstable_opts.unstable_options {
2535                early_dcx.early_fatal(
2536                    "`-C symbol-mangling-version=hashed` requires `-Z unstable-options`",
2537                );
2538            }
2539        }
2540    }
2541
2542    if cg.instrument_coverage != InstrumentCoverage::No {
2543        if cg.profile_generate.enabled() || cg.profile_use.is_some() {
2544            early_dcx.early_fatal(
2545                "option `-C instrument-coverage` is not compatible with either `-C profile-use` \
2546                or `-C profile-generate`",
2547            );
2548        }
2549
2550        // `-C instrument-coverage` implies `-C symbol-mangling-version=v0` - to ensure consistent
2551        // and reversible name mangling. Note, LLVM coverage tools can analyze coverage over
2552        // multiple runs, including some changes to source code; so mangled names must be consistent
2553        // across compilations.
2554        match cg.symbol_mangling_version {
2555            None => cg.symbol_mangling_version = Some(SymbolManglingVersion::V0),
2556            Some(SymbolManglingVersion::Legacy) => {
2557                early_dcx.early_warn(
2558                    "-C instrument-coverage requires symbol mangling version `v0`, \
2559                    but `-C symbol-mangling-version=legacy` was specified",
2560                );
2561            }
2562            Some(SymbolManglingVersion::V0) => {}
2563            Some(SymbolManglingVersion::Hashed) => {
2564                early_dcx.early_warn(
2565                    "-C instrument-coverage requires symbol mangling version `v0`, \
2566                    but `-C symbol-mangling-version=hashed` was specified",
2567                );
2568            }
2569        }
2570    }
2571
2572    if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") {
2573        // FIXME: this is only mutation of UnstableOptions here, move into
2574        // UnstableOptions::build?
2575        unstable_opts.graphviz_font = graphviz_font;
2576    }
2577
2578    if !cg.embed_bitcode {
2579        match cg.lto {
2580            LtoCli::No | LtoCli::Unspecified => {}
2581            LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => {
2582                early_dcx.early_fatal("options `-C embed-bitcode=no` and `-C lto` are incompatible")
2583            }
2584        }
2585    }
2586
2587    let unstable_options_enabled = nightly_options::is_unstable_enabled(matches);
2588    if !unstable_options_enabled && cg.force_frame_pointers == FramePointer::NonLeaf {
2589        early_dcx.early_fatal(
2590            "`-Cforce-frame-pointers=non-leaf` or `always` also requires `-Zunstable-options` \
2591                and a nightly compiler",
2592        )
2593    }
2594
2595    if !nightly_options::is_unstable_enabled(matches) && !unstable_opts.offload.is_empty() {
2596        early_dcx.early_fatal(
2597            "`-Zoffload=Enable` also requires `-Zunstable-options` \
2598                and a nightly compiler",
2599        )
2600    }
2601
2602    let target_triple = parse_target_triple(early_dcx, matches);
2603
2604    // Ensure `-Z unstable-options` is required when using the unstable `-C link-self-contained` and
2605    // `-C linker-flavor` options.
2606    if !unstable_options_enabled {
2607        if let Err(error) = cg.link_self_contained.check_unstable_variants(&target_triple) {
2608            early_dcx.early_fatal(error);
2609        }
2610
2611        if let Some(flavor) = cg.linker_flavor {
2612            if flavor.is_unstable() {
2613                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!(
2614                    "the linker flavor `{}` is unstable, the `-Z unstable-options` \
2615                        flag must also be passed to use the unstable values",
2616                    flavor.desc()
2617                ));
2618            }
2619        }
2620    }
2621
2622    // Check `-C link-self-contained` for consistency: individual components cannot be both enabled
2623    // and disabled at the same time.
2624    if let Some(erroneous_components) = cg.link_self_contained.check_consistency() {
2625        let names: String = erroneous_components
2626            .into_iter()
2627            .map(|c| c.as_str().unwrap())
2628            .intersperse(", ")
2629            .collect();
2630        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!(
2631            "some `-C link-self-contained` components were both enabled and disabled: {names}"
2632        ));
2633    }
2634
2635    let prints = print_request::collect_print_requests(early_dcx, &mut cg, &unstable_opts, matches);
2636
2637    // -Zretpoline-external-thunk also requires -Zretpoline
2638    if unstable_opts.retpoline_external_thunk {
2639        unstable_opts.retpoline = true;
2640        collected_options.target_modifiers.insert(
2641            OptionsTargetModifiers::UnstableOptions(UnstableOptionsTargetModifiers::Retpoline),
2642            "true".to_string(),
2643        );
2644    }
2645
2646    let cg = cg;
2647
2648    let opt_level = parse_opt_level(early_dcx, matches, &cg);
2649    // The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
2650    // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`)
2651    // for more details.
2652    let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No);
2653    let debuginfo = select_debuginfo(matches, &cg);
2654
2655    if !unstable_options_enabled {
2656        if let Err(error) = cg.linker_features.check_unstable_variants(&target_triple) {
2657            early_dcx.early_fatal(error);
2658        }
2659    }
2660
2661    if !unstable_options_enabled && cg.panic == Some(PanicStrategy::ImmediateAbort) {
2662        early_dcx.early_fatal(
2663            "`-Cpanic=immediate-abort` requires `-Zunstable-options` and a nightly compiler",
2664        )
2665    }
2666
2667    // Parse any `-l` flags, which link to native libraries.
2668    let libs = parse_native_libs(early_dcx, &unstable_opts, unstable_features, matches);
2669
2670    let test = matches.opt_present("test");
2671
2672    if !cg.remark.is_empty() && debuginfo == DebugInfo::None {
2673        early_dcx.early_warn("-C remark requires \"-C debuginfo=n\" to show source locations");
2674    }
2675
2676    if cg.remark.is_empty() && unstable_opts.remark_dir.is_some() {
2677        early_dcx
2678            .early_warn("using -Z remark-dir without enabling remarks using e.g. -C remark=all");
2679    }
2680
2681    let externs = parse_externs(early_dcx, matches, &unstable_opts);
2682
2683    let remap_path_prefix = parse_remap_path_prefix(early_dcx, matches, &unstable_opts);
2684    let remap_path_scope = parse_remap_path_scope(early_dcx, matches, &unstable_opts);
2685
2686    let pretty = parse_pretty(early_dcx, &unstable_opts);
2687
2688    // query-dep-graph is required if dump-dep-graph is given #106736
2689    if unstable_opts.dump_dep_graph && !unstable_opts.query_dep_graph {
2690        early_dcx.early_fatal("can't dump dependency graph without `-Z query-dep-graph`");
2691    }
2692
2693    let logical_env = parse_logical_env(early_dcx, matches);
2694
2695    let sysroot = Sysroot::new(matches.opt_str("sysroot").map(PathBuf::from));
2696
2697    let real_source_base_dir = |suffix: &str, confirm: &str| {
2698        let mut candidate = sysroot.path().join(suffix);
2699        if let Ok(metadata) = candidate.symlink_metadata() {
2700            // Replace the symlink bootstrap creates, with its destination.
2701            // We could try to use `fs::canonicalize` instead, but that might
2702            // produce unnecessarily verbose path.
2703            if metadata.file_type().is_symlink() {
2704                if let Ok(symlink_dest) = std::fs::read_link(&candidate) {
2705                    candidate = symlink_dest;
2706                }
2707            }
2708        }
2709
2710        // Only use this directory if it has a file we can expect to always find.
2711        candidate.join(confirm).is_file().then_some(candidate)
2712    };
2713
2714    let real_rust_source_base_dir =
2715        // This is the location used by the `rust-src` `rustup` component.
2716        real_source_base_dir("lib/rustlib/src/rust", "library/std/src/lib.rs");
2717
2718    let real_rustc_dev_source_base_dir =
2719        // This is the location used by the `rustc-dev` `rustup` component.
2720        real_source_base_dir("lib/rustlib/rustc-src/rust", "compiler/rustc/src/main.rs");
2721
2722    // We eagerly scan all files in each passed -L path. If the same directory is passed multiple
2723    // times, and the directory contains a lot of files, this can take a lot of time.
2724    // So we remove -L paths that were passed multiple times, and keep only the first occurrence.
2725    // We still have to keep the original order of the -L arguments.
2726    let search_paths: Vec<SearchPath> = {
2727        let mut seen_search_paths = FxHashSet::default();
2728        let search_path_matches: Vec<String> = matches.opt_strs("L");
2729        search_path_matches
2730            .iter()
2731            .filter(|p| seen_search_paths.insert(*p))
2732            .map(|path| {
2733                SearchPath::from_cli_opt(
2734                    sysroot.path(),
2735                    &target_triple,
2736                    early_dcx,
2737                    &path,
2738                    unstable_opts.unstable_options,
2739                )
2740            })
2741            .collect()
2742    };
2743
2744    // Ideally we would use `SourceMap::working_dir` instead, but we don't have access to it
2745    // so we manually create the potentially-remapped working directory
2746    let working_dir = {
2747        let working_dir = std::env::current_dir().unwrap_or_else(|e| {
2748            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}"));
2749        });
2750
2751        let file_mapping = file_path_mapping(remap_path_prefix.clone(), remap_path_scope);
2752        file_mapping.to_real_filename(&RealFileName::empty(), &working_dir)
2753    };
2754
2755    let verbose = matches.opt_present("verbose") || unstable_opts.verbose_internals;
2756
2757    Options {
2758        crate_types,
2759        optimize: opt_level,
2760        debuginfo,
2761        lint_opts,
2762        lint_cap,
2763        describe_lints,
2764        output_types,
2765        search_paths,
2766        sysroot,
2767        target_triple,
2768        test,
2769        incremental,
2770        unstable_opts,
2771        prints,
2772        cg,
2773        error_format,
2774        diagnostic_width,
2775        externs,
2776        unstable_features,
2777        crate_name,
2778        libs,
2779        debug_assertions,
2780        actually_rustdoc: false,
2781        resolve_doc_links: ResolveDocLinks::ExportedMetadata,
2782        trimmed_def_paths: false,
2783        cli_forced_codegen_units: codegen_units,
2784        cli_forced_local_thinlto_off: disable_local_thinlto,
2785        remap_path_prefix,
2786        remap_path_scope,
2787        real_rust_source_base_dir,
2788        real_rustc_dev_source_base_dir,
2789        edition,
2790        json_artifact_notifications,
2791        json_timings,
2792        json_unused_externs,
2793        json_future_incompat,
2794        pretty,
2795        working_dir,
2796        color,
2797        logical_env,
2798        verbose,
2799        target_modifiers: collected_options.target_modifiers,
2800        mitigation_coverage_map: collected_options.mitigations,
2801    }
2802}
2803
2804fn parse_pretty(early_dcx: &EarlyDiagCtxt, unstable_opts: &UnstableOptions) -> Option<PpMode> {
2805    use PpMode::*;
2806
2807    let first = match unstable_opts.unpretty.as_deref()? {
2808        "normal" => Source(PpSourceMode::Normal),
2809        "identified" => Source(PpSourceMode::Identified),
2810        "expanded" => Source(PpSourceMode::Expanded),
2811        "expanded,identified" => Source(PpSourceMode::ExpandedIdentified),
2812        "expanded,hygiene" => Source(PpSourceMode::ExpandedHygiene),
2813        "ast-tree" => AstTree,
2814        "ast-tree,expanded" => AstTreeExpanded,
2815        "hir" => Hir(PpHirMode::Normal),
2816        "hir,identified" => Hir(PpHirMode::Identified),
2817        "hir,typed" => Hir(PpHirMode::Typed),
2818        "hir-tree" => HirTree,
2819        "thir-tree" => ThirTree,
2820        "thir-flat" => ThirFlat,
2821        "mir" => Mir,
2822        "stable-mir" => StableMir,
2823        "mir-cfg" => MirCFG,
2824        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!(
2825            "argument to `unpretty` must be one of `normal`, `identified`, \
2826                            `expanded`, `expanded,identified`, `expanded,hygiene`, \
2827                            `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \
2828                            `hir,typed`, `hir-tree`, `thir-tree`, `thir-flat`, `mir`, `stable-mir`, or \
2829                            `mir-cfg`; got {name}"
2830        )),
2831    };
2832    {
    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:2832",
                        "rustc_session::config", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_session/src/config.rs"),
                        ::tracing_core::__macro_support::Option::Some(2832u32),
                        ::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:?}");
2833    Some(first)
2834}
2835
2836pub fn make_crate_type_option() -> RustcOptGroup {
2837    make_opt(
2838        OptionStability::Stable,
2839        OptionKind::Multi,
2840        "",
2841        "crate-type",
2842        "Comma separated list of types of crates
2843                                for the compiler to emit",
2844        "<bin|lib|rlib|dylib|cdylib|staticlib|proc-macro>",
2845    )
2846}
2847
2848pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> {
2849    let mut crate_types: Vec<CrateType> = Vec::new();
2850    for unparsed_crate_type in &list_list {
2851        for part in unparsed_crate_type.split(',') {
2852            let new_part = match part {
2853                "lib" => CrateType::default(),
2854                "rlib" => CrateType::Rlib,
2855                "staticlib" => CrateType::StaticLib,
2856                "dylib" => CrateType::Dylib,
2857                "cdylib" => CrateType::Cdylib,
2858                "bin" => CrateType::Executable,
2859                "proc-macro" => CrateType::ProcMacro,
2860                "sdylib" => CrateType::Sdylib,
2861                _ => {
2862                    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!(
2863                        "unknown crate type: `{part}`, expected one of: \
2864                        `lib`, `rlib`, `staticlib`, `dylib`, `cdylib`, `bin`, `proc-macro`",
2865                    ));
2866                }
2867            };
2868            if !crate_types.contains(&new_part) {
2869                crate_types.push(new_part)
2870            }
2871        }
2872    }
2873
2874    Ok(crate_types)
2875}
2876
2877pub mod nightly_options {
2878    use rustc_feature::UnstableFeatures;
2879
2880    use super::{OptionStability, RustcOptGroup};
2881    use crate::EarlyDiagCtxt;
2882
2883    pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
2884        match_is_nightly_build(matches)
2885            && matches.opt_strs("Z").iter().any(|x| *x == "unstable-options")
2886    }
2887
2888    pub fn match_is_nightly_build(matches: &getopts::Matches) -> bool {
2889        is_nightly_build(matches.opt_str("crate-name").as_deref())
2890    }
2891
2892    fn is_nightly_build(krate: Option<&str>) -> bool {
2893        UnstableFeatures::from_environment(krate).is_nightly_build()
2894    }
2895
2896    pub fn check_nightly_options(
2897        early_dcx: &EarlyDiagCtxt,
2898        matches: &getopts::Matches,
2899        flags: &[RustcOptGroup],
2900    ) {
2901        let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options");
2902        let really_allows_unstable_options = match_is_nightly_build(matches);
2903        let mut nightly_options_on_stable = 0;
2904
2905        for opt in flags.iter() {
2906            if opt.stability == OptionStability::Stable {
2907                continue;
2908            }
2909            if !matches.opt_present(opt.name) {
2910                continue;
2911            }
2912            if opt.name != "Z" && !has_z_unstable_option {
2913                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!(
2914                    "the `-Z unstable-options` flag must also be passed to enable \
2915                         the flag `{}`",
2916                    opt.name
2917                ));
2918            }
2919            if really_allows_unstable_options {
2920                continue;
2921            }
2922            match opt.stability {
2923                OptionStability::Unstable => {
2924                    nightly_options_on_stable += 1;
2925                    let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the option `{0}` is only accepted on the nightly compiler",
                opt.name))
    })format!(
2926                        "the option `{}` is only accepted on the nightly compiler",
2927                        opt.name
2928                    );
2929                    // The non-zero nightly_options_on_stable will force an early_fatal eventually.
2930                    let _ = early_dcx.early_err(msg);
2931                }
2932                OptionStability::Stable => {}
2933            }
2934        }
2935        if nightly_options_on_stable > 0 {
2936            early_dcx
2937                .early_help("consider switching to a nightly toolchain: `rustup default nightly`");
2938            early_dcx.early_note("selecting a toolchain with `+toolchain` arguments require a rustup proxy; see <https://rust-lang.github.io/rustup/concepts/index.html>");
2939            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>");
2940            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!(
2941                "{} nightly option{} were parsed",
2942                nightly_options_on_stable,
2943                if nightly_options_on_stable > 1 { "s" } else { "" }
2944            ));
2945        }
2946    }
2947}
2948
2949#[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)]
2950pub enum PpSourceMode {
2951    /// `-Zunpretty=normal`
2952    Normal,
2953    /// `-Zunpretty=expanded`
2954    Expanded,
2955    /// `-Zunpretty=identified`
2956    Identified,
2957    /// `-Zunpretty=expanded,identified`
2958    ExpandedIdentified,
2959    /// `-Zunpretty=expanded,hygiene`
2960    ExpandedHygiene,
2961}
2962
2963#[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)]
2964pub enum PpHirMode {
2965    /// `-Zunpretty=hir`
2966    Normal,
2967    /// `-Zunpretty=hir,identified`
2968    Identified,
2969    /// `-Zunpretty=hir,typed`
2970    Typed,
2971}
2972
2973#[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)]
2974/// Pretty print mode
2975pub enum PpMode {
2976    /// Options that print the source code, i.e.
2977    /// `-Zunpretty=normal` and `-Zunpretty=expanded`
2978    Source(PpSourceMode),
2979    /// `-Zunpretty=ast-tree`
2980    AstTree,
2981    /// `-Zunpretty=ast-tree,expanded`
2982    AstTreeExpanded,
2983    /// Options that print the HIR, i.e. `-Zunpretty=hir`
2984    Hir(PpHirMode),
2985    /// `-Zunpretty=hir-tree`
2986    HirTree,
2987    /// `-Zunpretty=thir-tree`
2988    ThirTree,
2989    /// `-Zunpretty=thir-flat`
2990    ThirFlat,
2991    /// `-Zunpretty=mir`
2992    Mir,
2993    /// `-Zunpretty=mir-cfg`
2994    MirCFG,
2995    /// `-Zunpretty=stable-mir`
2996    StableMir,
2997}
2998
2999impl PpMode {
3000    pub fn needs_ast_map(&self) -> bool {
3001        use PpMode::*;
3002        use PpSourceMode::*;
3003        match *self {
3004            Source(Normal | Identified) | AstTree => false,
3005
3006            Source(Expanded | ExpandedIdentified | ExpandedHygiene)
3007            | AstTreeExpanded
3008            | Hir(_)
3009            | HirTree
3010            | ThirTree
3011            | ThirFlat
3012            | Mir
3013            | MirCFG
3014            | StableMir => true,
3015        }
3016    }
3017
3018    pub fn needs_analysis(&self) -> bool {
3019        use PpMode::*;
3020        #[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)
3021    }
3022}
3023
3024#[derive(#[automatically_derived]
impl ::core::clone::Clone for WasiExecModel {
    #[inline]
    fn clone(&self) -> WasiExecModel {
        match self {
            WasiExecModel::Command => WasiExecModel::Command,
            WasiExecModel::Reactor => WasiExecModel::Reactor,
        }
    }
}Clone, #[automatically_derived]
impl ::core::hash::Hash for WasiExecModel {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash, #[automatically_derived]
impl ::core::cmp::PartialEq for WasiExecModel {
    #[inline]
    fn eq(&self, other: &WasiExecModel) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for WasiExecModel {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::fmt::Debug for WasiExecModel {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                WasiExecModel::Command => "Command",
                WasiExecModel::Reactor => "Reactor",
            })
    }
}Debug)]
3025pub enum WasiExecModel {
3026    Command,
3027    Reactor,
3028}
3029
3030/// Command-line arguments passed to the compiler have to be incorporated with
3031/// the dependency tracking system for incremental compilation. This module
3032/// provides some utilities to make this more convenient.
3033///
3034/// The values of all command-line arguments that are relevant for dependency
3035/// tracking are hashed into a single value that determines whether the
3036/// incremental compilation cache can be re-used or not. This hashing is done
3037/// via the `DepTrackingHash` trait defined below, since the standard `Hash`
3038/// implementation might not be suitable (e.g., arguments are stored in a `Vec`,
3039/// the hash of which is order dependent, but we might not want the order of
3040/// arguments to make a difference for the hash).
3041///
3042/// However, since the value provided by `Hash::hash` often *is* suitable,
3043/// especially for primitive types, there is the
3044/// `impl_dep_tracking_hash_via_hash!()` macro that allows to simply reuse the
3045/// `Hash` implementation for `DepTrackingHash`. It's important though that
3046/// we have an opt-in scheme here, so one is hopefully forced to think about
3047/// how the hash should be calculated when adding a new command-line argument.
3048pub(crate) mod dep_tracking {
3049    use std::collections::BTreeMap;
3050    use std::hash::Hash;
3051    use std::num::NonZero;
3052    use std::path::PathBuf;
3053
3054    use rustc_abi::Align;
3055    use rustc_data_structures::fx::FxIndexMap;
3056    use rustc_data_structures::stable_hasher::StableHasher;
3057    use rustc_errors::LanguageIdentifier;
3058    use rustc_feature::UnstableFeatures;
3059    use rustc_hashes::Hash64;
3060    use rustc_hir::attrs::CollapseMacroDebuginfo;
3061    use rustc_span::edition::Edition;
3062    use rustc_span::{RealFileName, RemapPathScopeComponents};
3063    use rustc_target::spec::{
3064        CodeModel, FramePointer, MergeFunctions, OnBrokenPipe, PanicStrategy, RelocModel,
3065        RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, SymbolVisibility, TargetTuple,
3066        TlsModel,
3067    };
3068
3069    use super::{
3070        AnnotateMoves, AutoDiff, BranchProtection, CFGuard, CFProtection, CoverageOptions,
3071        CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn,
3072        InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
3073        LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OptLevel, OutFileName, OutputType,
3074        OutputTypes, PatchableFunctionEntry, Polonius, ResolveDocLinks, SourceFileHashAlgorithm,
3075        SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
3076    };
3077    use crate::lint;
3078    use crate::utils::NativeLib;
3079
3080    pub(crate) trait DepTrackingHash {
3081        fn hash(
3082            &self,
3083            hasher: &mut StableHasher,
3084            error_format: ErrorOutputType,
3085            for_crate_hash: bool,
3086        );
3087    }
3088
3089    macro_rules! impl_dep_tracking_hash_via_hash {
3090        ($($t:ty),+ $(,)?) => {$(
3091            impl DepTrackingHash for $t {
3092                fn hash(&self, hasher: &mut StableHasher, _: ErrorOutputType, _for_crate_hash: bool) {
3093                    Hash::hash(self, hasher);
3094                }
3095            }
3096        )+};
3097    }
3098
3099    impl<T: DepTrackingHash> DepTrackingHash for Option<T> {
3100        fn hash(
3101            &self,
3102            hasher: &mut StableHasher,
3103            error_format: ErrorOutputType,
3104            for_crate_hash: bool,
3105        ) {
3106            match self {
3107                Some(x) => {
3108                    Hash::hash(&1, hasher);
3109                    DepTrackingHash::hash(x, hasher, error_format, for_crate_hash);
3110                }
3111                None => Hash::hash(&0, hasher),
3112            }
3113        }
3114    }
3115
3116    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!(
3117        (),
3118        AnnotateMoves,
3119        AutoDiff,
3120        Offload,
3121        bool,
3122        usize,
3123        NonZero<usize>,
3124        u64,
3125        Hash64,
3126        String,
3127        PathBuf,
3128        lint::Level,
3129        WasiExecModel,
3130        u32,
3131        FramePointer,
3132        RelocModel,
3133        CodeModel,
3134        TlsModel,
3135        InstrumentCoverage,
3136        CoverageOptions,
3137        InstrumentXRay,
3138        CrateType,
3139        MergeFunctions,
3140        OnBrokenPipe,
3141        PanicStrategy,
3142        RelroLevel,
3143        OptLevel,
3144        LtoCli,
3145        DebugInfo,
3146        DebugInfoCompression,
3147        MirStripDebugInfo,
3148        CollapseMacroDebuginfo,
3149        UnstableFeatures,
3150        NativeLib,
3151        SanitizerSet,
3152        CFGuard,
3153        CFProtection,
3154        TargetTuple,
3155        Edition,
3156        LinkerPluginLto,
3157        ResolveDocLinks,
3158        SplitDebuginfo,
3159        SplitDwarfKind,
3160        StackProtector,
3161        SwitchWithOptPath,
3162        SymbolManglingVersion,
3163        SymbolVisibility,
3164        RemapPathScopeComponents,
3165        SourceFileHashAlgorithm,
3166        OutFileName,
3167        OutputType,
3168        RealFileName,
3169        LocationDetail,
3170        FmtDebug,
3171        BranchProtection,
3172        LanguageIdentifier,
3173        NextSolverConfig,
3174        PatchableFunctionEntry,
3175        Polonius,
3176        InliningThreshold,
3177        FunctionReturn,
3178        Align,
3179    );
3180
3181    impl<T1, T2> DepTrackingHash for (T1, T2)
3182    where
3183        T1: DepTrackingHash,
3184        T2: DepTrackingHash,
3185    {
3186        fn hash(
3187            &self,
3188            hasher: &mut StableHasher,
3189            error_format: ErrorOutputType,
3190            for_crate_hash: bool,
3191        ) {
3192            Hash::hash(&0, hasher);
3193            DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash);
3194            Hash::hash(&1, hasher);
3195            DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash);
3196        }
3197    }
3198
3199    impl<T1, T2, T3> DepTrackingHash for (T1, T2, T3)
3200    where
3201        T1: DepTrackingHash,
3202        T2: DepTrackingHash,
3203        T3: DepTrackingHash,
3204    {
3205        fn hash(
3206            &self,
3207            hasher: &mut StableHasher,
3208            error_format: ErrorOutputType,
3209            for_crate_hash: bool,
3210        ) {
3211            Hash::hash(&0, hasher);
3212            DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash);
3213            Hash::hash(&1, hasher);
3214            DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash);
3215            Hash::hash(&2, hasher);
3216            DepTrackingHash::hash(&self.2, hasher, error_format, for_crate_hash);
3217        }
3218    }
3219
3220    impl<T: DepTrackingHash> DepTrackingHash for Vec<T> {
3221        fn hash(
3222            &self,
3223            hasher: &mut StableHasher,
3224            error_format: ErrorOutputType,
3225            for_crate_hash: bool,
3226        ) {
3227            Hash::hash(&self.len(), hasher);
3228            for (index, elem) in self.iter().enumerate() {
3229                Hash::hash(&index, hasher);
3230                DepTrackingHash::hash(elem, hasher, error_format, for_crate_hash);
3231            }
3232        }
3233    }
3234
3235    impl<T: DepTrackingHash, V: DepTrackingHash> DepTrackingHash for FxIndexMap<T, V> {
3236        fn hash(
3237            &self,
3238            hasher: &mut StableHasher,
3239            error_format: ErrorOutputType,
3240            for_crate_hash: bool,
3241        ) {
3242            Hash::hash(&self.len(), hasher);
3243            for (key, value) in self.iter() {
3244                DepTrackingHash::hash(key, hasher, error_format, for_crate_hash);
3245                DepTrackingHash::hash(value, hasher, error_format, for_crate_hash);
3246            }
3247        }
3248    }
3249
3250    impl DepTrackingHash for OutputTypes {
3251        fn hash(
3252            &self,
3253            hasher: &mut StableHasher,
3254            error_format: ErrorOutputType,
3255            for_crate_hash: bool,
3256        ) {
3257            Hash::hash(&self.0.len(), hasher);
3258            for (key, val) in &self.0 {
3259                DepTrackingHash::hash(key, hasher, error_format, for_crate_hash);
3260                if !for_crate_hash {
3261                    DepTrackingHash::hash(val, hasher, error_format, for_crate_hash);
3262                }
3263            }
3264        }
3265    }
3266
3267    // This is a stable hash because BTreeMap is a sorted container
3268    pub(crate) fn stable_hash(
3269        sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>,
3270        hasher: &mut StableHasher,
3271        error_format: ErrorOutputType,
3272        for_crate_hash: bool,
3273    ) {
3274        for (key, sub_hash) in sub_hashes {
3275            // Using Hash::hash() instead of DepTrackingHash::hash() is fine for
3276            // the keys, as they are just plain strings
3277            Hash::hash(&key.len(), hasher);
3278            Hash::hash(key, hasher);
3279            sub_hash.hash(hasher, error_format, for_crate_hash);
3280        }
3281    }
3282}
3283
3284/// How to run proc-macro code when building this crate
3285#[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)]
3286pub enum ProcMacroExecutionStrategy {
3287    /// Run the proc-macro code on the same thread as the server.
3288    SameThread,
3289
3290    /// Run the proc-macro code on a different thread.
3291    CrossThread,
3292}
3293
3294/// Which format to use for `-Z dump-mono-stats`
3295#[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)]
3296pub enum DumpMonoStatsFormat {
3297    /// Pretty-print a markdown table
3298    Markdown,
3299    /// Emit structured JSON
3300    Json,
3301}
3302
3303impl DumpMonoStatsFormat {
3304    pub fn extension(self) -> &'static str {
3305        match self {
3306            Self::Markdown => "md",
3307            Self::Json => "json",
3308        }
3309    }
3310}
3311
3312/// `-Z patchable-function-entry` representation - how many nops to put before and after function
3313/// entry.
3314#[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)]
3315pub struct PatchableFunctionEntry {
3316    /// Nops before the entry
3317    prefix: u8,
3318    /// Nops after the entry
3319    entry: u8,
3320}
3321
3322impl PatchableFunctionEntry {
3323    pub fn from_total_and_prefix_nops(
3324        total_nops: u8,
3325        prefix_nops: u8,
3326    ) -> Option<PatchableFunctionEntry> {
3327        if total_nops < prefix_nops {
3328            None
3329        } else {
3330            Some(Self { prefix: prefix_nops, entry: total_nops - prefix_nops })
3331        }
3332    }
3333    pub fn prefix(&self) -> u8 {
3334        self.prefix
3335    }
3336    pub fn entry(&self) -> u8 {
3337        self.entry
3338    }
3339}
3340
3341/// `-Zpolonius` values, enabling the borrow checker polonius analysis, and which version: legacy,
3342/// or future prototype.
3343#[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)]
3344pub enum Polonius {
3345    /// The default value: disabled.
3346    #[default]
3347    Off,
3348
3349    /// Legacy version, using datalog and the `polonius-engine` crate. Historical value for `-Zpolonius`.
3350    Legacy,
3351
3352    /// In-tree prototype, extending the NLL infrastructure.
3353    Next,
3354}
3355
3356impl Polonius {
3357    /// Returns whether the legacy version of polonius is enabled
3358    pub fn is_legacy_enabled(&self) -> bool {
3359        #[allow(non_exhaustive_omitted_patterns)] match self {
    Polonius::Legacy => true,
    _ => false,
}matches!(self, Polonius::Legacy)
3360    }
3361
3362    /// Returns whether the "next" version of polonius is enabled
3363    pub fn is_next_enabled(&self) -> bool {
3364        #[allow(non_exhaustive_omitted_patterns)] match self {
    Polonius::Next => true,
    _ => false,
}matches!(self, Polonius::Next)
3365    }
3366}
3367
3368#[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)]
3369pub enum InliningThreshold {
3370    Always,
3371    Sometimes(usize),
3372    Never,
3373}
3374
3375impl Default for InliningThreshold {
3376    fn default() -> Self {
3377        Self::Sometimes(100)
3378    }
3379}
3380
3381/// The different settings that the `-Zfunction-return` flag can have.
3382#[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)]
3383pub enum FunctionReturn {
3384    /// Keep the function return unmodified.
3385    #[default]
3386    Keep,
3387
3388    /// Replace returns with jumps to thunk, without emitting the thunk.
3389    ThunkExtern,
3390}
3391
3392/// Whether extra span comments are included when dumping MIR, via the `-Z mir-include-spans` flag.
3393/// By default, only enabled in the NLL MIR dumps, and disabled in all other passes.
3394#[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)]
3395pub enum MirIncludeSpans {
3396    Off,
3397    On,
3398    /// Default: include extra comments in NLL MIR dumps only. Can be ignored and considered as
3399    /// `Off` in all other cases.
3400    #[default]
3401    Nll,
3402}
3403
3404impl MirIncludeSpans {
3405    /// Unless opting into extra comments for all passes, they can be considered disabled.
3406    /// The cases where a distinction between on/off and a per-pass value can exist will be handled
3407    /// in the passes themselves: i.e. the `Nll` value is considered off for all intents and
3408    /// purposes, except for the NLL MIR dump pass.
3409    pub fn is_enabled(self) -> bool {
3410        self == MirIncludeSpans::On
3411    }
3412}