Skip to main content

rustc_session/
config.rs

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