33// SPDX-License-Identifier: MIT OR Apache-2.0
44
55use std:: any:: { Any , TypeId } ;
6- use std:: cell:: RefCell ;
76use std:: sync:: Arc ;
87
98use rusqlite:: { Connection , OptionalExtension } ;
109use rustc_data_structures:: fx:: FxHashMap ;
10+ use rustc_data_structures:: sync:: { DynSend , DynSync , MTLock , RwLock } ;
1111use rustc_hir:: def_id:: { CrateNum , LOCAL_CRATE } ;
1212use rustc_middle:: ty:: TyCtxt ;
1313use rustc_serialize:: { Decodable , Encodable } ;
@@ -18,8 +18,8 @@ use crate::preempt_count::UseSite;
1818pub ( crate ) trait Query : ' static {
1919 const NAME : & ' static str ;
2020
21- type Key < ' tcx > ;
22- type Value < ' tcx > ;
21+ type Key < ' tcx > : DynSend + DynSync ;
22+ type Value < ' tcx > : DynSend + DynSync ;
2323}
2424
2525pub ( crate ) trait QueryValueDecodable : Query {
@@ -50,13 +50,17 @@ pub(crate) trait PersistentQuery: QueryValueDecodable {
5050
5151pub struct AnalysisCtxt < ' tcx > {
5252 pub tcx : TyCtxt < ' tcx > ,
53- pub local_conn : Connection ,
54- pub sql_conn : RefCell < FxHashMap < CrateNum , Option < Arc < Connection > > > > ,
53+ pub local_conn : MTLock < Connection > ,
54+ pub sql_conn : RwLock < FxHashMap < CrateNum , Option < Arc < MTLock < Connection > > > > > ,
5555
56- pub call_stack : RefCell < Vec < UseSite < ' tcx > > > ,
57- pub query_cache : RefCell < FxHashMap < TypeId , Arc < dyn Any > > > ,
56+ pub call_stack : RwLock < Vec < UseSite < ' tcx > > > ,
57+ pub query_cache : RwLock < FxHashMap < TypeId , Arc < dyn Any + DynSend + DynSync > > > ,
5858}
5959
60+ // Everything in `AnalysisCtxt` is either `DynSend/DynSync` or `Send/Sync`, but since there're no relation between two right now compiler cannot infer this.
61+ unsafe impl < ' tcx > DynSend for AnalysisCtxt < ' tcx > { }
62+ unsafe impl < ' tcx > DynSync for AnalysisCtxt < ' tcx > { }
63+
6064impl < ' tcx > std:: ops:: Deref for AnalysisCtxt < ' tcx > {
6165 type Target = TyCtxt < ' tcx > ;
6266
@@ -105,7 +109,7 @@ const SCHEMA_VERSION: u32 = 1;
105109
106110impl Drop for AnalysisCtxt < ' _ > {
107111 fn drop ( & mut self ) {
108- self . local_conn . execute ( "commit" , ( ) ) . unwrap ( ) ;
112+ self . local_conn . lock ( ) . execute ( "commit" , ( ) ) . unwrap ( ) ;
109113 }
110114}
111115
@@ -127,26 +131,26 @@ impl ArcDowncast for Arc<dyn Any> {
127131impl < ' tcx > AnalysisCtxt < ' tcx > {
128132 pub ( crate ) fn query_cache < Q : Query > (
129133 & self ,
130- ) -> Arc < RefCell < FxHashMap < Q :: Key < ' tcx > , Q :: Value < ' tcx > > > > {
134+ ) -> Arc < RwLock < FxHashMap < Q :: Key < ' tcx > , Q :: Value < ' tcx > > > > {
131135 let key = TypeId :: of :: < Q > ( ) ;
132136 let mut guard = self . query_cache . borrow_mut ( ) ;
133- let cache = guard
137+ let cache = ( guard
134138 . entry ( key)
135139 . or_insert_with ( || {
136- let cache = Arc :: new ( RefCell :: new (
140+ let cache = Arc :: new ( RwLock :: new (
137141 FxHashMap :: < Q :: Key < ' static > , Q :: Value < ' static > > :: default ( ) ,
138142 ) ) ;
139143 cache
140144 } )
141- . clone ( )
142- . downcast :: < RefCell < FxHashMap < Q :: Key < ' static > , Q :: Value < ' static > > > > ( )
145+ . clone ( ) as Arc < dyn Any > )
146+ . downcast :: < RwLock < FxHashMap < Q :: Key < ' static > , Q :: Value < ' static > > > > ( )
143147 . unwrap ( ) ;
144148 // Everything stored inside query_cache is conceptually `'tcx`, but due to limitation
145149 // of `Any` we hack around the lifetime.
146150 unsafe { std:: mem:: transmute ( cache) }
147151 }
148152
149- pub ( crate ) fn sql_connection ( & self , cnum : CrateNum ) -> Option < Arc < Connection > > {
153+ pub ( crate ) fn sql_connection ( & self , cnum : CrateNum ) -> Option < Arc < MTLock < Connection > > > {
150154 if let Some ( v) = self . sql_conn . borrow ( ) . get ( & cnum) {
151155 return v. clone ( ) ;
152156 }
@@ -187,7 +191,7 @@ impl<'tcx> AnalysisCtxt<'tcx> {
187191 ) ;
188192 }
189193
190- result = Some ( Arc :: new ( conn) ) ;
194+ result = Some ( Arc :: new ( MTLock :: new ( conn) ) ) ;
191195 break ;
192196 }
193197 }
@@ -205,6 +209,7 @@ impl<'tcx> AnalysisCtxt<'tcx> {
205209
206210 pub ( crate ) fn sql_create_table < Q : Query > ( & self ) {
207211 self . local_conn
212+ . lock ( )
208213 . execute_batch ( & format ! (
209214 "CREATE TABLE {} (key BLOB PRIMARY KEY, value BLOB);" ,
210215 Q :: NAME
@@ -225,6 +230,7 @@ impl<'tcx> AnalysisCtxt<'tcx> {
225230
226231 let value_encoded: Vec < u8 > = self
227232 . sql_connection ( cnum) ?
233+ . lock ( )
228234 . query_row (
229235 & format ! ( "SELECT value FROM {} WHERE key = ?" , Q :: NAME ) ,
230236 rusqlite:: params![ encoded] ,
@@ -265,6 +271,7 @@ impl<'tcx> AnalysisCtxt<'tcx> {
265271 let value_encoded = encode_ctx. finish ( ) ;
266272
267273 self . local_conn
274+ . lock ( )
268275 . execute (
269276 & format ! (
270277 "INSERT OR REPLACE INTO {} (key, value) VALUES (?, ?)" ,
@@ -309,7 +316,7 @@ impl<'tcx> AnalysisCtxt<'tcx> {
309316
310317 let ret = Self {
311318 tcx,
312- local_conn : conn,
319+ local_conn : MTLock :: new ( conn) ,
313320 sql_conn : Default :: default ( ) ,
314321 call_stack : Default :: default ( ) ,
315322 query_cache : Default :: default ( ) ,
0 commit comments