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