@@ -5,6 +5,7 @@ use crate::passes::{self, BoxedResolver, QueryContext};
55use rustc_ast as ast;
66use rustc_codegen_ssa:: traits:: CodegenBackend ;
77use rustc_codegen_ssa:: CodegenResults ;
8+ use rustc_data_structures:: steal:: Steal ;
89use rustc_data_structures:: svh:: Svh ;
910use rustc_data_structures:: sync:: { Lrc , OnceCell , WorkerLocal } ;
1011use rustc_hir:: def_id:: LOCAL_CRATE ;
@@ -19,43 +20,53 @@ use rustc_session::{output::find_crate_name, Session};
1920use rustc_span:: symbol:: sym;
2021use rustc_span:: Symbol ;
2122use std:: any:: Any ;
22- use std:: cell:: { Ref , RefCell , RefMut } ;
23+ use std:: cell:: { RefCell , RefMut } ;
2324use std:: rc:: Rc ;
2425use std:: sync:: Arc ;
2526
2627/// Represent the result of a query.
2728///
28- /// This result can be stolen 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.
2930///
30- /// [`take `]: Self::take
31+ /// [`steal `]: Steal::steal
3132/// [`compute`]: Self::compute
3233pub struct Query < T > {
33- result : RefCell < Option < Result < T > > > ,
34+ /// `None` means no value has been computed yet.
35+ result : RefCell < Option < Result < Steal < T > > > > ,
3436}
3537
3638impl < T > Query < T > {
37- fn compute < F : FnOnce ( ) -> Result < T > > ( & self , f : F ) -> Result < & Query < T > > {
38- self . result . borrow_mut ( ) . get_or_insert_with ( f) . as_ref ( ) . map ( |_| self ) . map_err ( |& err| err)
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 )
3948 }
49+ }
50+
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 > > ;
4055
41- /// Takes ownership of the query result. Further attempts to take or peek the query
42- /// result will panic unless it is generated by calling the `compute` method.
43- pub fn take ( & self ) -> T {
44- self . result . borrow_mut ( ) . take ( ) . expect ( "missing query result" ) . unwrap ( )
56+ fn deref ( & self ) -> & Self :: Target {
57+ & self . 0
4558 }
59+ }
4660
47- /// Borrows the query result using the RefCell. Panics if the result is stolen.
48- pub fn peek ( & self ) -> Ref < ' _ , T > {
49- Ref :: map ( self . result . borrow ( ) , |r| {
50- r. as_ref ( ) . unwrap ( ) . as_ref ( ) . expect ( "missing query result" )
51- } )
61+ impl < ' a , T > std:: ops:: DerefMut for QueryResult < ' a , T > {
62+ fn deref_mut ( & mut self ) -> & mut Self :: Target {
63+ & mut self . 0
5264 }
65+ }
5366
54- /// Mutably borrows the query result using the RefCell. Panics if the result is stolen.
55- pub fn peek_mut ( & self ) -> RefMut < ' _ , T > {
56- RefMut :: map ( self . result . borrow_mut ( ) , |r| {
57- r. as_mut ( ) . unwrap ( ) . as_mut ( ) . expect ( "missing query result" )
58- } )
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)
5970 }
6071}
6172
@@ -111,24 +122,24 @@ impl<'tcx> Queries<'tcx> {
111122 self . compiler . codegen_backend ( )
112123 }
113124
114- fn dep_graph_future ( & self ) -> Result < & Query < Option < DepGraphFuture > > > {
125+ fn dep_graph_future ( & self ) -> Result < QueryResult < ' _ , Option < DepGraphFuture > > > {
115126 self . dep_graph_future . compute ( || {
116127 let sess = self . session ( ) ;
117128 Ok ( sess. opts . build_dep_graph ( ) . then ( || rustc_incremental:: load_dep_graph ( sess) ) )
118129 } )
119130 }
120131
121- pub fn parse ( & self ) -> Result < & Query < ast:: Crate > > {
132+ pub fn parse ( & self ) -> Result < QueryResult < ' _ , ast:: Crate > > {
122133 self . parse . compute ( || {
123134 passes:: parse ( self . session ( ) , & self . compiler . input )
124135 . map_err ( |mut parse_error| parse_error. emit ( ) )
125136 } )
126137 }
127138
128- pub fn register_plugins ( & self ) -> Result < & Query < ( ast:: Crate , Lrc < LintStore > ) > > {
139+ pub fn register_plugins ( & self ) -> Result < QueryResult < ' _ , ( ast:: Crate , Lrc < LintStore > ) > > {
129140 self . register_plugins . compute ( || {
130- let crate_name = * self . crate_name ( ) ?. peek ( ) ;
131- let krate = self . parse ( ) ?. take ( ) ;
141+ let crate_name = * self . crate_name ( ) ?. borrow ( ) ;
142+ let krate = self . parse ( ) ?. steal ( ) ;
132143
133144 let empty: & ( dyn Fn ( & Session , & mut LintStore ) + Sync + Send ) = & |_, _| { } ;
134145 let ( krate, lint_store) = passes:: register_plugins (
@@ -150,11 +161,11 @@ impl<'tcx> Queries<'tcx> {
150161 } )
151162 }
152163
153- pub fn crate_name ( & self ) -> Result < & Query < Symbol > > {
164+ pub fn crate_name ( & self ) -> Result < QueryResult < ' _ , Symbol > > {
154165 self . crate_name . compute ( || {
155166 Ok ( {
156167 let parse_result = self . parse ( ) ?;
157- let krate = parse_result. peek ( ) ;
168+ let krate = parse_result. borrow ( ) ;
158169 // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
159170 find_crate_name ( self . session ( ) , & krate. attrs , & self . compiler . input )
160171 } )
@@ -163,11 +174,12 @@ impl<'tcx> Queries<'tcx> {
163174
164175 pub fn expansion (
165176 & self ,
166- ) -> Result < & Query < ( Lrc < ast:: Crate > , Rc < RefCell < BoxedResolver > > , Lrc < LintStore > ) > > {
177+ ) -> Result < QueryResult < ' _ , ( Lrc < ast:: Crate > , Rc < RefCell < BoxedResolver > > , Lrc < LintStore > ) > >
178+ {
167179 trace ! ( "expansion" ) ;
168180 self . expansion . compute ( || {
169- let crate_name = * self . crate_name ( ) ?. peek ( ) ;
170- 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 ( ) ;
171183 let _timer = self . session ( ) . timer ( "configure_and_expand" ) ;
172184 let sess = self . session ( ) ;
173185 let mut resolver = passes:: create_resolver (
@@ -183,10 +195,10 @@ impl<'tcx> Queries<'tcx> {
183195 } )
184196 }
185197
186- fn dep_graph ( & self ) -> Result < & Query < DepGraph > > {
198+ fn dep_graph ( & self ) -> Result < QueryResult < ' _ , DepGraph > > {
187199 self . dep_graph . compute ( || {
188200 let sess = self . session ( ) ;
189- let future_opt = self . dep_graph_future ( ) ?. take ( ) ;
201+ let future_opt = self . dep_graph_future ( ) ?. steal ( ) ;
190202 let dep_graph = future_opt
191203 . and_then ( |future| {
192204 let ( prev_graph, prev_work_products) =
@@ -199,10 +211,11 @@ impl<'tcx> Queries<'tcx> {
199211 } )
200212 }
201213
202- pub fn prepare_outputs ( & self ) -> Result < & Query < OutputFilenames > > {
214+ pub fn prepare_outputs ( & self ) -> Result < QueryResult < ' _ , OutputFilenames > > {
203215 self . prepare_outputs . compute ( || {
204- let ( krate, boxed_resolver, _) = & * self . expansion ( ) ?. peek ( ) ;
205- 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 ( ) ;
206219 passes:: prepare_outputs (
207220 self . session ( ) ,
208221 self . compiler ,
@@ -213,12 +226,12 @@ impl<'tcx> Queries<'tcx> {
213226 } )
214227 }
215228
216- pub fn global_ctxt ( & ' tcx self ) -> Result < & Query < QueryContext < ' tcx > > > {
229+ pub fn global_ctxt ( & ' tcx self ) -> Result < QueryResult < ' _ , QueryContext < ' tcx > > > {
217230 self . global_ctxt . compute ( || {
218- let crate_name = * self . crate_name ( ) ?. peek ( ) ;
219- let outputs = self . prepare_outputs ( ) ?. take ( ) ;
220- let dep_graph = self . dep_graph ( ) ?. peek ( ) . clone ( ) ;
221- 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 ( ) ;
222235 Ok ( passes:: create_global_ctxt (
223236 self . compiler ,
224237 lint_store,
@@ -235,9 +248,9 @@ impl<'tcx> Queries<'tcx> {
235248 } )
236249 }
237250
238- pub fn ongoing_codegen ( & ' tcx self ) -> Result < & Query < Box < dyn Any > > > {
251+ pub fn ongoing_codegen ( & ' tcx self ) -> Result < QueryResult < ' _ , Box < dyn Any > > > {
239252 self . ongoing_codegen . compute ( || {
240- self . global_ctxt ( ) ?. peek_mut ( ) . enter ( |tcx| {
253+ self . global_ctxt ( ) ?. enter ( |tcx| {
241254 tcx. analysis ( ( ) ) . ok ( ) ;
242255
243256 // Don't do code generation if there were any errors
@@ -293,12 +306,10 @@ impl<'tcx> Queries<'tcx> {
293306 let sess = self . session ( ) . clone ( ) ;
294307 let codegen_backend = self . codegen_backend ( ) . clone ( ) ;
295308
296- let dep_graph = self . dep_graph ( ) ?. peek ( ) . clone ( ) ;
297- let ( crate_hash, prepare_outputs) = self
298- . global_ctxt ( ) ?
299- . peek_mut ( )
300- . enter ( |tcx| ( tcx. crate_hash ( LOCAL_CRATE ) , tcx. output_filenames ( ( ) ) . clone ( ) ) ) ;
301- let ongoing_codegen = self . ongoing_codegen ( ) ?. take ( ) ;
309+ let ( crate_hash, prepare_outputs, dep_graph) = self . global_ctxt ( ) ?. enter ( |tcx| {
310+ ( tcx. crate_hash ( LOCAL_CRATE ) , tcx. output_filenames ( ( ) ) . clone ( ) , tcx. dep_graph . clone ( ) )
311+ } ) ;
312+ let ongoing_codegen = self . ongoing_codegen ( ) ?. steal ( ) ;
302313
303314 Ok ( Linker {
304315 sess,
@@ -382,6 +393,7 @@ impl Compiler {
382393 // NOTE: intentionally does not compute the global context if it hasn't been built yet,
383394 // since that likely means there was a parse error.
384395 if let Some ( Ok ( gcx) ) = & mut * queries. global_ctxt . result . borrow_mut ( ) {
396+ let gcx = gcx. get_mut ( ) ;
385397 // We assume that no queries are run past here. If there are new queries
386398 // after this point, they'll show up as "<unknown>" in self-profiling data.
387399 {
0 commit comments