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