Skip to content

Commit 86c2d1a

Browse files
committed
Don't use a generator for BoxedResolver
The generator is non-trivial and requires unsafe code anyway. Using regular unsafe code without a generator is much easier to follow.
1 parent 36bdfdc commit 86c2d1a

File tree

2 files changed

+48
-119
lines changed

2 files changed

+48
-119
lines changed

compiler/rustc_interface/src/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
#![feature(box_patterns)]
33
#![feature(internal_output_capture)]
44
#![feature(nll)]
5-
#![feature(generator_trait)]
6-
#![feature(generators)]
75
#![feature(once_cell)]
86
#![recursion_limit = "256"]
97

compiler/rustc_interface/src/passes.rs

+48-117
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ use std::cell::RefCell;
4646
use std::ffi::OsString;
4747
use std::io::{self, BufWriter, Write};
4848
use std::lazy::SyncLazy;
49-
use std::marker::PhantomData;
50-
use std::ops::{Generator, GeneratorState};
49+
use std::marker::PhantomPinned;
5150
use std::path::PathBuf;
5251
use std::pin::Pin;
5352
use std::rc::Rc;
@@ -87,99 +86,64 @@ fn count_nodes(krate: &ast::Crate) -> usize {
8786
counter.count
8887
}
8988

90-
pub struct AccessAction(*mut dyn for<'a> FnMut(&mut Resolver<'a>));
91-
92-
impl AccessAction {
93-
pub fn get(self) -> *mut dyn for<'a> FnMut(&mut Resolver<'a>) {
94-
self.0
95-
}
96-
}
97-
98-
pub enum Action {
99-
Initial,
100-
Access(AccessAction),
101-
Complete,
102-
}
103-
104-
#[derive(PartialEq)]
105-
struct Marker<T>(PhantomData<T>);
106-
107-
impl<T> Marker<T> {
108-
unsafe fn new() -> Self {
109-
Marker(PhantomData)
110-
}
111-
}
112-
113-
enum YieldType<I, A> {
114-
Initial(I),
115-
Accessor(Marker<A>),
116-
}
117-
118-
pub struct BoxedResolver {
119-
generator: Pin<
120-
Box<
121-
dyn Generator<
122-
Action,
123-
Yield = YieldType<Result<ast::Crate>, for<'a> fn(&mut Resolver<'a>)>,
124-
Return = ResolverOutputs,
125-
>,
126-
>,
127-
>,
89+
pub struct BoxedResolver(Pin<Box<BoxedResolverInner>>);
90+
91+
// Note: Drop order is important to prevent dangling references. Resolver must be dropped first,
92+
// then resolver_arenas and finally session.
93+
// The drop order is defined to be from top to bottom in RFC1857, so there is no need for
94+
// ManuallyDrop for as long as the fields are not reordered.
95+
struct BoxedResolverInner {
96+
resolver: Option<Resolver<'static>>,
97+
resolver_arenas: ResolverArenas<'static>,
98+
session: Lrc<Session>,
99+
_pin: PhantomPinned,
128100
}
129101

130102
impl BoxedResolver {
131-
fn new<T>(generator: T) -> Result<(ast::Crate, Self)>
103+
fn new<F>(session: Lrc<Session>, make_resolver: F) -> Result<(ast::Crate, Self)>
132104
where
133-
T: ::std::ops::Generator<
134-
Action,
135-
Yield = YieldType<Result<ast::Crate>, fn(&mut Resolver<'_>)>,
136-
Return = ResolverOutputs,
137-
> + 'static,
105+
F: for<'a> FnOnce(
106+
&'a Session,
107+
&'a ResolverArenas<'a>,
108+
) -> Result<(ast::Crate, Resolver<'a>)>,
138109
{
139-
let mut generator = Box::pin(generator);
140-
141-
// Run it to the first yield to set it up
142-
let init = match generator.as_mut().resume(Action::Initial) {
143-
GeneratorState::Yielded(YieldType::Initial(y)) => y,
144-
_ => panic!(),
145-
};
146-
147-
init.map(|init| (init, BoxedResolver { generator }))
110+
let mut boxed_resolver = Box::new(BoxedResolverInner {
111+
session,
112+
resolver_arenas: Resolver::arenas(),
113+
resolver: None,
114+
_pin: PhantomPinned,
115+
});
116+
unsafe {
117+
let (crate_, resolver) = make_resolver(
118+
std::mem::transmute::<&Session, &Session>(&boxed_resolver.session),
119+
std::mem::transmute::<&ResolverArenas<'_>, &ResolverArenas<'_>>(
120+
&boxed_resolver.resolver_arenas,
121+
),
122+
)?;
123+
boxed_resolver.resolver =
124+
Some(std::mem::transmute::<Resolver<'_>, Resolver<'_>>(resolver));
125+
Ok((crate_, BoxedResolver(Pin::new_unchecked(boxed_resolver))))
126+
}
148127
}
149128

150129
pub fn access<F: for<'a> FnOnce(&mut Resolver<'a>) -> R, R>(&mut self, f: F) -> R {
151-
// Turn the FnOnce closure into *mut dyn FnMut()
152-
// so we can pass it in to the generator
153-
let mut r = None;
154-
let mut f = Some(f);
155-
let mut_f: &mut dyn for<'a> FnMut(&mut Resolver<'a>) = &mut |resolver| {
156-
let f = f.take().unwrap();
157-
r = Some(f(resolver));
130+
let mut resolver = unsafe {
131+
self.0.as_mut().map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver)
158132
};
159-
let mut_f = mut_f as *mut dyn for<'a> FnMut(&mut Resolver<'a>);
160-
161-
// Get the generator to call our closure
162-
unsafe {
163-
// Call the generator, which in turn will call the closure
164-
if let GeneratorState::Complete(_) = self
165-
.generator
166-
.as_mut()
167-
.resume(Action::Access(AccessAction(::std::mem::transmute(mut_f))))
168-
{
169-
panic!()
170-
}
171-
}
172-
173-
// Unwrap the result
174-
r.unwrap()
133+
f((&mut *resolver).as_mut().unwrap())
175134
}
176135

177136
pub fn to_resolver_outputs(resolver: Rc<RefCell<BoxedResolver>>) -> ResolverOutputs {
178137
match Rc::try_unwrap(resolver) {
179138
Ok(resolver) => {
180-
// Tell the generator we want it to complete, consuming it and yielding a result
181-
let result = resolver.into_inner().generator.as_mut().resume(Action::Complete);
182-
if let GeneratorState::Complete(r) = result { r } else { panic!() }
139+
let mut resolver = resolver.into_inner();
140+
let mut resolver = unsafe {
141+
resolver
142+
.0
143+
.as_mut()
144+
.map_unchecked_mut(|boxed_resolver| &mut boxed_resolver.resolver)
145+
};
146+
resolver.take().unwrap().into_outputs()
183147
}
184148
Err(resolver) => resolver.borrow_mut().access(|resolver| resolver.clone_outputs()),
185149
}
@@ -206,48 +170,15 @@ pub fn configure_and_expand(
206170
// its contents but the results of name resolution on those contents. Hopefully we'll push
207171
// this back at some point.
208172
let crate_name = crate_name.to_string();
209-
BoxedResolver::new(static move |mut action| {
210-
let _ = action;
211-
let sess = &*sess;
212-
let resolver_arenas = Resolver::arenas();
213-
let res = configure_and_expand_inner(
173+
BoxedResolver::new(sess, move |sess, resolver_arenas| {
174+
configure_and_expand_inner(
214175
sess,
215176
&lint_store,
216177
krate,
217178
&crate_name,
218179
&resolver_arenas,
219180
metadata_loader,
220-
);
221-
let mut resolver = match res {
222-
Err(v) => {
223-
yield YieldType::Initial(Err(v));
224-
panic!()
225-
}
226-
Ok((krate, resolver)) => {
227-
action = yield YieldType::Initial(Ok(krate));
228-
resolver
229-
}
230-
};
231-
232-
loop {
233-
match action {
234-
Action::Access(accessor) => {
235-
let accessor: &mut dyn FnMut(&mut Resolver<'_>) =
236-
unsafe { ::std::mem::transmute(accessor.get()) };
237-
(*accessor)(&mut resolver);
238-
unsafe {
239-
let marker = Marker::<fn(&mut Resolver<'_>)>::new();
240-
action = yield YieldType::Accessor(marker);
241-
};
242-
}
243-
Action::Complete => break,
244-
Action::Initial => {
245-
panic!("unexpected box_region action: Initial")
246-
}
247-
}
248-
}
249-
250-
resolver.into_outputs()
181+
)
251182
})
252183
}
253184

0 commit comments

Comments
 (0)