use std::any::Any;
use std::ffi::{OsStr, OsString};
use std::io::{self, BufWriter, Write};
use std::path::{Path, PathBuf};
use std::sync::{Arc, LazyLock, OnceLock};
use std::{env, fs, iter};

use rustc_ast::{self as ast, CRATE_NODE_ID};
use rustc_attr_parsing::{AttributeParser, ShouldEmit};
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::{CompiledModules, CrateInfo};
use rustc_data_structures::indexmap::IndexMap;
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{
    AppendOnlyIndexVec, DynSend, DynSync, FreezeLock, WorkerLocal, par_fns,
};
use rustc_data_structures::thousands;
use rustc_errors::timings::TimingSection;
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level};
use rustc_expand::base::{ExtCtxt, LintStoreExpand};
use rustc_feature::Features;
use rustc_fs_util::try_canonicalize;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap};
use rustc_hir::definitions::Definitions;
use rustc_hir::limit::Limit;
use rustc_hir::{Attribute, Target, find_attr};
use rustc_incremental::setup_dep_graph;
use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store};
use rustc_metadata::EncodedMetadata;
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
use rustc_middle::ty::{self, RegisteredTools, TyCtxt};
use rustc_middle::util::Providers;
use rustc_parse::lexer::StripTokens;
use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
use rustc_passes::{abi_test, input_stats, layout_test};
use rustc_resolve::{Resolver, ResolverOutputs};
use rustc_session::Session;
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked;
use rustc_session::errors::feature_err;
use rustc_session::output::{filename_for_input, invalid_output_for_target};
use rustc_session::search_paths::PathKind;
use rustc_span::{
    DUMMY_SP, ErrorGuaranteed, ExpnKind, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym,
};
use rustc_trait_selection::{solve, traits};
use tracing::{info, instrument};

use crate::interface::Compiler;
use crate::{diagnostics, limits, util};

pub fn parse<'a>(sess: &'a Session) -> ast::Crate {
    let mut krate = sess
        .time("parse_crate", || {
            let mut parser = unwrap_or_emit_fatal(match &sess.io.input {
                Input::File(file) => new_parser_from_file(
                    &sess.psess,
                    file,
                    StripTokens::ShebangAndFrontmatter,
                    None,
                ),
                Input::Str { input, name } => new_parser_from_source_str(
                    &sess.psess,
                    name.clone(),
                    input.clone(),
                    StripTokens::ShebangAndFrontmatter,
                ),
            });
            parser.parse_crate_mod()
        })
        .unwrap_or_else(|parse_error| {
            let guar: ErrorGuaranteed = parse_error.emit();
            guar.raise_fatal();
        });

    rustc_builtin_macros::cmdline_attrs::inject(
        &mut krate,
        &sess.psess,
        &sess.opts.unstable_opts.crate_attr,
    );

    krate
}

fn pre_expansion_lint<'a>(
    sess: &Session,
    features: &Features,
    lint_store: &LintStore,
    registered_tools: &RegisteredTools,
    check_node: EarlyCheckNode<'a>,
    node_name: Symbol,
) {
    sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run(
        || {
            rustc_lint::check_ast_node(
                sess,
                features,
                true,
                lint_store,
                registered_tools,
                None,
                rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
                check_node,
            );
        },
    );
}

// Cannot implement directly for `LintStore` due to trait coherence.
struct LintStoreExpandImpl<'a>(&'a LintStore);

impl LintStoreExpand for LintStoreExpandImpl<'_> {
    fn pre_expansion_lint(
        &self,
        sess: &Session,
        features: &Features,
        registered_tools: &RegisteredTools,
        node_id: ast::NodeId,
        attrs: &[ast::Attribute],
        items: &[Box<ast::Item>],
        name: Symbol,
    ) {
        let check_node = EarlyCheckNode::LoadedMod(node_id, attrs, items);
        pre_expansion_lint(sess, features, self.0, registered_tools, check_node, name);
    }
}

/// Runs the "early phases" of the compiler: initial `cfg` processing,
/// syntax expansion, secondary `cfg` expansion, synthesis of a test
/// harness if one is to be provided, injection of a dependency on the
/// standard library and prelude, and name resolution.
#[instrument(level = "trace", skip(krate, resolver))]
fn configure_and_expand(
    mut krate: ast::Crate,
    pre_configured_attrs: &[ast::Attribute],
    resolver: &mut Resolver<'_, '_>,
) -> ast::Crate {
    let tcx = resolver.tcx();
    let sess = tcx.sess;
    let features = tcx.features();
    let lint_store = unerased_lint_store(sess);
    let crate_name = tcx.crate_name(LOCAL_CRATE);
    pre_expansion_lint(
        sess,
        features,
        lint_store,
        tcx.registered_tools(()),
        EarlyCheckNode::CrateRoot(&krate, pre_configured_attrs),
        crate_name,
    );
    rustc_builtin_macros::register_builtin_macros(resolver);

    let num_standard_library_imports = sess.time("crate_injection", || {
        rustc_builtin_macros::standard_library_imports::inject(
            &mut krate,
            pre_configured_attrs,
            resolver,
            sess,
            features,
        )
    });

    // Expand all macros
    krate = sess.time("macro_expand_crate", || {
        // Windows dlls do not have rpaths, so they don't know how to find their
        // dependencies. It's up to us to tell the system where to find all the
        // dependent dlls. Note that this uses cfg!(windows) as opposed to
        // targ_cfg because syntax extensions are always loaded for the host
        // compiler, not for the target.
        //
        // This is somewhat of an inherently racy operation, however, as
        // multiple threads calling this function could possibly continue
        // extending PATH far beyond what it should. To solve this for now we
        // just don't add any new elements to PATH which are already there
        // within PATH. This is basically a targeted fix at #17360 for rustdoc
        // which runs rustc in parallel but has been seen (#33844) to cause
        // problems with PATH becoming too long.
        let mut old_path = OsString::new();
        if cfg!(windows) {
            old_path = env::var_os("PATH").unwrap_or(old_path);
            let mut new_path = Vec::from_iter(
                sess.host_filesearch().search_paths(PathKind::Native).map(|p| p.dir.clone()),
            );
            for path in env::split_paths(&old_path) {
                if !new_path.contains(&path) {
                    new_path.push(path);
                }
            }
            unsafe {
                env::set_var(
                    "PATH",
                    env::join_paths(
                        new_path.iter().filter(|p| env::join_paths(iter::once(p)).is_ok()),
                    )
                    .unwrap(),
                );
            }
        }

        // Create the config for macro expansion
        let recursion_limit = get_recursion_limit(pre_configured_attrs, sess);
        let cfg = rustc_expand::expand::ExpansionConfig {
            crate_name,
            features,
            recursion_limit,
            trace_mac: sess.opts.unstable_opts.trace_macros,
            should_test: sess.is_test_crate(),
            span_debug: sess.opts.unstable_opts.span_debug,
            proc_macro_backtrace: sess.opts.unstable_opts.proc_macro_backtrace,
        };

        let lint_store = LintStoreExpandImpl(lint_store);
        let mut ecx = ExtCtxt::new(sess, cfg, resolver, Some(&lint_store));
        ecx.num_standard_library_imports = num_standard_library_imports;
        // Expand macros now!
        let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate));

        if ecx.nb_macro_errors > 0 {
            sess.dcx().abort_if_errors();
        }

        // The rest is error reporting and stats

        sess.psess.buffered_lints.with_lock(|buffered_lints: &mut Vec<BufferedEarlyLint>| {
            buffered_lints.append(&mut ecx.buffered_early_lint);
        });

        sess.time("check_unused_macros", || {
            ecx.check_unused_macros();
        });

        // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed
        // with a large AST
        if ecx.reduced_recursion_limit.is_some() {
            sess.dcx().abort_if_errors();
            unreachable!();
        }

        if cfg!(windows) {
            unsafe {
                env::set_var("PATH", &old_path);
            }
        }

        if ecx.sess.opts.unstable_opts.macro_stats {
            print_macro_stats(&ecx);
        }

        krate
    });

    sess.time("maybe_building_test_harness", || {
        rustc_builtin_macros::test_harness::inject(&mut krate, sess, features, resolver)
    });

    let has_proc_macro_decls = sess.time("AST_validation", || {
        rustc_ast_passes::ast_validation::check_crate(
            sess,
            features,
            &krate,
            tcx.is_sdylib_interface_build(),
            resolver.lint_buffer(),
        )
    });

    let crate_types = tcx.crate_types();
    let is_executable_crate = crate_types.contains(&CrateType::Executable);
    let is_proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);

    if crate_types.len() > 1 {
        if is_executable_crate {
            sess.dcx().emit_err(diagnostics::MixedBinCrate);
        }
        if is_proc_macro_crate {
            sess.dcx().emit_err(diagnostics::MixedProcMacroCrate);
        }
    }
    if crate_types.contains(&CrateType::Sdylib) && !tcx.features().export_stable() {
        feature_err(sess, sym::export_stable, DUMMY_SP, "`sdylib` crate type is unstable").emit();
    }

    if is_proc_macro_crate && !sess.panic_strategy().unwinds() {
        sess.dcx().emit_warn(diagnostics::ProcMacroCratePanicAbort);
    }

    sess.time("maybe_create_a_macro_crate", || {
        let is_test_crate = sess.is_test_crate();
        rustc_builtin_macros::proc_macro_harness::inject(
            &mut krate,
            sess,
            features,
            resolver,
            is_proc_macro_crate,
            has_proc_macro_decls,
            is_test_crate,
            sess.dcx(),
        )
    });

    // Done with macro expansion!

    resolver.resolve_crate(&krate);

    CStore::from_tcx(tcx).report_session_incompatibilities(tcx, &krate);
    krate
}

fn print_macro_stats(ecx: &ExtCtxt<'_>) {
    use std::fmt::Write;

    let crate_name = ecx.ecfg.crate_name.as_str();
    let crate_name = if crate_name == "build_script_build" {
        // This is a build script. Get the package name from the environment.
        let pkg_name =
            std::env::var("CARGO_PKG_NAME").unwrap_or_else(|_| "<unknown crate>".to_string());
        format!("{pkg_name} build script")
    } else {
        crate_name.to_string()
    };

    // No instability because we immediately sort the produced vector.
    #[allow(rustc::potential_query_instability)]
    let mut macro_stats: Vec<_> = ecx
        .macro_stats
        .iter()
        .map(|((name, kind), stat)| {
            // This gives the desired sort order: sort by bytes, then lines, etc.
            (stat.bytes, stat.lines, stat.uses, name, *kind)
        })
        .collect();
    macro_stats.sort_unstable();
    macro_stats.reverse(); // bigger items first

    let prefix = "macro-stats";
    let name_w = 32;
    let uses_w = 7;
    let lines_w = 11;
    let avg_lines_w = 11;
    let bytes_w = 11;
    let avg_bytes_w = 11;
    let banner_w = name_w + uses_w + lines_w + avg_lines_w + bytes_w + avg_bytes_w;

    // We write all the text into a string and print it with a single
    // `eprint!`. This is an attempt to minimize interleaved text if multiple
    // rustc processes are printing macro-stats at the same time (e.g. with
    // `RUSTFLAGS='-Zmacro-stats' cargo build`). It still doesn't guarantee
    // non-interleaving, though.
    let mut s = String::new();
    _ = writeln!(s, "{prefix} {}", "=".repeat(banner_w));
    _ = writeln!(s, "{prefix} MACRO EXPANSION STATS: {}", crate_name);
    _ = writeln!(
        s,
        "{prefix} {:<name_w$}{:>uses_w$}{:>lines_w$}{:>avg_lines_w$}{:>bytes_w$}{:>avg_bytes_w$}",
        "Macro Name", "Uses", "Lines", "Avg Lines", "Bytes", "Avg Bytes",
    );
    _ = writeln!(s, "{prefix} {}", "-".repeat(banner_w));
    // It's helpful to print something when there are no entries, otherwise it
    // might look like something went wrong.
    if macro_stats.is_empty() {
        _ = writeln!(s, "{prefix} (none)");
    }
    for (bytes, lines, uses, name, kind) in macro_stats {
        let mut name = ExpnKind::Macro(kind, *name).descr();
        let uses_with_underscores = thousands::usize_with_underscores(uses);
        let avg_lines = lines as f64 / uses as f64;
        let avg_bytes = bytes as f64 / uses as f64;

        // Ensure the "Macro Name" and "Uses" columns are as compact as possible.
        let mut uses_w = uses_w;
        if name.len() + uses_with_underscores.len() >= name_w + uses_w {
            // The name would abut or overlap the uses value. Print the name
            // on a line by itself, then set the name to empty and print things
            // normally, to show the stats on the next line.
            _ = writeln!(s, "{prefix} {:<name_w$}", name);
            name = String::new();
        } else if name.len() >= name_w {
            // The name won't abut or overlap with the uses value, but it does
            // overlap with the empty part of the uses column. Shrink the width
            // of the uses column to account for the excess name length.
            uses_w -= name.len() - name_w;
        };

        _ = writeln!(
            s,
            "{prefix} {:<name_w$}{:>uses_w$}{:>lines_w$}{:>avg_lines_w$}{:>bytes_w$}{:>avg_bytes_w$}",
            name,
            uses_with_underscores,
            thousands::usize_with_underscores(lines),
            thousands::f64p1_with_underscores(avg_lines),
            thousands::usize_with_underscores(bytes),
            thousands::f64p1_with_underscores(avg_bytes),
        );
    }
    _ = writeln!(s, "{prefix} {}", "=".repeat(banner_w));
    eprint!("{s}");
}

fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) {
    let sess = tcx.sess;
    let (resolver, krate) = tcx.resolver_for_lowering();
    let resolver = &*resolver.borrow();
    let krate = &*krate.borrow();
    let mut lint_buffer = resolver.lint_buffer.steal();

    if sess.opts.unstable_opts.input_stats {
        input_stats::print_ast_stats(tcx, krate);
    }

    // Needs to go *after* expansion to be able to check the results of macro expansion.
    sess.time("complete_gated_feature_checking", || {
        rustc_ast_passes::feature_gate::check_crate(krate, sess, tcx.features());
    });

    // Add all buffered lints from the `ParseSess` to the `Session`.
    sess.psess.buffered_lints.with_lock(|buffered_lints| {
        info!("{} parse sess buffered_lints", buffered_lints.len());
        for early_lint in buffered_lints.drain(..) {
            lint_buffer.add_early_lint(early_lint);
        }
    });

    // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing.
    sess.psess.bad_unicode_identifiers.with_lock(|identifiers| {
        for (ident, mut spans) in identifiers.drain(..) {
            spans.sort();
            if ident == sym::ferris {
                enum FerrisFix {
                    SnakeCase,
                    ScreamingSnakeCase,
                    PascalCase,
                }

                impl FerrisFix {
                    const fn as_str(self) -> &'static str {
                        match self {
                            FerrisFix::SnakeCase => "ferris",
                            FerrisFix::ScreamingSnakeCase => "FERRIS",
                            FerrisFix::PascalCase => "Ferris",
                        }
                    }
                }

                let first_span = spans[0];
                let prev_source = sess.psess.source_map().span_to_prev_source(first_span);
                let ferris_fix = prev_source
                    .map_or(FerrisFix::SnakeCase, |source| {
                        let mut source_before_ferris = source.split_whitespace().rev();
                        match source_before_ferris.next() {
                            Some("struct" | "trait" | "mod" | "union" | "type" | "enum") => {
                                FerrisFix::PascalCase
                            }
                            Some("const" | "static") => FerrisFix::ScreamingSnakeCase,
                            Some("mut") if source_before_ferris.next() == Some("static") => {
                                FerrisFix::ScreamingSnakeCase
                            }
                            _ => FerrisFix::SnakeCase,
                        }
                    })
                    .as_str();

                sess.dcx().emit_err(diagnostics::FerrisIdentifier {
                    spans,
                    first_span,
                    ferris_fix,
                });
            } else {
                sess.dcx().emit_err(diagnostics::EmojiIdentifier { spans, ident });
            }
        }
    });

    let lint_store = unerased_lint_store(tcx.sess);
    rustc_lint::check_ast_node(
        sess,
        tcx.features(),
        false,
        lint_store,
        tcx.registered_tools(()),
        Some(lint_buffer),
        rustc_lint::BuiltinCombinedEarlyLintPass::new(),
        EarlyCheckNode::CrateRoot(&*krate, &*krate.attrs),
    )
}

fn env_var_os<'tcx>(tcx: TyCtxt<'tcx>, key: &'tcx OsStr) -> Option<&'tcx OsStr> {
    let value = env::var_os(key);

    let value_tcx = value.as_ref().map(|value| {
        let encoded_bytes = tcx.arena.alloc_slice(value.as_encoded_bytes());
        debug_assert_eq!(value.as_encoded_bytes(), encoded_bytes);
        // SAFETY: The bytes came from `as_encoded_bytes`, and we assume that
        // `alloc_slice` is implemented correctly, and passes the same bytes
        // back (debug asserted above).
        unsafe { OsStr::from_encoded_bytes_unchecked(encoded_bytes) }
    });

    // Also add the variable to Cargo's dependency tracking
    //
    // NOTE: This only works for passes run before `write_dep_info`. See that
    // for extension points for configuring environment variables to be
    // properly change-tracked.
    tcx.sess.env_depinfo.borrow_mut().insert((
        Symbol::intern(&key.to_string_lossy()),
        value.as_ref().and_then(|value| value.to_str()).map(|value| Symbol::intern(value)),
    ));

    value_tcx
}

// Returns all the paths that correspond to generated files.
fn generated_output_paths(
    tcx: TyCtxt<'_>,
    outputs: &OutputFilenames,
    exact_name: bool,
    crate_name: Symbol,
) -> Vec<PathBuf> {
    let sess = tcx.sess;
    let mut out_filenames = Vec::new();
    for output_type in sess.opts.output_types.keys() {
        let out_filename = outputs.path(*output_type);
        let file = out_filename.as_path().to_path_buf();
        match *output_type {
            // If the filename has been overridden using `-o`, it will not be modified
            // by appending `.rlib`, `.exe`, etc., so we can skip this transformation.
            OutputType::Exe if !exact_name => {
                for crate_type in tcx.crate_types().iter() {
                    let p = filename_for_input(sess, *crate_type, crate_name, outputs);
                    out_filenames.push(p.as_path().to_path_buf());
                }
            }
            OutputType::DepInfo if sess.opts.unstable_opts.dep_info_omit_d_target => {
                // Don't add the dep-info output when omitting it from dep-info targets
            }
            OutputType::DepInfo if out_filename.is_stdout() => {
                // Don't add the dep-info output when it goes to stdout
            }
            _ => {
                out_filenames.push(file);
            }
        }
    }
    out_filenames
}

fn output_contains_path(output_paths: &[PathBuf], input_path: &Path) -> bool {
    let input_path = try_canonicalize(input_path).ok();
    if input_path.is_none() {
        return false;
    }
    output_paths.iter().any(|output_path| try_canonicalize(output_path).ok() == input_path)
}

fn output_conflicts_with_dir(output_paths: &[PathBuf]) -> Option<&PathBuf> {
    output_paths.iter().find(|output_path| output_path.is_dir())
}

fn escape_dep_filename(filename: &str) -> String {
    // Apparently clang and gcc *only* escape spaces:
    // https://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
    filename.replace(' ', "\\ ")
}

// Makefile comments only need escaping newlines and `\`.
// The result can be unescaped by anything that can unescape `escape_default` and friends.
fn escape_dep_env(symbol: Symbol) -> String {
    let s = symbol.as_str();
    let mut escaped = String::with_capacity(s.len());
    for c in s.chars() {
        match c {
            '\n' => escaped.push_str(r"\n"),
            '\r' => escaped.push_str(r"\r"),
            '\\' => escaped.push_str(r"\\"),
            _ => escaped.push(c),
        }
    }
    escaped
}

fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[PathBuf]) {
    // Write out dependency rules to the dep-info file if requested
    let sess = tcx.sess;
    if !sess.opts.output_types.contains_key(&OutputType::DepInfo) {
        return;
    }
    let deps_output = outputs.path(OutputType::DepInfo);
    let deps_filename = deps_output.as_path();

    let result = try {
        // Build a list of files used to compile the output and
        // write Makefile-compatible dependency rules
        let mut files: IndexMap<String, (u64, Option<SourceFileHash>)> = sess
            .source_map()
            .files()
            .iter()
            .filter(|fmap| fmap.is_real_file())
            .filter(|fmap| !fmap.is_imported())
            .map(|fmap| {
                (
                    escape_dep_filename(&fmap.name.prefer_local_unconditionally().to_string()),
                    (
                        // This needs to be unnormalized,
                        // as external tools wouldn't know how rustc normalizes them
                        fmap.unnormalized_source_len as u64,
                        fmap.checksum_hash,
                    ),
                )
            })
            .collect();

        let checksum_hash_algo = sess.opts.unstable_opts.checksum_hash_algorithm;

        // Account for explicitly marked-to-track files
        // (e.g. accessed in proc macros).
        let file_depinfo = sess.file_depinfo.borrow();

        let normalize_path = |path: PathBuf| escape_dep_filename(&path.to_string_lossy());

        // The entries will be used to declare dependencies between files in a
        // Makefile-like output, so the iteration order does not matter.
        fn hash_iter_files<P: AsRef<Path>>(
            it: impl Iterator<Item = P>,
            checksum_hash_algo: Option<SourceFileHashAlgorithm>,
        ) -> impl Iterator<Item = (P, (u64, Option<SourceFileHash>))> {
            it.map(move |path| {
                match checksum_hash_algo.and_then(|algo| {
                    fs::File::open(path.as_ref())
                        .and_then(|mut file| {
                            SourceFileHash::new(algo, &mut file).map(|h| (file, h))
                        })
                        .and_then(|(file, h)| file.metadata().map(|m| (m.len(), h)))
                        .map_err(|e| {
                            tracing::error!(
                                "failed to compute checksum, omitting it from dep-info {} {e}",
                                path.as_ref().display()
                            )
                        })
                        .ok()
                }) {
                    Some((file_len, checksum)) => (path, (file_len, Some(checksum))),
                    None => (path, (0, None)),
                }
            })
        }

        let extra_tracked_files = hash_iter_files(
            file_depinfo.iter().map(|path_sym| normalize_path(PathBuf::from(path_sym.as_str()))),
            checksum_hash_algo,
        );
        files.extend(extra_tracked_files);

        // We also need to track used PGO profile files
        if let Some(ref profile_instr) = sess.opts.cg.profile_use {
            files.extend(hash_iter_files(
                iter::once(normalize_path(profile_instr.as_path().to_path_buf())),
                checksum_hash_algo,
            ));
        }
        if let Some(ref profile_sample) = sess.opts.unstable_opts.profile_sample_use {
            files.extend(hash_iter_files(
                iter::once(normalize_path(profile_sample.as_path().to_path_buf())),
                checksum_hash_algo,
            ));
        }

        // Debugger visualizer files
        for debugger_visualizer in tcx.debugger_visualizers(LOCAL_CRATE) {
            files.extend(hash_iter_files(
                iter::once(normalize_path(debugger_visualizer.path.clone().unwrap())),
                checksum_hash_algo,
            ));
        }

        if sess.binary_dep_depinfo() {
            if let Some(ref backend) = sess.opts.unstable_opts.codegen_backend {
                if backend.contains('.') {
                    // If the backend name contain a `.`, it is the path to an external dynamic
                    // library. If not, it is not a path.
                    files.extend(hash_iter_files(
                        iter::once(backend.to_string()),
                        checksum_hash_algo,
                    ));
                }
            }

            for &cnum in tcx.crates(()) {
                let source = tcx.used_crate_source(cnum);
                if let Some(path) = &source.dylib {
                    files.extend(hash_iter_files(
                        iter::once(escape_dep_filename(&path.display().to_string())),
                        checksum_hash_algo,
                    ));
                }
                if let Some(path) = &source.rlib {
                    files.extend(hash_iter_files(
                        iter::once(escape_dep_filename(&path.display().to_string())),
                        checksum_hash_algo,
                    ));
                }
                if let Some(path) = &source.rmeta {
                    files.extend(hash_iter_files(
                        iter::once(escape_dep_filename(&path.display().to_string())),
                        checksum_hash_algo,
                    ));
                }
            }
        }

        let write_deps_to_file = |file: &mut dyn Write| -> io::Result<()> {
            for path in out_filenames {
                writeln!(
                    file,
                    "{}: {}\n",
                    path.display(),
                    files.keys().map(String::as_str).intersperse(" ").collect::<String>()
                )?;
            }

            // Emit a fake target for each input file to the compilation. This
            // prevents `make` from spitting out an error if a file is later
            // deleted. For more info see #28735
            for path in files.keys() {
                writeln!(file, "{path}:")?;
            }

            // Emit special comments with information about accessed environment variables.
            let env_depinfo = sess.env_depinfo.borrow();
            if !env_depinfo.is_empty() {
                // We will soon sort, so the initial order does not matter.
                #[allow(rustc::potential_query_instability)]
                let mut envs: Vec<_> = env_depinfo
                    .iter()
                    .map(|(k, v)| (escape_dep_env(*k), v.map(escape_dep_env)))
                    .collect();
                envs.sort_unstable();
                writeln!(file)?;
                for (k, v) in envs {
                    write!(file, "# env-dep:{k}")?;
                    if let Some(v) = v {
                        write!(file, "={v}")?;
                    }
                    writeln!(file)?;
                }
            }

            // If caller requested this information, add special comments about source file checksums.
            // These are not necessarily the same checksums as was used in the debug files.
            if sess.opts.unstable_opts.checksum_hash_algorithm().is_some() {
                files
                    .iter()
                    .filter_map(|(path, (file_len, hash_algo))| {
                        hash_algo.map(|hash_algo| (path, file_len, hash_algo))
                    })
                    .try_for_each(|(path, file_len, checksum_hash)| {
                        writeln!(file, "# checksum:{checksum_hash} file_len:{file_len} {path}")
                    })?;
            }

            Ok(())
        };

        match deps_output {
            OutFileName::Stdout => {
                let mut file = BufWriter::new(io::stdout());
                write_deps_to_file(&mut file)?;
            }
            OutFileName::Real(ref path) => {
                let mut file = fs::File::create_buffered(path)?;
                write_deps_to_file(&mut file)?;
            }
        }
    };

    match result {
        Ok(_) => {
            if sess.opts.json_artifact_notifications {
                sess.dcx().emit_artifact_notification(deps_filename, "dep-info");
            }
        }
        Err(error) => {
            sess.dcx()
                .emit_fatal(diagnostics::ErrorWritingDependencies { path: deps_filename, error });
        }
    }
}

fn resolver_for_lowering_raw<'tcx>(
    tcx: TyCtxt<'tcx>,
    (): (),
) -> (
    &'tcx Steal<ty::ResolverAstLowering<'tcx>>,
    &'tcx Steal<ast::Crate>,
    &'tcx ty::ResolverGlobalCtxt,
) {
    let arenas = Resolver::arenas();
    let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`.
    let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal();
    let mut resolver = Resolver::new(
        tcx,
        &pre_configured_attrs,
        krate.spans.inner_span,
        krate.spans.inject_use_span,
        &arenas,
    );
    let krate = configure_and_expand(krate, &pre_configured_attrs, &mut resolver);

    // Make sure we don't mutate the cstore from here on.
    tcx.untracked().cstore.freeze();

    let ResolverOutputs {
        global_ctxt: untracked_resolutions,
        ast_lowering: untracked_resolver_for_lowering,
    } = resolver.into_outputs();

    (
        tcx.arena.alloc(Steal::new(untracked_resolver_for_lowering)),
        tcx.arena.alloc(Steal::new(krate)),
        tcx.arena.alloc(untracked_resolutions),
    )
}

pub fn write_dep_info(tcx: TyCtxt<'_>) {
    // Make sure name resolution and macro expansion is run for
    // the side-effect of providing a complete set of all
    // accessed files and env vars.
    let _ = tcx.resolver_for_lowering();

    let sess = tcx.sess;
    let _timer = sess.timer("write_dep_info");
    let crate_name = tcx.crate_name(LOCAL_CRATE);

    let outputs = tcx.output_filenames(());
    let output_paths =
        generated_output_paths(tcx, outputs, sess.io.output_file.is_some(), crate_name);

    // Ensure the source file isn't accidentally overwritten during compilation.
    if let Some(input_path) = sess.io.input.opt_path() {
        if sess.opts.will_create_output_file() {
            if output_contains_path(&output_paths, input_path) {
                sess.dcx()
                    .emit_fatal(diagnostics::InputFileWouldBeOverWritten { path: input_path });
            }
            if let Some(dir_path) = output_conflicts_with_dir(&output_paths) {
                sess.dcx().emit_fatal(diagnostics::GeneratedFileConflictsWithDirectory {
                    input_path,
                    dir_path,
                });
            }
        }
    }

    if let Some(ref dir) = sess.io.temps_dir {
        if fs::create_dir_all(dir).is_err() {
            sess.dcx().emit_fatal(diagnostics::TempsDirError);
        }
    }

    write_out_deps(tcx, outputs, &output_paths);

    let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)
        && sess.opts.output_types.len() == 1;

    if !only_dep_info {
        if let Some(ref dir) = sess.io.output_dir {
            if fs::create_dir_all(dir).is_err() {
                sess.dcx().emit_fatal(diagnostics::OutDirError);
            }
        }
    }
}

pub fn write_interface<'tcx>(tcx: TyCtxt<'tcx>) {
    if !tcx.crate_types().contains(&rustc_session::config::CrateType::Sdylib) {
        return;
    }
    let _timer = tcx.sess.timer("write_interface");
    let (_, krate) = tcx.resolver_for_lowering();

    let krate = rustc_ast_pretty::pprust::print_crate_as_interface(
        &*krate.borrow(),
        tcx.sess.psess.edition,
        &tcx.sess.psess.attr_id_generator,
    );
    let export_output = tcx.output_filenames(()).interface_path();
    let mut file = fs::File::create_buffered(export_output).unwrap();
    if let Err(err) = write!(file, "{}", krate) {
        tcx.dcx().fatal(format!("error writing interface file: {}", err));
    }
}

pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {
    let providers = &mut Providers::default();
    providers.queries.analysis = analysis;
    providers.queries.resolver_for_lowering_raw = resolver_for_lowering_raw;
    providers.queries.stripped_cfg_items = |tcx, _| &tcx.resolutions(()).stripped_cfg_items[..];
    providers.queries.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).2;
    providers.queries.early_lint_checks = early_lint_checks;
    providers.queries.env_var_os = env_var_os;
    providers.queries.proc_macro_decls_static = |tcx, _| tcx.hir_crate_items(()).proc_macro_decls();
    rustc_ast_lowering::provide(&mut providers.queries);
    limits::provide(&mut providers.queries);
    rustc_expand::provide(&mut providers.queries);
    rustc_const_eval::provide(providers);
    rustc_middle::hir::provide(&mut providers.queries);
    rustc_borrowck::provide(&mut providers.queries);
    rustc_incremental::provide(providers);
    rustc_mir_build::provide(providers);
    rustc_mir_transform::provide(providers);
    rustc_monomorphize::provide(providers);
    rustc_privacy::provide(&mut providers.queries);
    rustc_query_impl::provide(providers);
    rustc_resolve::provide(&mut providers.queries);
    rustc_hir_analysis::provide(&mut providers.queries);
    rustc_hir_typeck::provide(&mut providers.queries);
    ty::provide(&mut providers.queries);
    traits::provide(&mut providers.queries);
    solve::provide(&mut providers.queries);
    rustc_passes::provide(&mut providers.queries);
    rustc_traits::provide(&mut providers.queries);
    rustc_ty_utils::provide(&mut providers.queries);
    rustc_metadata::provide(providers);
    rustc_lint::provide(&mut providers.queries);
    rustc_symbol_mangling::provide(&mut providers.queries);
    rustc_codegen_ssa::provide(providers);
    *providers
});

pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
    compiler: &Compiler,
    krate: rustc_ast::Crate,
    f: F,
) -> T {
    let sess = &compiler.sess;

    let pre_configured_attrs = rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);

    let crate_name = get_crate_name(sess, &pre_configured_attrs);
    let crate_types = collect_crate_types(
        sess,
        &compiler.codegen_backend.supported_crate_types(sess),
        compiler.codegen_backend.name(),
        &pre_configured_attrs,
        krate.spans.inner_span,
    );
    let stable_crate_id = StableCrateId::new(
        crate_name,
        crate_types.contains(&CrateType::Executable),
        sess.opts.cg.metadata.clone(),
        sess.cfg_version,
    );

    let outputs = util::build_output_filenames(&pre_configured_attrs, sess);

    let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id);

    let cstore =
        FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _);
    let definitions = FreezeLock::new(Definitions::new(stable_crate_id));

    let stable_crate_ids = FreezeLock::new(StableCrateIdMap::default());
    let untracked =
        Untracked { cstore, source_span: AppendOnlyIndexVec::new(), definitions, stable_crate_ids };

    // We're constructing the HIR here; we don't care what we will
    // read, since we haven't even constructed the *input* to
    // incr. comp. yet.
    dep_graph.assert_ignored();

    let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess);

    let codegen_backend = &compiler.codegen_backend;
    let mut providers = *DEFAULT_QUERY_PROVIDERS;
    codegen_backend.provide(&mut providers);

    if let Some(callback) = compiler.override_queries {
        callback(sess, &mut providers);
    }

    let incremental = dep_graph.is_fully_enabled();

    // Note: this function body is the origin point of the widely-used 'tcx lifetime.
    //
    // `gcx_cell` is defined here and `&gcx_cell` is passed to `create_global_ctxt`, which then
    // actually creates the `GlobalCtxt` with a `gcx_cell.get_or_init(...)` call. This is done so
    // that the resulting reference has the type `&'tcx GlobalCtxt<'tcx>`, which is what `TyCtxt`
    // needs. If we defined and created the `GlobalCtxt` within `create_global_ctxt` then its type
    // would be `&'a GlobalCtxt<'tcx>`, with two lifetimes.
    //
    // Similarly, by creating `arena` here and passing in `&arena`, that reference has the type
    // `&'tcx WorkerLocal<Arena<'tcx>>`, also with one lifetime. And likewise for `hir_arena`.

    let gcx_cell = OnceLock::new();
    let arena = WorkerLocal::new(|_| Arena::default());
    let hir_arena = WorkerLocal::new(|_| rustc_hir::Arena::default());

    TyCtxt::create_global_ctxt(
        &gcx_cell,
        &compiler.sess,
        crate_types,
        stable_crate_id,
        &arena,
        &hir_arena,
        untracked,
        dep_graph,
        rustc_query_impl::make_dep_kind_vtables(&arena),
        rustc_query_impl::query_system(
            providers.queries,
            providers.extern_queries,
            query_result_on_disk_cache,
            incremental,
        ),
        providers.hooks,
        compiler.current_gcx.clone(),
        Arc::clone(&compiler.jobserver_proxy),
        |tcx| {
            let feed = tcx.create_crate_num(stable_crate_id).unwrap();
            assert_eq!(feed.key(), LOCAL_CRATE);
            feed.crate_name(crate_name);

            let feed = tcx.feed_unit_query();
            feed.features_query(tcx.arena.alloc(rustc_expand::config::features(
                tcx.sess,
                &pre_configured_attrs,
                crate_name,
            )));
            feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs))));
            feed.output_filenames(Arc::new(outputs));

            // There are two paths out of `f`.
            // - Normal exit.
            // - Panic, e.g. triggered by `abort_if_errors` or a fatal error.
            //
            // If a panic occurs, we still need to wind down the self-profiler to correctly record
            // the query events that are still in flight. Otherwise, they will be invalid and will
            // show up as "<unknown>" in the profiling data.
            let res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(tcx)));
            let res = match res {
                Ok(res) => res,
                Err(err) => {
                    tcx.alloc_self_profile_query_strings();

                    // Resume unwinding if a panic happened.
                    std::panic::resume_unwind(err);
                }
            };

            tcx.finish();
            res
        },
    )
}

struct DiagCallback<'tcx> {
    callback: Box<
        dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level, &dyn Any) -> Diag<'b, ()> + DynSend + DynSync,
    >,
    tcx: TyCtxt<'tcx>,
}

impl<'a, 'tcx> Diagnostic<'a, ()> for DiagCallback<'tcx> {
    fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
        (self.callback)(dcx, level, self.tcx.sess)
    }
}

pub fn emit_delayed_lints(tcx: TyCtxt<'_>) {
    for owner_id in tcx.hir_crate_items(()).owners() {
        if let Some(delayed_lints) = tcx.opt_ast_lowering_delayed_lints(owner_id) {
            for lint in delayed_lints.steal() {
                tcx.emit_node_span_lint(
                    lint.lint_id.lint,
                    lint.id,
                    lint.span.clone(),
                    DiagCallback { callback: lint.callback, tcx },
                );
            }
        }
    }
}

/// Runs all analyses that we guarantee to run, even if errors were reported in earlier analyses.
/// This function never fails.
fn run_required_analyses(tcx: TyCtxt<'_>) {
    if tcx.sess.opts.unstable_opts.input_stats {
        rustc_passes::input_stats::print_hir_stats(tcx);
    }
    // When using rustdoc's "jump to def" feature, it enters this code and `check_crate`
    // is not defined. So we need to cfg it out.
    #[cfg(all(not(doc), debug_assertions))]
    rustc_passes::hir_id_validator::check_crate(tcx);

    // Prefetch this to prevent multiple threads from blocking on it later.
    // This is needed since the `hir_id_validator::check_crate` call above is not guaranteed
    // to use `hir_crate_items`.
    tcx.ensure_done().hir_crate_items(());

    rustc_passes::delegation::check_glob_and_list_delegations_target_expr(tcx);

    let sess = tcx.sess;
    sess.time("misc_checking_1", || {
        par_fns(&mut [
            &mut || {
                sess.time("looking_for_entry_point", || tcx.ensure_ok().entry_fn(()));
                sess.time("check_externally_implementable_items", || {
                    tcx.ensure_ok().check_externally_implementable_items(())
                });

                sess.time("looking_for_derive_registrar", || {
                    tcx.ensure_ok().proc_macro_decls_static(())
                });

                CStore::from_tcx(tcx).report_unused_deps(tcx);
            },
            &mut || {
                tcx.ensure_ok().exportable_items(LOCAL_CRATE);
                tcx.ensure_ok().stable_order_of_exportable_impls(LOCAL_CRATE);
                tcx.par_hir_for_each_module(|module| {
                    tcx.ensure_ok().check_mod_attrs(module);
                    tcx.ensure_ok().check_mod_unstable_api_usage(module);
                });
            },
            &mut || {
                // We force these queries to run,
                // since they might not otherwise get called.
                // This marks the corresponding crate-level attributes
                // as used, and ensures that their values are valid.
                tcx.ensure_ok().limits(());
            },
        ]);
    });

    sess.time("emit_ast_lowering_delayed_lints", || {
        emit_delayed_lints(tcx);
    });

    rustc_hir_analysis::check_crate(tcx);
    // Freeze definitions as we don't add new ones at this point.
    // We need to wait until now since we synthesize a by-move body
    // for all coroutine-closures.
    //
    // This improves performance by allowing lock-free access to them.
    tcx.untracked().definitions.freeze();

    sess.time("MIR_borrow_checking", || {
        tcx.par_hir_body_owners(|def_id| {
            let not_typeck_child = !tcx.is_typeck_child(def_id.to_def_id());
            if not_typeck_child {
                // Child unsafety and borrowck happens together with the parent
                tcx.ensure_ok().check_unsafety(def_id);
            }
            if tcx.is_trivial_const(def_id) {
                return;
            }
            if not_typeck_child {
                tcx.ensure_ok().mir_borrowck(def_id);
                tcx.ensure_ok().check_transmutes(def_id);
            }
            tcx.ensure_ok().has_ffi_unwind_calls(def_id);
            tcx.ensure_ok().check_liveness(def_id);

            // If we need to codegen, ensure that we emit all errors from
            // `mir_drops_elaborated_and_const_checked` now, to avoid discovering
            // them later during codegen.
            if tcx.sess.opts.output_types.should_codegen()
                || tcx.hir_body_const_context(def_id).is_some()
            {
                tcx.ensure_ok().mir_drops_elaborated_and_const_checked(def_id);
            }
            if tcx.is_coroutine(def_id.to_def_id())
                && (!tcx.is_async_drop_in_place_coroutine(def_id.to_def_id()))
            {
                // Eagerly check the unsubstituted layout for cycles.
                tcx.ensure_ok()
                    .layout_of(ty::TypingEnv::codegen(tcx, def_id.to_def_id()).as_query_input(
                        tcx.type_of(def_id).instantiate_identity().skip_norm_wip(),
                    ));
            }
        });
    });

    sess.time("layout_testing", || layout_test::test_layout(tcx));
    sess.time("abi_testing", || abi_test::test_abi(tcx));
}

/// Runs the type-checking, region checking and other miscellaneous analysis
/// passes on the crate.
fn analysis(tcx: TyCtxt<'_>, (): ()) {
    run_required_analyses(tcx);

    let sess = tcx.sess;

    // Avoid overwhelming user with errors if borrow checking failed.
    // I'm not sure how helpful this is, to be honest, but it avoids a
    // lot of annoying errors in the ui tests (basically,
    // lint warnings and so on -- kindck used to do this abort, but
    // kindck is gone now). -nmatsakis
    //
    // But we exclude lint errors from this, because lint errors are typically
    // less serious and we're more likely to want to continue (#87337).
    if let Some(guar) = sess.dcx().has_errors_excluding_lint_errors() {
        guar.raise_fatal();
    }

    sess.time("misc_checking_3", || {
        par_fns(&mut [
            &mut || {
                tcx.ensure_ok().effective_visibilities(());

                par_fns(&mut [
                    &mut || {
                        tcx.par_hir_for_each_module(|module| {
                            tcx.ensure_ok().check_private_in_public(module)
                        })
                    },
                    &mut || {
                        tcx.par_hir_for_each_module(|module| {
                            tcx.ensure_ok().check_mod_deathness(module)
                        });
                    },
                    &mut || {
                        sess.time("lint_checking", || {
                            rustc_lint::check_crate(tcx);
                        });
                    },
                    &mut || {
                        tcx.ensure_ok().clashing_extern_declarations(());
                    },
                ]);
            },
            &mut || {
                sess.time("privacy_checking_modules", || {
                    tcx.par_hir_for_each_module(|module| {
                        tcx.ensure_ok().check_mod_privacy(module);
                    });
                });
            },
        ]);

        // This check has to be run after all lints are done processing. We don't
        // define a lint filter, as all lint checks should have finished at this point.
        sess.time("check_lint_expectations", || tcx.ensure_ok().check_expectations(None));

        // This query is only invoked normally if a diagnostic is emitted that needs any
        // diagnostic item. If the crate compiles without checking any diagnostic items,
        // we will fail to emit overlap diagnostics. Thus we invoke it here unconditionally.
        let _ = tcx.all_diagnostic_items(());
    });

    // If `-Zvalidate-mir` is set, we also want to compute the final MIR for each item
    // (either its `mir_for_ctfe` or `optimized_mir`) since that helps uncover any bugs
    // in MIR optimizations that may only be reachable through codegen, or other codepaths
    // that requires the optimized/ctfe MIR, coroutine bodies, or evaluating consts.
    // Nevertheless, wait after type checking is finished, as optimizing code that does not
    // type-check is very prone to ICEs.
    if tcx.sess.opts.unstable_opts.validate_mir {
        sess.time("ensuring_final_MIR_is_computable", || {
            tcx.par_hir_body_owners(|def_id| {
                if !tcx.is_trivial_const(def_id) {
                    tcx.instance_mir(ty::InstanceKind::Item(def_id.into()));
                }
            });
        });
    }
}

/// Runs the codegen backend, after which the AST and analysis can
/// be discarded.
pub(crate) fn start_codegen<'tcx>(
    codegen_backend: &dyn CodegenBackend,
    tcx: TyCtxt<'tcx>,
) -> (Box<dyn Any>, CrateInfo, EncodedMetadata) {
    tcx.sess.timings.start_section(tcx.sess.dcx(), TimingSection::Codegen);

    // Hook for tests.
    if let Some((def_id, _)) = tcx.entry_fn(())
        && find_attr!(tcx, def_id, RustcDelayedBugFromInsideQuery)
    {
        tcx.ensure_ok().trigger_delayed_bug(def_id);
    }

    // Don't run this test assertions when not doing codegen. Compiletest tries to build
    // build-fail tests in check mode first and expects it to not give an error in that case.
    if tcx.sess.opts.output_types.should_codegen() {
        rustc_symbol_mangling::test::dump_symbol_names_and_def_paths(tcx);
    }

    // Don't do code generation if there were any errors. Likewise if
    // there were any delayed bugs, because codegen will likely cause
    // more ICEs, obscuring the original problem.
    if let Some(guar) = tcx.sess.dcx().has_errors_or_delayed_bugs() {
        guar.raise_fatal();
    }

    info!("Pre-codegen\n{:?}", tcx.debug_stats());

    let metadata = rustc_metadata::fs::encode_and_write_metadata(tcx);

    let codegen = tcx.sess.time("codegen_crate", || {
        if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() {
            // Skip crate items and just output metadata in -Z no-codegen mode.
            tcx.sess.dcx().abort_if_errors();

            // Linker::link will skip join_codegen in case of a CodegenResults Any value.
            Box::new(CompiledModules { modules: vec![], allocator_module: None })
        } else {
            codegen_backend.codegen_crate(tcx)
        }
    });

    info!("Post-codegen\n{:?}", tcx.debug_stats());

    // This must run after monomorphization so that all generic types
    // have been instantiated.
    if tcx.sess.opts.unstable_opts.print_type_sizes {
        tcx.sess.code_stats.print_type_sizes();
    }

    let crate_info = CrateInfo::new(tcx, codegen_backend.target_cpu(tcx.sess));

    (codegen, crate_info, metadata)
}

/// Compute and validate the crate name.
pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol {
    // We validate *all* occurrences of `#![crate_name]`, pick the first find and
    // if a crate name was passed on the command line via `--crate-name` we enforce
    // that they match.
    // We perform the validation step here instead of later to ensure it gets run
    // in all code paths that require the crate name very early on, namely before
    // macro expansion.

    let attr_crate_name =
        parse_crate_name(sess, krate_attrs, ShouldEmit::EarlyFatal { also_emit_lints: true });

    let validate = |name, span| {
        rustc_session::output::validate_crate_name(sess, name, span);
        name
    };

    if let Some(crate_name) = &sess.opts.crate_name {
        let crate_name = Symbol::intern(crate_name);
        if let Some((attr_crate_name, span)) = attr_crate_name
            && attr_crate_name != crate_name
        {
            sess.dcx().emit_err(diagnostics::CrateNameDoesNotMatch {
                span,
                crate_name,
                attr_crate_name,
            });
        }
        return validate(crate_name, None);
    }

    if let Some((crate_name, span)) = attr_crate_name {
        return validate(crate_name, Some(span));
    }

    if let Input::File(ref path) = sess.io.input
        && let Some(file_stem) = path.file_stem().and_then(|s| s.to_str())
    {
        if file_stem.starts_with('-') {
            sess.dcx().emit_err(diagnostics::CrateNameInvalid { crate_name: file_stem });
        } else {
            return validate(Symbol::intern(&file_stem.replace('-', "_")), None);
        }
    }

    sym::rust_out
}

pub(crate) fn parse_crate_name(
    sess: &Session,
    attrs: &[ast::Attribute],
    emit_errors: ShouldEmit,
) -> Option<(Symbol, Span)> {
    let rustc_hir::Attribute::Parsed(AttributeKind::CrateName { name, name_span, .. }) =
        AttributeParser::parse_limited_should_emit(
            sess,
            attrs,
            &[sym::crate_name],
            DUMMY_SP,
            rustc_ast::node_id::CRATE_NODE_ID,
            Target::Crate,
            None,
            emit_errors,
        )?
    else {
        unreachable!("crate_name is the only attr we could've parsed here");
    };

    Some((name, name_span))
}

pub fn collect_crate_types(
    session: &Session,
    backend_crate_types: &[CrateType],
    codegen_backend_name: &'static str,
    attrs: &[ast::Attribute],
    crate_span: Span,
) -> Vec<CrateType> {
    // If we're generating a test executable, then ignore all other output
    // styles at all other locations
    if session.opts.test {
        if !session.target.executables {
            session.dcx().emit_warn(diagnostics::UnsupportedCrateTypeForTarget {
                crate_type: CrateType::Executable,
                target_triple: &session.opts.target_triple,
            });
            return Vec::new();
        }
        return vec![CrateType::Executable];
    }

    // Shadow `sdylib` crate type in interface build.
    if session.opts.unstable_opts.build_sdylib_interface {
        return vec![CrateType::Rlib];
    }

    // Only check command line flags if present. If no types are specified by
    // command line, then reuse the empty `base` Vec to hold the types that
    // will be found in crate attributes.
    // JUSTIFICATION: before wrapper fn is available
    #[allow(rustc::bad_opt_access)]
    let mut base = session.opts.crate_types.clone();
    if base.is_empty() {
        if let Some(Attribute::Parsed(AttributeKind::CrateType(crate_type))) =
            AttributeParser::parse_limited_should_emit(
                session,
                attrs,
                &[sym::crate_type],
                crate_span,
                CRATE_NODE_ID,
                Target::Crate,
                None,
                ShouldEmit::EarlyFatal { also_emit_lints: false },
            )
        {
            base.extend(crate_type);
        }

        if base.is_empty() {
            base.push(default_output_for_target(session));
        } else {
            base.sort();
            base.dedup();
        }
    }

    base.retain(|crate_type| {
        if invalid_output_for_target(session, *crate_type) {
            session.dcx().emit_warn(diagnostics::UnsupportedCrateTypeForTarget {
                crate_type: *crate_type,
                target_triple: &session.opts.target_triple,
            });
            false
        } else if !backend_crate_types.contains(crate_type) {
            session.dcx().emit_warn(diagnostics::UnsupportedCrateTypeForCodegenBackend {
                crate_type: *crate_type,
                codegen_backend: codegen_backend_name,
            });
            false
        } else {
            true
        }
    });

    base
}

/// Returns default crate type for target
///
/// Default crate type is used when crate type isn't provided neither
/// through cmd line arguments nor through crate attributes
///
/// It is CrateType::Executable for all platforms but iOS as there is no
/// way to run iOS binaries anyway without jailbreaking and
/// interaction with Rust code through static library is the only
/// option for now
fn default_output_for_target(sess: &Session) -> CrateType {
    if !sess.target.executables { CrateType::StaticLib } else { CrateType::Executable }
}

fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
    let attr = AttributeParser::parse_limited_should_emit(
        sess,
        &krate_attrs,
        &[sym::recursion_limit],
        DUMMY_SP,
        rustc_ast::node_id::CRATE_NODE_ID,
        Target::Crate,
        None,
        // errors are fatal here, but lints aren't.
        // If things aren't fatal we continue, and will parse this again.
        // That makes the same lint trigger again.
        // So, no lints here to avoid duplicates.
        ShouldEmit::EarlyFatal { also_emit_lints: false },
    );
    crate::limits::get_recursion_limit(attr.as_slice(), sess)
}
