Skip to content

Commit 50587b0

Browse files
committed
Prefer an enum over Option<Option<Result<T>>>
1 parent 26ffca2 commit 50587b0

File tree

1 file changed

+28
-37
lines changed

1 file changed

+28
-37
lines changed

compiler/rustc_interface/src/queries.rs

Lines changed: 28 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -30,66 +30,57 @@ use std::sync::Arc;
3030
/// [`take`]: Self::take
3131
/// [`compute`]: Self::compute
3232
pub struct Query<T> {
33-
// The outer option is `None` until the query is computed.
34-
// Then the whole thing becomes `Some(Some(result))`.
35-
// Once the value gets taken/stolen, it is `Some(None)`.
36-
result: RefCell<Option<Option<Result<T>>>>,
33+
result: RefCell<Result<State<T>>>,
34+
}
35+
36+
enum State<T> {
37+
NotComputedYet,
38+
Computed(T),
39+
Stolen,
3740
}
3841

3942
impl<T> Query<T> {
4043
fn compute<F: FnOnce() -> Result<T>>(&self, f: F) -> Result<&Query<T>> {
41-
self.result
42-
.borrow_mut()
43-
.get_or_insert_with(|| Some(f()))
44-
.as_ref()
45-
.expect("query already taken")
46-
.as_ref()
47-
.map(|_| self)
48-
.map_err(|&err| err)
44+
let mut result = self.result.borrow_mut();
45+
if matches!(*result, Ok(State::NotComputedYet)) {
46+
*result = f().map(State::Computed);
47+
}
48+
result.as_ref().map(|_| self).map_err(|e| *e)
4949
}
5050

5151
/// Takes ownership of the query result. Further attempts to take or peek the query
5252
/// result will panic unless it is generated by calling the `compute` method.
5353
pub fn take(&self) -> T {
54-
self.result
55-
.borrow_mut()
56-
.as_mut()
57-
.expect("query never computed")
58-
.take()
59-
.expect("query already taken")
60-
.unwrap()
54+
match std::mem::replace(&mut *self.result.borrow_mut(), Ok(State::Stolen)).unwrap() {
55+
State::NotComputedYet => panic!("query never computed"),
56+
State::Computed(val) => val,
57+
State::Stolen => panic!("query already taken"),
58+
}
6159
}
6260

6361
/// Borrows the query result using the RefCell. Panics if the result is stolen.
6462
pub fn peek(&self) -> Ref<'_, T> {
65-
Ref::map(self.result.borrow(), |r| {
66-
r.as_ref()
67-
.unwrap()
68-
.as_ref()
69-
.expect("query never computed")
70-
.as_ref()
71-
.expect("query already taken")
63+
Ref::map(self.result.borrow(), |r| match r.as_ref().unwrap() {
64+
State::NotComputedYet => panic!("query never computed"),
65+
State::Computed(val) => val,
66+
State::Stolen => panic!("query already taken"),
7267
})
7368
}
7469
}
7570

7671
impl<'tcx> Query<QueryContext<'tcx>> {
7772
pub fn enter<T>(&self, f: impl FnOnce(TyCtxt<'tcx>) -> T) -> T {
78-
self.result
79-
.borrow_mut()
80-
.as_mut()
81-
.unwrap()
82-
.as_mut()
83-
.expect("query never computed")
84-
.as_mut()
85-
.expect("query already taken")
86-
.enter(f)
73+
match self.result.borrow_mut().as_mut().unwrap() {
74+
State::NotComputedYet => panic!("query never computed"),
75+
State::Computed(qcx) => qcx.enter(f),
76+
State::Stolen => panic!("query already taken"),
77+
}
8778
}
8879
}
8980

9081
impl<T> Default for Query<T> {
9182
fn default() -> Self {
92-
Query { result: RefCell::new(None) }
83+
Query { result: RefCell::new(Ok(State::NotComputedYet)) }
9384
}
9485
}
9586

@@ -407,7 +398,7 @@ impl Compiler {
407398

408399
// NOTE: intentionally does not compute the global context if it hasn't been built yet,
409400
// since that likely means there was a parse error.
410-
if let Some(Some(Ok(gcx))) = &mut *queries.global_ctxt.result.borrow_mut() {
401+
if let Ok(State::Computed(gcx)) = &mut *queries.global_ctxt.result.borrow_mut() {
411402
// We assume that no queries are run past here. If there are new queries
412403
// after this point, they'll show up as "<unknown>" in self-profiling data.
413404
{

0 commit comments

Comments
 (0)