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_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
use rustc_errors::{ErrorReported, PResult};
use rustc_expand::base::ExtCtxt;
-use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE};
+use rustc_hir::def_id::LOCAL_CRATE;
use rustc_hir::Crate;
use rustc_lint::LintStore;
use rustc_metadata::creader::CStore;
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};
counter.count
}
-declare_box_region_type!(
- pub BoxedResolver,
- for(),
- (&mut Resolver<'_>) -> (Result<ast::Crate>, ResolverOutputs)
-);
+pub use boxed_resolver::BoxedResolver;
+mod boxed_resolver {
+ use super::*;
+
+ pub struct BoxedResolver(Pin<Box<BoxedResolverInner>>);
+
+ // Note: Drop order is important to prevent dangling references. Resolver must be dropped first,
+ // then resolver_arenas and finally session.
+ // The drop order is defined to be from top to bottom in RFC1857, so there is no need for
+ // ManuallyDrop for as long as the fields are not reordered.
+ struct BoxedResolverInner {
+ resolver: Option<Resolver<'static>>,
+ resolver_arenas: ResolverArenas<'static>,
+ session: Lrc<Session>,
+ _pin: PhantomPinned,
+ }
+
+ 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: 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,
+ ),
+ )?;
+ 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
// its contents but the results of name resolution on those contents. Hopefully we'll push
// this back at some point.
let crate_name = crate_name.to_string();
- let (result, resolver) = BoxedResolver::new(static move |mut action| {
- let _ = action;
- let sess = &*sess;
- let resolver_arenas = Resolver::arenas();
- let res = configure_and_expand_inner(
+ BoxedResolver::new(sess, move |sess, resolver_arenas| {
+ configure_and_expand_inner(
sess,
&lint_store,
krate,
&crate_name,
&resolver_arenas,
- &*metadata_loader,
- );
- let mut resolver = match res {
- Err(v) => {
- yield BoxedResolver::initial_yield(Err(v));
- panic!()
- }
- Ok((krate, resolver)) => {
- action = yield BoxedResolver::initial_yield(Ok(krate));
- resolver
- }
- };
- box_region_allow_access!(for(), (&mut Resolver<'_>), (&mut resolver), action);
- resolver.into_outputs()
- });
- result.map(|k| (k, resolver))
-}
-
-impl BoxedResolver {
- pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ResolverOutputs {
- match Rc::try_unwrap(resolver) {
- Ok(resolver) => resolver.into_inner().complete(),
- Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()),
- }
- }
+ metadata_loader,
+ )
+ })
}
pub fn register_plugins<'a>(
let crate_types = util::collect_crate_types(sess, &krate.attrs);
sess.init_crate_types(crate_types);
- let stable_crate_id = StableCrateId::new(
- crate_name,
- sess.crate_types().contains(&CrateType::Executable),
- sess.opts.cg.metadata.clone(),
- );
- sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized");
- rustc_incremental::prepare_session_directory(sess, &crate_name, stable_crate_id)?;
+ let disambiguator = util::compute_crate_disambiguator(sess);
+ sess.crate_disambiguator.set(disambiguator).expect("not yet initialized");
+ rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator)?;
if sess.opts.incremental.is_some() {
sess.time("incr_comp_garbage_collect_session_directories", || {
fn configure_and_expand_inner<'a>(
sess: &'a Session,
- lint_store: &'a LintStore,
+ lint_store: &LintStore,
mut krate: ast::Crate,
crate_name: &str,
resolver_arenas: &'a ResolverArenas<'a>,
- metadata_loader: &'a MetadataLoaderDyn,
+ metadata_loader: Box<MetadataLoaderDyn>,
) -> Result<(ast::Crate, Resolver<'a>)> {
tracing::trace!("configure_and_expand_inner");
pre_expansion_lint(sess, lint_store, &krate, crate_name);
query_result_on_disk_cache,
queries.as_dyn(),
&crate_name,
- &outputs,
+ outputs,
)
})
});
.tempdir_in(out_filename.parent().unwrap())
.unwrap_or_else(|err| tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err)));
let metadata_tmpdir = MaybeTempDir::new(metadata_tmpdir, tcx.sess.opts.cg.save_temps);
- let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir);
+ let metadata_filename = emit_metadata(tcx.sess, &metadata.raw_data, &metadata_tmpdir);
if let Err(e) = util::non_durable_rename(&metadata_filename, &out_filename) {
tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
}