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