From 3e3e70d529d8c7d7c4d7bc4fefc9f109393b9245 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:19:43 +0200 Subject: Merging upstream version 1.69.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_interface/src/passes.rs | 308 ++++++++++++--------------------- 1 file changed, 106 insertions(+), 202 deletions(-) (limited to 'compiler/rustc_interface/src/passes.rs') diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 379a76528..81c1d665e 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1,9 +1,4 @@ -use crate::errors::{ - CantEmitMIR, EmojiIdentifier, ErrorWritingDependencies, FerrisIdentifier, - GeneratedFileConflictsWithDirectory, InputFileWouldBeOverWritten, MixedBinCrate, - MixedProcMacroCrate, OutDirError, ProcMacroCratePanicAbort, ProcMacroDocWithoutArg, - TempsDirError, -}; +use crate::errors; use crate::interface::{Compiler, Result}; use crate::proc_macro_decls; use crate::util; @@ -13,11 +8,12 @@ use rustc_ast::{self as ast, visit}; use rustc_borrowck as mir_borrowck; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::parallel; +use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{Lrc, OnceCell, WorkerLocal}; -use rustc_errors::{ErrorGuaranteed, PResult}; +use rustc_errors::PResult; use rustc_expand::base::{ExtCtxt, LintStoreExpand, ResolverExpand}; -use rustc_hir::def_id::StableCrateId; -use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore}; +use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; +use rustc_lint::{unerased_lint_store, BufferedEarlyLint, EarlyCheckNode, LintStore}; use rustc_metadata::creader::CStore; use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; @@ -28,9 +24,9 @@ use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_a use rustc_passes::{self, hir_stats, layout_test}; use rustc_plugin_impl as plugin; use rustc_query_impl::{OnDiskCache, Queries as TcxQueries}; -use rustc_resolve::{Resolver, ResolverArenas}; +use rustc_resolve::Resolver; use rustc_session::config::{CrateType, Input, OutputFilenames, OutputType}; -use rustc_session::cstore::{MetadataLoader, MetadataLoaderDyn, Untracked}; +use rustc_session::cstore::{CrateStoreDyn, MetadataLoader, Untracked}; use rustc_session::output::filename_for_input; use rustc_session::search_paths::PathKind; use rustc_session::{Limit, Session}; @@ -40,14 +36,10 @@ use rustc_target::spec::PanicStrategy; use rustc_trait_selection::traits; use std::any::Any; -use std::cell::RefCell; use std::ffi::OsString; use std::io::{self, BufWriter, Write}; -use std::marker::PhantomPinned; use std::path::{Path, PathBuf}; -use std::pin::Pin; -use std::rc::Rc; -use std::sync::LazyLock; +use std::sync::{Arc, LazyLock}; use std::{env, fs, iter}; pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> { @@ -80,93 +72,6 @@ fn count_nodes(krate: &ast::Crate) -> usize { counter.count } -pub use boxed_resolver::BoxedResolver; -mod boxed_resolver { - use super::*; - - pub struct BoxedResolver(Pin>); - - struct BoxedResolverInner { - session: Lrc, - resolver_arenas: Option>, - resolver: Option>, - _pin: PhantomPinned, - } - - // Note: Drop order is important to prevent dangling references. Resolver must be dropped first, - // then resolver_arenas and session. - impl Drop for BoxedResolverInner { - fn drop(&mut self) { - self.resolver.take(); - self.resolver_arenas.take(); - } - } - - impl BoxedResolver { - pub(super) fn new( - session: Lrc, - make_resolver: impl for<'a> FnOnce(&'a Session, &'a ResolverArenas<'a>) -> Resolver<'a>, - ) -> BoxedResolver { - 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 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(resolver); - BoxedResolver(Pin::new_unchecked(boxed_resolver)) - } - } - - pub fn access 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>) -> ty::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()), - } - } - } -} - -pub fn create_resolver( - sess: Lrc, - metadata_loader: Box, - krate: &ast::Crate, - crate_name: Symbol, -) -> BoxedResolver { - trace!("create_resolver"); - BoxedResolver::new(sess, move |sess, resolver_arenas| { - Resolver::new(sess, krate, crate_name, metadata_loader, resolver_arenas) - }) -} - pub fn register_plugins<'a>( sess: &'a Session, metadata_loader: &'a dyn MetadataLoader, @@ -267,14 +172,12 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> { /// 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. -pub fn configure_and_expand( - sess: &Session, - lint_store: &LintStore, - mut krate: ast::Crate, - crate_name: Symbol, - resolver: &mut Resolver<'_>, -) -> Result { - trace!("configure_and_expand"); +#[instrument(level = "trace", skip(krate, resolver))] +fn configure_and_expand(mut krate: ast::Crate, resolver: &mut Resolver<'_, '_>) -> ast::Crate { + let tcx = resolver.tcx(); + let sess = tcx.sess; + let lint_store = unerased_lint_store(tcx); + let crate_name = tcx.crate_name(LOCAL_CRATE); pre_expansion_lint(sess, lint_store, resolver.registered_tools(), &krate, crate_name); rustc_builtin_macros::register_builtin_macros(resolver); @@ -345,20 +248,19 @@ pub fn configure_and_expand( ecx.check_unused_macros(); }); - let recursion_limit_hit = ecx.reduced_recursion_limit.is_some(); + // 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.abort_if_errors(); + unreachable!(); + } if cfg!(windows) { env::set_var("PATH", &old_path); } - if recursion_limit_hit { - // If we hit a recursion limit, exit early to avoid later passes getting overwhelmed - // with a large AST - Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) - } else { - Ok(krate) - } - })?; + krate + }); sess.time("maybe_building_test_harness", || { rustc_builtin_macros::test_harness::inject(sess, resolver, &mut krate) @@ -374,39 +276,29 @@ pub fn configure_and_expand( if crate_types.len() > 1 { if is_executable_crate { - sess.emit_err(MixedBinCrate); + sess.emit_err(errors::MixedBinCrate); } if is_proc_macro_crate { - sess.emit_err(MixedProcMacroCrate); + sess.emit_err(errors::MixedProcMacroCrate); } } if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort { - sess.emit_warning(ProcMacroCratePanicAbort); + sess.emit_warning(errors::ProcMacroCratePanicAbort); } - // For backwards compatibility, we don't try to run proc macro injection - // if rustdoc is run on a proc macro crate without '--crate-type proc-macro' being - // specified. This should only affect users who manually invoke 'rustdoc', as - // 'cargo doc' will automatically pass the proper '--crate-type' flags. - // However, we do emit a warning, to let such users know that they should - // start passing '--crate-type proc-macro' - if has_proc_macro_decls && sess.opts.actually_rustdoc && !is_proc_macro_crate { - sess.emit_warning(ProcMacroDocWithoutArg); - } else { - krate = sess.time("maybe_create_a_macro_crate", || { - let is_test_crate = sess.opts.test; - rustc_builtin_macros::proc_macro_harness::inject( - sess, - resolver, - krate, - is_proc_macro_crate, - has_proc_macro_decls, - is_test_crate, - sess.diagnostic(), - ) - }); - } + krate = sess.time("maybe_create_a_macro_crate", || { + let is_test_crate = sess.opts.test; + rustc_builtin_macros::proc_macro_harness::inject( + sess, + resolver, + krate, + is_proc_macro_crate, + has_proc_macro_decls, + is_test_crate, + sess.diagnostic(), + ) + }); // Done with macro expansion! @@ -441,9 +333,9 @@ pub fn configure_and_expand( spans.sort(); if ident == sym::ferris { let first_span = spans[0]; - sess.emit_err(FerrisIdentifier { spans, first_span }); + sess.emit_err(errors::FerrisIdentifier { spans, first_span }); } else { - sess.emit_err(EmojiIdentifier { spans, ident }); + sess.emit_err(errors::EmojiIdentifier { spans, ident }); } } }); @@ -461,7 +353,7 @@ pub fn configure_and_expand( ) }); - Ok(krate) + krate } // Returns all the paths that correspond to generated files. @@ -548,7 +440,7 @@ fn escape_dep_env(symbol: Symbol) -> String { fn write_out_deps( sess: &Session, - boxed_resolver: &RefCell, + cstore: &CrateStoreDyn, outputs: &OutputFilenames, out_filenames: &[PathBuf], ) { @@ -600,20 +492,19 @@ fn write_out_deps( } } - boxed_resolver.borrow_mut().access(|resolver| { - for cnum in resolver.cstore().crates_untracked() { - let source = resolver.cstore().crate_source_untracked(cnum); - if let Some((path, _)) = &source.dylib { - files.push(escape_dep_filename(&path.display().to_string())); - } - if let Some((path, _)) = &source.rlib { - files.push(escape_dep_filename(&path.display().to_string())); - } - if let Some((path, _)) = &source.rmeta { - files.push(escape_dep_filename(&path.display().to_string())); - } + let cstore = cstore.as_any().downcast_ref::().unwrap(); + for cnum in cstore.crates_untracked() { + let source = cstore.crate_source_untracked(cnum); + if let Some((path, _)) = &source.dylib { + files.push(escape_dep_filename(&path.display().to_string())); + } + if let Some((path, _)) = &source.rlib { + files.push(escape_dep_filename(&path.display().to_string())); } - }); + if let Some((path, _)) = &source.rmeta { + files.push(escape_dep_filename(&path.display().to_string())); + } + } } let mut file = BufWriter::new(fs::File::create(&deps_filename)?); @@ -656,18 +547,38 @@ fn write_out_deps( } } Err(error) => { - sess.emit_fatal(ErrorWritingDependencies { path: &deps_filename, error }); + sess.emit_fatal(errors::ErrorWritingDependencies { path: &deps_filename, error }); } } } -pub fn prepare_outputs( - sess: &Session, - krate: &ast::Crate, - boxed_resolver: &RefCell, - crate_name: Symbol, -) -> Result { +fn resolver_for_lowering<'tcx>( + tcx: TyCtxt<'tcx>, + (): (), +) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc)> { + let arenas = Resolver::arenas(); + let krate = tcx.crate_for_resolver(()).steal(); + let mut resolver = Resolver::new(tcx, &krate, &arenas); + let krate = configure_and_expand(krate, &mut resolver); + + // Make sure we don't mutate the cstore from here on. + tcx.untracked().cstore.leak(); + + let ty::ResolverOutputs { + global_ctxt: untracked_resolutions, + ast_lowering: untracked_resolver_for_lowering, + } = resolver.into_outputs(); + + let feed = tcx.feed_unit_query(); + feed.resolutions(tcx.arena.alloc(untracked_resolutions)); + tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))) +} + +fn output_filenames(tcx: TyCtxt<'_>, (): ()) -> Arc { + let sess = tcx.sess; let _timer = sess.timer("prepare_outputs"); + let (_, krate) = &*tcx.resolver_for_lowering(()).borrow(); + let crate_name = tcx.crate_name(LOCAL_CRATE); // FIXME: rustdoc passes &[] instead of &krate.attrs here let outputs = util::build_output_filenames(&krate.attrs, sess); @@ -679,25 +590,24 @@ pub fn prepare_outputs( if let Some(ref input_path) = sess.io.input.opt_path() { if sess.opts.will_create_output_file() { if output_contains_path(&output_paths, input_path) { - let reported = sess.emit_err(InputFileWouldBeOverWritten { path: input_path }); - return Err(reported); + sess.emit_fatal(errors::InputFileWouldBeOverWritten { path: input_path }); } if let Some(ref dir_path) = output_conflicts_with_dir(&output_paths) { - let reported = - sess.emit_err(GeneratedFileConflictsWithDirectory { input_path, dir_path }); - return Err(reported); + sess.emit_fatal(errors::GeneratedFileConflictsWithDirectory { + input_path, + dir_path, + }); } } } if let Some(ref dir) = sess.io.temps_dir { if fs::create_dir_all(dir).is_err() { - let reported = sess.emit_err(TempsDirError); - return Err(reported); + sess.emit_fatal(errors::TempsDirError); } } - write_out_deps(sess, boxed_resolver, &outputs, &output_paths); + write_out_deps(sess, &*tcx.cstore_untracked(), &outputs, &output_paths); let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo) && sess.opts.output_types.len() == 1; @@ -705,19 +615,20 @@ pub fn prepare_outputs( if !only_dep_info { if let Some(ref dir) = sess.io.output_dir { if fs::create_dir_all(dir).is_err() { - let reported = sess.emit_err(OutDirError); - return Err(reported); + sess.emit_fatal(errors::OutDirError); } } } - Ok(outputs) + outputs.into() } pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; providers.hir_crate = rustc_ast_lowering::lower_to_hir; + providers.output_filenames = output_filenames; + providers.resolver_for_lowering = resolver_for_lowering; proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); rustc_middle::hir::provide(providers); @@ -747,30 +658,16 @@ pub static DEFAULT_EXTERN_QUERY_PROVIDERS: LazyLock = LazyLock: extern_providers }); -pub struct QueryContext<'tcx> { - gcx: &'tcx GlobalCtxt<'tcx>, -} - -impl<'tcx> QueryContext<'tcx> { - pub fn enter(&mut self, f: F) -> R - where - F: FnOnce(TyCtxt<'tcx>) -> R, - { - let icx = ty::tls::ImplicitCtxt::new(self.gcx); - ty::tls::enter_context(&icx, |_| f(icx.tcx)) - } -} - pub fn create_global_ctxt<'tcx>( compiler: &'tcx Compiler, lint_store: Lrc, dep_graph: DepGraph, untracked: Untracked, queries: &'tcx OnceCell>, - global_ctxt: &'tcx OnceCell>, + gcx_cell: &'tcx OnceCell>, arena: &'tcx WorkerLocal>, hir_arena: &'tcx WorkerLocal>, -) -> QueryContext<'tcx> { +) -> &'tcx GlobalCtxt<'tcx> { // 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. @@ -794,8 +691,8 @@ pub fn create_global_ctxt<'tcx>( TcxQueries::new(local_providers, extern_providers, query_result_on_disk_cache) }); - let gcx = sess.time("setup_global_ctxt", || { - global_ctxt.get_or_init(move || { + sess.time("setup_global_ctxt", || { + gcx_cell.get_or_init(move || { TyCtxt::create_global_ctxt( sess, lint_store, @@ -808,9 +705,7 @@ pub fn create_global_ctxt<'tcx>( rustc_query_impl::query_callbacks(arena), ) }) - }); - - QueryContext { gcx } + }) } /// Runs the resolution, type-checking, region checking and other @@ -900,6 +795,15 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { } }); + if tcx.sess.opts.unstable_opts.drop_tracking_mir { + tcx.hir().par_body_owners(|def_id| { + if let rustc_hir::def::DefKind::Generator = tcx.def_kind(def_id) { + tcx.ensure().mir_generator_witnesses(def_id); + tcx.ensure().check_generator_obligations(def_id); + } + }); + } + sess.time("layout_testing", || layout_test::test_layout(tcx)); // Avoid overwhelming user with errors if borrow checking failed. @@ -975,7 +879,7 @@ pub fn start_codegen<'tcx>( if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { if let Err(error) = rustc_mir_transform::dump_mir::emit_mir(tcx) { - tcx.sess.emit_err(CantEmitMIR { error }); + tcx.sess.emit_err(errors::CantEmitMIR { error }); tcx.sess.abort_if_errors(); } } -- cgit v1.2.3