]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_interface/src/passes.rs
Don't require LintStore to live for 'a in configure_and_expand_inner
[rust.git] / compiler / rustc_interface / src / passes.rs
index 79b318a4d34df50f44fdeaa6ab8e4f1a33de2e1b..62abc5e696430ef8e0d3f66a29a33df3e1ed7e20 100644 (file)
@@ -7,6 +7,7 @@
 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};
@@ -46,8 +47,7 @@
 use std::ffi::OsString;
 use std::io::{self, BufWriter, Write};
 use std::lazy::SyncLazy;
-use std::marker::PhantomData;
-use std::ops::{Generator, GeneratorState};
+use std::marker::PhantomPinned;
 use std::path::PathBuf;
 use std::pin::Pin;
 use std::rc::Rc;
@@ -87,103 +87,72 @@ fn count_nodes(krate: &ast::Crate) -> usize {
     counter.count
 }
 
-pub struct AccessAction(*mut dyn for<'a> FnMut(&mut Resolver<'a>));
-
-impl AccessAction {
-    pub fn get(self) -> *mut dyn for<'a> FnMut(&mut Resolver<'a>) {
-        self.0
-    }
-}
-
-pub enum Action {
-    Initial,
-    Access(AccessAction),
-    Complete,
-}
-
-#[derive(PartialEq)]
-pub struct Marker<T>(PhantomData<T>);
-
-impl<T> Marker<T> {
-    pub unsafe fn new() -> Self {
-        Marker(PhantomData)
-    }
-}
-
-pub enum YieldType<I, A> {
-    Initial(I),
-    Accessor(Marker<A>),
-}
-
-pub struct BoxedResolver {
-    generator: Pin<
-        Box<
-            dyn Generator<
-                Action,
-                Yield = YieldType<Result<ast::Crate>, for<'a> fn(&mut Resolver<'a>)>,
-                Return = ResolverOutputs,
-            >,
-        >,
-    >,
-}
-
-impl BoxedResolver {
-    fn new<T>(generator: T) -> (Result<ast::Crate>, Self)
-    where
-        T: ::std::ops::Generator<
-                Action,
-                Yield = YieldType<Result<ast::Crate>, fn(&mut Resolver<'_>)>,
-                Return = ResolverOutputs,
-            > + 'static,
-    {
-        let mut generator = Box::pin(generator);
-
-        // Run it to the first yield to set it up
-        let init = match generator.as_mut().resume(Action::Initial) {
-            GeneratorState::Yielded(YieldType::Initial(y)) => y,
-            _ => panic!(),
-        };
-
-        (init, BoxedResolver { generator })
+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,
     }
 
-    pub fn access<F: for<'a> FnOnce(&mut Resolver<'a>) -> R, R>(&mut self, f: F) -> R {
-        // Turn the FnOnce closure into *mut dyn FnMut()
-        // so we can pass it in to the generator
-        let mut r = None;
-        let mut f = Some(f);
-        let mut_f: &mut dyn for<'a> FnMut(&mut Resolver<'a>) = &mut |resolver| {
-            let f = f.take().unwrap();
-            r = Some(f(resolver));
-        };
-        let mut_f = mut_f as *mut dyn for<'a> FnMut(&mut Resolver<'a>);
-
-        // Get the generator to call our closure
-        unsafe {
-            // Call the generator, which in turn will call the closure
-            if let GeneratorState::Complete(_) = self
-                .generator
-                .as_mut()
-                .resume(Action::Access(AccessAction(::std::mem::transmute(mut_f))))
-            {
-                panic!()
+    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))))
             }
         }
 
-        // Unwrap the result
-        r.unwrap()
-    }
-
-    pub fn complete(mut self) -> ResolverOutputs {
-        // Tell the generator we want it to complete, consuming it and yielding a result
-        let result = self.generator.as_mut().resume(Action::Complete);
-        if let GeneratorState::Complete(r) = result { r } else { panic!() }
-    }
+        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())
+        }
 
-    fn initial_yield(
-        value: Result<ast::Crate>,
-    ) -> YieldType<Result<ast::Crate>, fn(&mut Resolver<'_>)> {
-        YieldType::Initial(value)
+        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()),
+            }
+        }
     }
 }
 
@@ -207,59 +176,16 @@ pub fn configure_and_expand(
     // 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
-            }
-        };
-
-        loop {
-            match action {
-                Action::Access(accessor) => {
-                    let accessor: &mut dyn FnMut(&mut Resolver<'_>) =
-                        unsafe { ::std::mem::transmute(accessor.get()) };
-                    (*accessor)(&mut resolver);
-                    unsafe {
-                        let marker = Marker::<fn(&mut Resolver<'_>)>::new();
-                        action = yield YieldType::Accessor(marker);
-                    };
-                }
-                Action::Complete => break,
-                Action::Initial => {
-                    panic!("unexpected box_region action: Initial")
-                }
-            }
-        }
-
-        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()),
-        }
-    }
+        )
+    })
 }
 
 pub fn register_plugins<'a>(
@@ -668,7 +594,7 @@ fn escape_dep_env(symbol: Symbol) -> String {
 
 fn write_out_deps(
     sess: &Session,
-    resolver: &Resolver<'_>,
+    boxed_resolver: &Steal<Rc<RefCell<BoxedResolver>>>,
     outputs: &OutputFilenames,
     out_filenames: &[PathBuf],
 ) {
@@ -695,18 +621,20 @@ fn write_out_deps(
         }
 
         if sess.binary_dep_depinfo() {
-            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()));
+            boxed_resolver.borrow().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 mut file = BufWriter::new(fs::File::create(&deps_filename)?);
@@ -762,7 +690,7 @@ pub fn prepare_outputs(
     sess: &Session,
     compiler: &Compiler,
     krate: &ast::Crate,
-    resolver: &Resolver<'_>,
+    boxed_resolver: &Steal<Rc<RefCell<BoxedResolver>>>,
     crate_name: &str,
 ) -> Result<OutputFilenames> {
     let _timer = sess.timer("prepare_outputs");
@@ -802,7 +730,7 @@ pub fn prepare_outputs(
         }
     }
 
-    write_out_deps(sess, resolver, &outputs, &output_paths);
+    write_out_deps(sess, boxed_resolver, &outputs, &output_paths);
 
     let only_dep_info = sess.opts.output_types.contains_key(&OutputType::DepInfo)
         && sess.opts.output_types.len() == 1;