@@ -30,66 +30,57 @@ use std::sync::Arc;
30
30
/// [`take`]: Self::take
31
31
/// [`compute`]: Self::compute
32
32
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 ,
37
40
}
38
41
39
42
impl < T > Query < T > {
40
43
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)
49
49
}
50
50
51
51
/// Takes ownership of the query result. Further attempts to take or peek the query
52
52
/// result will panic unless it is generated by calling the `compute` method.
53
53
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
+ }
61
59
}
62
60
63
61
/// Borrows the query result using the RefCell. Panics if the result is stolen.
64
62
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" ) ,
72
67
} )
73
68
}
74
69
}
75
70
76
71
impl < ' tcx > Query < QueryContext < ' tcx > > {
77
72
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
+ }
87
78
}
88
79
}
89
80
90
81
impl < T > Default for Query < T > {
91
82
fn default ( ) -> Self {
92
- Query { result : RefCell :: new ( None ) }
83
+ Query { result : RefCell :: new ( Ok ( State :: NotComputedYet ) ) }
93
84
}
94
85
}
95
86
@@ -407,7 +398,7 @@ impl Compiler {
407
398
408
399
// NOTE: intentionally does not compute the global context if it hasn't been built yet,
409
400
// 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 ( ) {
411
402
// We assume that no queries are run past here. If there are new queries
412
403
// after this point, they'll show up as "<unknown>" in self-profiling data.
413
404
{
0 commit comments