@@ -19,7 +19,6 @@ use std::sync::{Arc, Mutex, MutexGuard};
19
19
20
20
use crate :: dag:: { Dag , DagLike } ;
21
21
22
- use super :: bound_mutex:: BoundMutex ;
23
22
use super :: { Bound , CompleteBound , Error , Final , Type } ;
24
23
25
24
/// Type inference context, or handle to a context.
@@ -60,9 +59,13 @@ impl Context {
60
59
61
60
/// Helper function to allocate a bound and return a reference to it.
62
61
fn alloc_bound ( & self , bound : Bound ) -> BoundRef {
62
+ let mut lock = self . lock ( ) ;
63
+ lock. slab . push ( bound) ;
64
+ let index = lock. slab . len ( ) - 1 ;
65
+
63
66
BoundRef {
64
67
context : Arc :: as_ptr ( & self . slab ) ,
65
- index : Arc :: new ( BoundMutex :: new ( bound ) ) ,
68
+ index,
66
69
}
67
70
}
68
71
@@ -132,7 +135,8 @@ impl Context {
132
135
/// Panics if passed a `BoundRef` that was not allocated by this context.
133
136
pub fn get ( & self , bound : & BoundRef ) -> Bound {
134
137
bound. assert_matches_context ( self ) ;
135
- bound. index . get ( ) . shallow_clone ( )
138
+ let lock = self . lock ( ) ;
139
+ lock. slab [ bound. index ] . shallow_clone ( )
136
140
}
137
141
138
142
/// Reassigns a bound to a different bound.
@@ -147,8 +151,8 @@ impl Context {
147
151
///
148
152
/// Also panics if passed a `BoundRef` that was not allocated by this context.
149
153
pub fn reassign_non_complete ( & self , bound : BoundRef , new : Bound ) {
150
- bound . assert_matches_context ( self ) ;
151
- bound . index . set ( new)
154
+ let mut lock = self . lock ( ) ;
155
+ lock . reassign_non_complete ( bound , new) ;
152
156
}
153
157
154
158
/// Binds the type to a given bound. If this fails, attach the provided
@@ -157,15 +161,15 @@ impl Context {
157
161
/// Fails if the type has an existing incompatible bound.
158
162
pub fn bind ( & self , existing : & Type , new : Bound , hint : & ' static str ) -> Result < ( ) , Error > {
159
163
let existing_root = existing. bound . root ( ) ;
160
- let lock = self . lock ( ) ;
164
+ let mut lock = self . lock ( ) ;
161
165
lock. bind ( existing_root, new, hint)
162
166
}
163
167
164
168
/// Unify the type with another one.
165
169
///
166
170
/// Fails if the bounds on the two types are incompatible
167
171
pub fn unify ( & self , ty1 : & Type , ty2 : & Type , hint : & ' static str ) -> Result < ( ) , Error > {
168
- let lock = self . lock ( ) ;
172
+ let mut lock = self . lock ( ) ;
169
173
lock. unify ( ty1, ty2, hint)
170
174
}
171
175
@@ -180,9 +184,7 @@ impl Context {
180
184
#[ derive( Debug , Clone ) ]
181
185
pub struct BoundRef {
182
186
context : * const Mutex < Vec < Bound > > ,
183
- // Will become an index into the context in a latter commit, but for
184
- // now we set it to an Arc<BoundMutex> to preserve semantics.
185
- index : Arc < BoundMutex > ,
187
+ index : usize ,
186
188
}
187
189
188
190
impl BoundRef {
@@ -200,7 +202,7 @@ impl BoundRef {
200
202
pub fn occurs_check_id ( & self ) -> OccursCheckId {
201
203
OccursCheckId {
202
204
context : self . context ,
203
- index : Arc :: as_ptr ( & self . index ) ,
205
+ index : self . index ,
204
206
}
205
207
}
206
208
}
@@ -211,13 +213,13 @@ impl super::PointerLike for BoundRef {
211
213
self . context, other. context,
212
214
"tried to compare two bounds from different inference contexts"
213
215
) ;
214
- Arc :: ptr_eq ( & self . index , & other. index )
216
+ self . index == other. index
215
217
}
216
218
217
219
fn shallow_clone ( & self ) -> Self {
218
220
BoundRef {
219
221
context : self . context ,
220
- index : Arc :: clone ( & self . index ) ,
222
+ index : self . index ,
221
223
}
222
224
}
223
225
}
@@ -243,7 +245,7 @@ pub struct OccursCheckId {
243
245
context : * const Mutex < Vec < Bound > > ,
244
246
// Will become an index into the context in a latter commit, but for
245
247
// now we set it to an Arc<BoundMutex> to preserve semantics.
246
- index : * const BoundMutex ,
248
+ index : usize ,
247
249
}
248
250
249
251
/// Structure representing an inference context with its slab allocator mutex locked.
@@ -255,17 +257,25 @@ struct LockedContext<'ctx> {
255
257
}
256
258
257
259
impl < ' ctx > LockedContext < ' ctx > {
260
+ fn reassign_non_complete ( & mut self , bound : BoundRef , new : Bound ) {
261
+ assert ! (
262
+ !matches!( self . slab[ bound. index] , Bound :: Complete ( ..) ) ,
263
+ "tried to modify finalized type" ,
264
+ ) ;
265
+ self . slab [ bound. index ] = new;
266
+ }
267
+
258
268
/// Unify the type with another one.
259
269
///
260
270
/// Fails if the bounds on the two types are incompatible
261
- fn unify ( & self , existing : & Type , other : & Type , hint : & ' static str ) -> Result < ( ) , Error > {
271
+ fn unify ( & mut self , existing : & Type , other : & Type , hint : & ' static str ) -> Result < ( ) , Error > {
262
272
existing. bound . unify ( & other. bound , |x_bound, y_bound| {
263
- self . bind ( x_bound, y_bound. index . get ( ) , hint)
273
+ self . bind ( x_bound, self . slab [ y_bound. index ] . shallow_clone ( ) , hint)
264
274
} )
265
275
}
266
276
267
- fn bind ( & self , existing : BoundRef , new : Bound , hint : & ' static str ) -> Result < ( ) , Error > {
268
- let existing_bound = existing. index . get ( ) ;
277
+ fn bind ( & mut self , existing : BoundRef , new : Bound , hint : & ' static str ) -> Result < ( ) , Error > {
278
+ let existing_bound = self . slab [ existing. index ] . shallow_clone ( ) ;
269
279
let bind_error = || Error :: Bind {
270
280
existing_bound : existing_bound. shallow_clone ( ) ,
271
281
new_bound : new. shallow_clone ( ) ,
@@ -278,7 +288,7 @@ impl<'ctx> LockedContext<'ctx> {
278
288
// Free types are simply dropped and replaced by the new bound
279
289
( Bound :: Free ( _) , _) => {
280
290
// Free means non-finalized, so set() is ok.
281
- existing . index . set ( new) ;
291
+ self . reassign_non_complete ( existing , new) ;
282
292
Ok ( ( ) )
283
293
}
284
294
// Binding complete->complete shouldn't ever happen, but if so, we just
@@ -320,14 +330,17 @@ impl<'ctx> LockedContext<'ctx> {
320
330
//
321
331
// It also gives the user access to more information about the type,
322
332
// prior to finalization.
323
- if let ( Some ( data1) , Some ( data2) ) = ( y1. final_data ( ) , y2. final_data ( ) ) {
324
- existing
325
- . index
326
- . set ( Bound :: Complete ( if let Bound :: Sum ( ..) = existing_bound {
327
- Final :: sum ( data1, data2)
333
+ let y1_bound = & self . slab [ y1. bound . root ( ) . index ] ;
334
+ let y2_bound = & self . slab [ y2. bound . root ( ) . index ] ;
335
+ if let ( Bound :: Complete ( data1) , Bound :: Complete ( data2) ) = ( y1_bound, y2_bound) {
336
+ self . reassign_non_complete (
337
+ existing,
338
+ Bound :: Complete ( if let Bound :: Sum ( ..) = existing_bound {
339
+ Final :: sum ( Arc :: clone ( data1) , Arc :: clone ( data2) )
328
340
} else {
329
- Final :: product ( data1, data2)
330
- } ) ) ;
341
+ Final :: product ( Arc :: clone ( data1) , Arc :: clone ( data2) )
342
+ } ) ,
343
+ ) ;
331
344
}
332
345
Ok ( ( ) )
333
346
}
0 commit comments