Skip to main content

rustc_session/
config.rs

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