1
Fork 0

Use a submodule as safety boundary for BoxedResolver

This commit is contained in:
bjorn3 2021-06-01 10:49:42 +02:00
parent 86c2d1a2a7
commit 5e148200d4

View file

@ -86,66 +86,71 @@ fn count_nodes(krate: &ast::Crate) -> usize {
counter.count counter.count
} }
pub struct BoxedResolver(Pin<Box<BoxedResolverInner>>); pub use boxed_resolver::BoxedResolver;
mod boxed_resolver {
use super::*;
// Note: Drop order is important to prevent dangling references. Resolver must be dropped first, pub struct BoxedResolver(Pin<Box<BoxedResolverInner>>);
// 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 { // Note: Drop order is important to prevent dangling references. Resolver must be dropped first,
fn new<F>(session: Lrc<Session>, make_resolver: F) -> Result<(ast::Crate, Self)> // then resolver_arenas and finally session.
where // The drop order is defined to be from top to bottom in RFC1857, so there is no need for
F: for<'a> FnOnce( // ManuallyDrop for as long as the fields are not reordered.
&'a Session, struct BoxedResolverInner {
&'a ResolverArenas<'a>, resolver: Option<Resolver<'static>>,
) -> Result<(ast::Crate, Resolver<'a>)>, resolver_arenas: ResolverArenas<'static>,
{ session: Lrc<Session>,
let mut boxed_resolver = Box::new(BoxedResolverInner { _pin: PhantomPinned,
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 { impl BoxedResolver {
let mut resolver = unsafe { pub(super) fn new<F>(session: Lrc<Session>, make_resolver: F) -> Result<(ast::Crate, Self)>
self.0.as_mut().map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver) where
}; F: for<'a> FnOnce(
f((&mut *resolver).as_mut().unwrap()) &'a Session,
} &'a ResolverArenas<'a>,
) -> Result<(ast::Crate, Resolver<'a>)>,
pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ResolverOutputs { {
match Rc::try_unwrap(resolver) { let mut boxed_resolver = Box::new(BoxedResolverInner {
Ok(resolver) => { session,
let mut resolver = resolver.into_inner(); resolver_arenas: Resolver::arenas(),
let mut resolver = unsafe { resolver: None,
resolver _pin: PhantomPinned,
.0 });
.as_mut() unsafe {
.map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver) let (crate_, resolver) = make_resolver(
}; std::mem::transmute::<&Session, &Session>(&boxed_resolver.session),
resolver.take().unwrap().into_outputs() 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()),
} }
Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()),
} }
} }
} }