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