<commit_before>use crate::interface::{Compiler, Result};
use crate::proc_macro_decls;
use crate::util;

use rustc_ast::mut_visit::MutVisitor;
use rustc_ast::{self as ast, visit};
use rustc_codegen_ssa::back::link::emit_metadata;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::parallel;
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_errors::{ErrorReported, PResult};
use rustc_expand::base::ExtCtxt;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_hir::Crate;
use rustc_lint::LintStore;
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph;
use rustc_middle::middle;
use rustc_middle::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
use rustc_mir as mir;
use rustc_mir_build as mir_build;
use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
use rustc_passes::{self, hir_stats, layout_test};
use rustc_plugin_impl as plugin;
use rustc_query_impl::Queries as TcxQueries;
use rustc_resolve::{Resolver, ResolverArenas};
use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType, PpMode, PpSourceMode};
use rustc_session::lint;
use rustc_session::output::{filename_for_input, filename_for_metadata};
use rustc_session::search_paths::PathKind;
use rustc_session::Session;
use rustc_span::symbol::{Ident, Symbol};
use rustc_trait_selection::traits;
use rustc_typeck as typeck;
use tracing::{info, warn};

use rustc_serialize::json;
use tempfile::Builder as TempFileBuilder;

use std::any::Any;
use std::cell::RefCell;
use std::ffi::OsString;
use std::io::{self, BufWriter, Write};
use std::lazy::SyncLazy;
use std::marker::PhantomPinned;
use std::path::PathBuf;
use std::pin::Pin;
use std::rc::Rc;
use std::{env, fs, iter};

pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
    let krate = sess.time("parse_crate", || match input {
        Input::File(file) => parse_crate_from_file(file, &sess.parse_sess),
        Input::Str { input, name } => {
            parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess)
        }
    })?;

    if sess.opts.debugging_opts.ast_json_noexpand {
        println!("{}", json::as_json(&krate));
    }

    if sess.opts.debugging_opts.input_stats {
        eprintln!("Lines of code:             {}", sess.source_map().count_lines());
        eprintln!("Pre-expansion node count:  {}", count_nodes(&krate));
    }

    if let Some(ref s) = sess.opts.debugging_opts.show_span {
        rustc_ast_passes::show_span::run(sess.diagnostic(), s, &krate);
    }

    if sess.opts.debugging_opts.hir_stats {
        hir_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS");
    }

    Ok(krate)
}

fn count_nodes(krate: &ast::Crate) -> usize {
    let mut counter = rustc_ast_passes::node_count::NodeCounter::new();
    visit::walk_crate(&mut counter, krate);
    counter.count
}

pub use boxed_resolver::BoxedResolver;
mod boxed_resolver {
    use super::*;

    pub struct BoxedResolver(Pin<Box<BoxedResolverInner>>);

    struct BoxedResolverInner {
        session: Lrc<Session>,
        resolver_arenas: Option<ResolverArenas<'static>>,
        resolver: Option<Resolver<'static>>,
        _pin: PhantomPinned,
    }

    // Note: Drop order is important to prevent dangling references. Resolver must be dropped first,
    // then resolver_arenas and finally session.
    impl Drop for BoxedResolverInner {
        fn drop(&mut self) {
            self.resolver.take();
            self.resolver_arenas.take();
        }
    }

    impl BoxedResolver {
        pub(super) fn new<F>(session: Lrc<Session>, make_resolver: F) -> Result<(ast::Crate, Self)>
        where
            F: for<'a> FnOnce(
                &'a Session,
                &'a ResolverArenas<'a>,
            ) -> Result<(ast::Crate, Resolver<'a>)>,
        {
            let mut boxed_resolver = Box::new(BoxedResolverInner {
                session,
                resolver_arenas: Some(Resolver::arenas()),
                resolver: None,
                _pin: PhantomPinned,
            });
            unsafe {
                let (crate_, resolver) = make_resolver(
                    std::mem::transmute::<&Session, &Session>(&boxed_resolver.session),
                    std::mem::transmute::<&ResolverArenas<'_>, &ResolverArenas<'_>>(
                        boxed_resolver.resolver_arenas.as_ref().unwrap(),
                    ),
                )?;
                boxed_resolver.resolver =
                    Some(std::mem::transmute::<Resolver<'_>, Resolver<'_>>(resolver));
                Ok((crate_, BoxedResolver(Pin::new_unchecked(boxed_resolver))))
            }
        }

        pub fn access<F: for<'a> FnOnce(&mut Resolver<'a>) -> R, R>(&mut self, f: F) -> R {
            let mut resolver = unsafe {
                self.0.as_mut().map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver)
            };
            f((&mut *resolver).as_mut().unwrap())
        }

        pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ResolverOutputs {
            match Rc::try_unwrap(resolver) {
                Ok(resolver) => {
                    let mut resolver = resolver.into_inner();
                    let mut resolver = unsafe {
                        resolver
                            .0
                            .as_mut()
                            .map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver)
                    };
                    resolver.take().unwrap().into_outputs()
                }
                Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()),
            }
        }
    }
}

/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins,
/// syntax expansion, secondary `cfg` expansion, synthesis of a test<commit_msg>Add safety comments<commit_after>use crate::interface::{Compiler, Result};
use crate::proc_macro_decls;
use crate::util;

use rustc_ast::mut_visit::MutVisitor;
use rustc_ast::{self as ast, visit};
use rustc_codegen_ssa::back::link::emit_metadata;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_data_structures::parallel;
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{par_iter, Lrc, OnceCell, ParallelIterator, WorkerLocal};
use rustc_data_structures::temp_dir::MaybeTempDir;
use rustc_errors::{ErrorReported, PResult};
use rustc_expand::base::ExtCtxt;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_hir::Crate;
use rustc_lint::LintStore;
use rustc_metadata::creader::CStore;
use rustc_middle::arena::Arena;
use rustc_middle::dep_graph::DepGraph;
use rustc_middle::middle;
use rustc_middle::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt};
use rustc_mir as mir;
use rustc_mir_build as mir_build;
use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str};
use rustc_passes::{self, hir_stats, layout_test};
use rustc_plugin_impl as plugin;
use rustc_query_impl::Queries as TcxQueries;
use rustc_resolve::{Resolver, ResolverArenas};
use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType, PpMode, PpSourceMode};
use rustc_session::lint;
use rustc_session::output::{filename_for_input, filename_for_metadata};
use rustc_session::search_paths::PathKind;
use rustc_session::Session;
use rustc_span::symbol::{Ident, Symbol};
use rustc_trait_selection::traits;
use rustc_typeck as typeck;
use tracing::{info, warn};

use rustc_serialize::json;
use tempfile::Builder as TempFileBuilder;

use std::any::Any;
use std::cell::RefCell;
use std::ffi::OsString;
use std::io::{self, BufWriter, Write};
use std::lazy::SyncLazy;
use std::marker::PhantomPinned;
use std::path::PathBuf;
use std::pin::Pin;
use std::rc::Rc;
use std::{env, fs, iter};

pub fn parse<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::Crate> {
    let krate = sess.time("parse_crate", || match input {
        Input::File(file) => parse_crate_from_file(file, &sess.parse_sess),
        Input::Str { input, name } => {
            parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess)
        }
    })?;

    if sess.opts.debugging_opts.ast_json_noexpand {
        println!("{}", json::as_json(&krate));
    }

    if sess.opts.debugging_opts.input_stats {
        eprintln!("Lines of code:             {}", sess.source_map().count_lines());
        eprintln!("Pre-expansion node count:  {}", count_nodes(&krate));
    }

    if let Some(ref s) = sess.opts.debugging_opts.show_span {
        rustc_ast_passes::show_span::run(sess.diagnostic(), s, &krate);
    }

    if sess.opts.debugging_opts.hir_stats {
        hir_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS");
    }

    Ok(krate)
}

fn count_nodes(krate: &ast::Crate) -> usize {
    let mut counter = rustc_ast_passes::node_count::NodeCounter::new();
    visit::walk_crate(&mut counter, krate);
    counter.count
}

pub use boxed_resolver::BoxedResolver;
mod boxed_resolver {
    use super::*;

    pub struct BoxedResolver(Pin<Box<BoxedResolverInner>>);

    struct BoxedResolverInner {
        session: Lrc<Session>,
        resolver_arenas: Option<ResolverArenas<'static>>,
        resolver: Option<Resolver<'static>>,
        _pin: PhantomPinned,
    }

    // Note: Drop order is important to prevent dangling references. Resolver must be dropped first,
    // then resolver_arenas and finally session.
    impl Drop for BoxedResolverInner {
        fn drop(&mut self) {
            self.resolver.take();
            self.resolver_arenas.take();
        }
    }

    impl BoxedResolver {
        pub(super) fn new<F>(session: Lrc<Session>, make_resolver: F) -> Result<(ast::Crate, Self)>
        where
            F: for<'a> FnOnce(
                &'a Session,
                &'a ResolverArenas<'a>,
            ) -> Result<(ast::Crate, Resolver<'a>)>,
        {
            let mut boxed_resolver = Box::new(BoxedResolverInner {
                session,
                resolver_arenas: Some(Resolver::arenas()),
                resolver: None,
                _pin: PhantomPinned,
            });
            // SAFETY: `make_resolver` takes a resolver arena with an arbitrary lifetime and
            // returns a resolver with the same lifetime as the arena. We ensure that the arena
            // outlives the resolver in the drop impl and elsewhere so these transmutes are sound.
            unsafe {
                let (crate_, resolver) = make_resolver(
                    std::mem::transmute::<&Session, &Session>(&boxed_resolver.session),
                    std::mem::transmute::<&ResolverArenas<'_>, &ResolverArenas<'_>>(
                        boxed_resolver.resolver_arenas.as_ref().unwrap(),
                    ),
                )?;
                boxed_resolver.resolver =
                    Some(std::mem::transmute::<Resolver<'_>, Resolver<'_>>(resolver));
                Ok((crate_, BoxedResolver(Pin::new_unchecked(boxed_resolver))))
            }
        }

        pub fn access<F: for<'a> FnOnce(&mut Resolver<'a>) -> R, R>(&mut self, f: F) -> R {
            // SAFETY: The resolver doesn't need to be pinned.
            let mut resolver = unsafe {
                self.0.as_mut().map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver)
            };
            f((&mut *resolver).as_mut().unwrap())
        }

        pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ResolverOutputs {
            match Rc::try_unwrap(resolver) {
                Ok(resolver) => {
                    let mut resolver = resolver.into_inner();
                    // SAFETY: The resolver doesn't need to be pinned.
                    let mut resolver = unsafe {
                        resolver
                            .0
                            .as_mut()
                            .map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver)
                    };
                    resolver.take().unwrap().into_outputs()
                }
                Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()),
            }
        }
    }
}

/// Runs the "early phases" of the compiler: initial `cfg` processing, loading compiler plugins,
/// syntax expansion, secondary `cfg` expansion, synthesis of a test
{'fraction_non_alphanumeric': 0.12982815702349046, 'fraction_numerical': 0.00031530821377896896, 'mean_word_length': 3.0301778907242696, 'pattern_counts': {'":': 0, '<': 59, '<?xml version=': 0, '>': 81, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2962768', 'n_tokens_mistral': 4078, 'n_tokens_neox': 4069, 'n_words': 801}