Use a submodule as safety boundary for BoxedResolver
This commit is contained in:
parent
86c2d1a2a7
commit
5e148200d4
1 changed files with 60 additions and 55 deletions
|
@ -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()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue