@@ -5,6 +5,7 @@ use crate::passes::{self, BoxedResolver, QueryContext};
5
5
use rustc_ast as ast;
6
6
use rustc_codegen_ssa:: traits:: CodegenBackend ;
7
7
use rustc_codegen_ssa:: CodegenResults ;
8
+ use rustc_data_structures:: steal:: Steal ;
8
9
use rustc_data_structures:: svh:: Svh ;
9
10
use rustc_data_structures:: sync:: { Lrc , OnceCell , WorkerLocal } ;
10
11
use rustc_hir:: def_id:: LOCAL_CRATE ;
@@ -19,68 +20,59 @@ use rustc_session::{output::find_crate_name, Session};
19
20
use rustc_span:: symbol:: sym;
20
21
use rustc_span:: Symbol ;
21
22
use std:: any:: Any ;
22
- use std:: cell:: { Ref , RefCell } ;
23
+ use std:: cell:: { RefCell , RefMut } ;
23
24
use std:: rc:: Rc ;
24
25
use std:: sync:: Arc ;
25
26
26
27
/// Represent the result of a query.
27
28
///
28
- /// This result can be stolen once with the [`take `] method and generated with the [`compute`] method.
29
+ /// This result can be stolen once with the [`steal `] method and generated with the [`compute`] method.
29
30
///
30
- /// [`take `]: Self::take
31
+ /// [`steal `]: Steal::steal
31
32
/// [`compute`]: Self::compute
32
33
pub struct Query < T > {
33
- result : RefCell < Result < State < T > > > ,
34
- }
35
-
36
- enum State < T > {
37
- NotComputedYet ,
38
- Computed ( T ) ,
39
- Stolen ,
34
+ /// `None` means no value has been computed yet.
35
+ result : RefCell < Option < Result < Steal < T > > > > ,
40
36
}
41
37
42
38
impl < T > Query < T > {
43
- fn compute < F : FnOnce ( ) -> Result < T > > ( & self , f : F ) -> Result < & Query < T > > {
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)
39
+ fn compute < F : FnOnce ( ) -> Result < T > > ( & self , f : F ) -> Result < QueryResult < ' _ , T > > {
40
+ RefMut :: filter_map (
41
+ self . result . borrow_mut ( ) ,
42
+ |r : & mut Option < Result < Steal < T > > > | -> Option < & mut Steal < T > > {
43
+ r. get_or_insert_with ( || f ( ) . map ( Steal :: new) ) . as_mut ( ) . ok ( )
44
+ } ,
45
+ )
46
+ . map_err ( |r| * r. as_ref ( ) . unwrap ( ) . as_ref ( ) . map ( |_| ( ) ) . unwrap_err ( ) )
47
+ . map ( QueryResult )
49
48
}
49
+ }
50
50
51
- /// Takes ownership of the query result. Further attempts to take or peek the query
52
- /// result will panic unless it is generated by calling the `compute` method.
53
- pub fn take ( & self ) -> T {
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
- }
51
+ pub struct QueryResult < ' a , T > ( RefMut < ' a , Steal < T > > ) ;
52
+
53
+ impl < ' a , T > std:: ops:: Deref for QueryResult < ' a , T > {
54
+ type Target = RefMut < ' a , Steal < T > > ;
55
+
56
+ fn deref ( & self ) -> & Self :: Target {
57
+ & self . 0
59
58
}
59
+ }
60
60
61
- /// Borrows the query result using the RefCell. Panics if the result is stolen.
62
- pub fn peek ( & self ) -> Ref < ' _ , T > {
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" ) ,
67
- } )
61
+ impl < ' a , T > std:: ops:: DerefMut for QueryResult < ' a , T > {
62
+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
63
+ & mut self . 0
68
64
}
69
65
}
70
66
71
- impl < ' tcx > Query < QueryContext < ' tcx > > {
72
- pub fn enter < T > ( & self , f : impl FnOnce ( TyCtxt < ' tcx > ) -> T ) -> T {
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
- }
67
+ impl < ' a , ' tcx > QueryResult < ' a , QueryContext < ' tcx > > {
68
+ pub fn enter < T > ( mut self , f : impl FnOnce ( TyCtxt < ' tcx > ) -> T ) -> T {
69
+ ( * self . 0 ) . get_mut ( ) . enter ( f)
78
70
}
79
71
}
80
72
81
73
impl < T > Default for Query < T > {
82
74
fn default ( ) -> Self {
83
- Query { result : RefCell :: new ( Ok ( State :: NotComputedYet ) ) }
75
+ Query { result : RefCell :: new ( None ) }
84
76
}
85
77
}
86
78
@@ -130,24 +122,24 @@ impl<'tcx> Queries<'tcx> {
130
122
self . compiler . codegen_backend ( )
131
123
}
132
124
133
- fn dep_graph_future ( & self ) -> Result < & Query < Option < DepGraphFuture > > > {
125
+ fn dep_graph_future ( & self ) -> Result < QueryResult < ' _ , Option < DepGraphFuture > > > {
134
126
self . dep_graph_future . compute ( || {
135
127
let sess = self . session ( ) ;
136
128
Ok ( sess. opts . build_dep_graph ( ) . then ( || rustc_incremental:: load_dep_graph ( sess) ) )
137
129
} )
138
130
}
139
131
140
- pub fn parse ( & self ) -> Result < & Query < ast:: Crate > > {
132
+ pub fn parse ( & self ) -> Result < QueryResult < ' _ , ast:: Crate > > {
141
133
self . parse . compute ( || {
142
134
passes:: parse ( self . session ( ) , & self . compiler . input )
143
135
. map_err ( |mut parse_error| parse_error. emit ( ) )
144
136
} )
145
137
}
146
138
147
- pub fn register_plugins ( & self ) -> Result < & Query < ( ast:: Crate , Lrc < LintStore > ) > > {
139
+ pub fn register_plugins ( & self ) -> Result < QueryResult < ' _ , ( ast:: Crate , Lrc < LintStore > ) > > {
148
140
self . register_plugins . compute ( || {
149
- let crate_name = self . crate_name ( ) ?. peek ( ) . clone ( ) ;
150
- let krate = self . parse ( ) ?. take ( ) ;
141
+ let crate_name = self . crate_name ( ) ?. borrow ( ) . clone ( ) ;
142
+ let krate = self . parse ( ) ?. steal ( ) ;
151
143
152
144
let empty: & ( dyn Fn ( & Session , & mut LintStore ) + Sync + Send ) = & |_, _| { } ;
153
145
let ( krate, lint_store) = passes:: register_plugins (
@@ -169,11 +161,11 @@ impl<'tcx> Queries<'tcx> {
169
161
} )
170
162
}
171
163
172
- pub fn crate_name ( & self ) -> Result < & Query < Symbol > > {
164
+ pub fn crate_name ( & self ) -> Result < QueryResult < ' _ , Symbol > > {
173
165
self . crate_name . compute ( || {
174
166
Ok ( {
175
167
let parse_result = self . parse ( ) ?;
176
- let krate = parse_result. peek ( ) ;
168
+ let krate = parse_result. borrow ( ) ;
177
169
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
178
170
find_crate_name ( self . session ( ) , & krate. attrs , & self . compiler . input )
179
171
} )
@@ -182,11 +174,12 @@ impl<'tcx> Queries<'tcx> {
182
174
183
175
pub fn expansion (
184
176
& self ,
185
- ) -> Result < & Query < ( Lrc < ast:: Crate > , Rc < RefCell < BoxedResolver > > , Lrc < LintStore > ) > > {
177
+ ) -> Result < QueryResult < ' _ , ( Lrc < ast:: Crate > , Rc < RefCell < BoxedResolver > > , Lrc < LintStore > ) > >
178
+ {
186
179
trace ! ( "expansion" ) ;
187
180
self . expansion . compute ( || {
188
- let crate_name = * self . crate_name ( ) ?. peek ( ) ;
189
- let ( krate, lint_store) = self . register_plugins ( ) ?. take ( ) ;
181
+ let crate_name = * self . crate_name ( ) ?. borrow ( ) ;
182
+ let ( krate, lint_store) = self . register_plugins ( ) ?. steal ( ) ;
190
183
let _timer = self . session ( ) . timer ( "configure_and_expand" ) ;
191
184
let sess = self . session ( ) ;
192
185
let mut resolver = passes:: create_resolver (
@@ -202,10 +195,10 @@ impl<'tcx> Queries<'tcx> {
202
195
} )
203
196
}
204
197
205
- fn dep_graph ( & self ) -> Result < & Query < DepGraph > > {
198
+ fn dep_graph ( & self ) -> Result < QueryResult < ' _ , DepGraph > > {
206
199
self . dep_graph . compute ( || {
207
200
let sess = self . session ( ) ;
208
- let future_opt = self . dep_graph_future ( ) ?. take ( ) ;
201
+ let future_opt = self . dep_graph_future ( ) ?. steal ( ) ;
209
202
let dep_graph = future_opt
210
203
. and_then ( |future| {
211
204
let ( prev_graph, prev_work_products) =
@@ -218,10 +211,11 @@ impl<'tcx> Queries<'tcx> {
218
211
} )
219
212
}
220
213
221
- pub fn prepare_outputs ( & self ) -> Result < & Query < OutputFilenames > > {
214
+ pub fn prepare_outputs ( & self ) -> Result < QueryResult < ' _ , OutputFilenames > > {
222
215
self . prepare_outputs . compute ( || {
223
- let ( krate, boxed_resolver, _) = & * self . expansion ( ) ?. peek ( ) ;
224
- let crate_name = * self . crate_name ( ) ?. peek ( ) ;
216
+ let expansion = self . expansion ( ) ?;
217
+ let ( krate, boxed_resolver, _) = & * expansion. borrow ( ) ;
218
+ let crate_name = * self . crate_name ( ) ?. borrow ( ) ;
225
219
passes:: prepare_outputs (
226
220
self . session ( ) ,
227
221
self . compiler ,
@@ -232,12 +226,12 @@ impl<'tcx> Queries<'tcx> {
232
226
} )
233
227
}
234
228
235
- pub fn global_ctxt ( & ' tcx self ) -> Result < & Query < QueryContext < ' tcx > > > {
229
+ pub fn global_ctxt ( & ' tcx self ) -> Result < QueryResult < ' _ , QueryContext < ' tcx > > > {
236
230
self . global_ctxt . compute ( || {
237
- let crate_name = * self . crate_name ( ) ?. peek ( ) ;
238
- let outputs = self . prepare_outputs ( ) ?. take ( ) ;
239
- let dep_graph = self . dep_graph ( ) ?. peek ( ) . clone ( ) ;
240
- let ( krate, resolver, lint_store) = self . expansion ( ) ?. take ( ) ;
231
+ let crate_name = * self . crate_name ( ) ?. borrow ( ) ;
232
+ let outputs = self . prepare_outputs ( ) ?. steal ( ) ;
233
+ let dep_graph = self . dep_graph ( ) ?. borrow ( ) . clone ( ) ;
234
+ let ( krate, resolver, lint_store) = self . expansion ( ) ?. steal ( ) ;
241
235
Ok ( passes:: create_global_ctxt (
242
236
self . compiler ,
243
237
lint_store,
@@ -254,7 +248,7 @@ impl<'tcx> Queries<'tcx> {
254
248
} )
255
249
}
256
250
257
- pub fn ongoing_codegen ( & ' tcx self ) -> Result < & Query < Box < dyn Any > > > {
251
+ pub fn ongoing_codegen ( & ' tcx self ) -> Result < QueryResult < ' _ , Box < dyn Any > > > {
258
252
self . ongoing_codegen . compute ( || {
259
253
self . global_ctxt ( ) ?. enter ( |tcx| {
260
254
tcx. analysis ( ( ) ) . ok ( ) ;
@@ -315,7 +309,7 @@ impl<'tcx> Queries<'tcx> {
315
309
let ( crate_hash, prepare_outputs, dep_graph) = self . global_ctxt ( ) ?. enter ( |tcx| {
316
310
( tcx. crate_hash ( LOCAL_CRATE ) , tcx. output_filenames ( ( ) ) . clone ( ) , tcx. dep_graph . clone ( ) )
317
311
} ) ;
318
- let ongoing_codegen = self . ongoing_codegen ( ) ?. take ( ) ;
312
+ let ongoing_codegen = self . ongoing_codegen ( ) ?. steal ( ) ;
319
313
320
314
Ok ( Linker {
321
315
sess,
@@ -398,7 +392,8 @@ impl Compiler {
398
392
399
393
// NOTE: intentionally does not compute the global context if it hasn't been built yet,
400
394
// since that likely means there was a parse error.
401
- if let Ok ( State :: Computed ( gcx) ) = & mut * queries. global_ctxt . result . borrow_mut ( ) {
395
+ if let Some ( Ok ( gcx) ) = & mut * queries. global_ctxt . result . borrow_mut ( ) {
396
+ let gcx = gcx. get_mut ( ) ;
402
397
// We assume that no queries are run past here. If there are new queries
403
398
// after this point, they'll show up as "<unknown>" in self-profiling data.
404
399
{
0 commit comments