@@ -15,8 +15,6 @@ use std::collections::hash_map::Entry;
15
15
16
16
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
17
17
18
- use hir:: WherePredicate ;
19
-
20
18
use infer:: { InferCtxt , RegionObligation } ;
21
19
use infer:: region_constraints:: { Constraint , RegionConstraintData } ;
22
20
@@ -36,32 +34,42 @@ pub struct RegionDeps<'tcx> {
36
34
smaller : FxHashSet < RegionTarget < ' tcx > >
37
35
}
38
36
39
- pub enum AutoTraitResult {
37
+ pub enum AutoTraitResult < A > {
40
38
ExplicitImpl ,
41
- PositiveImpl , /*(ty::Generics), TODO(twk)*/
39
+ PositiveImpl ( A ) ,
42
40
NegativeImpl ,
43
41
}
44
42
45
- impl AutoTraitResult {
43
+ impl < A > AutoTraitResult < A > {
46
44
fn is_auto ( & self ) -> bool {
47
45
match * self {
48
- AutoTraitResult :: PositiveImpl | AutoTraitResult :: NegativeImpl => true ,
46
+ AutoTraitResult :: PositiveImpl ( _ ) | AutoTraitResult :: NegativeImpl => true ,
49
47
_ => false ,
50
48
}
51
49
}
52
50
}
53
51
52
+ pub struct AutoTraitInfo < ' cx > {
53
+ pub full_user_env : ty:: ParamEnv < ' cx > ,
54
+ pub region_data : RegionConstraintData < ' cx > ,
55
+ pub names_map : FxHashMap < String , String > ,
56
+ pub vid_to_region : FxHashMap < ty:: RegionVid , ty:: Region < ' cx > > ,
57
+ }
58
+
54
59
pub struct AutoTraitFinder < ' a , ' tcx : ' a > {
55
60
pub tcx : & ' a TyCtxt < ' a , ' tcx , ' tcx > ,
56
61
}
57
62
58
63
impl < ' a , ' tcx > AutoTraitFinder < ' a , ' tcx > {
59
- pub fn find_auto_trait_generics (
64
+ pub fn find_auto_trait_generics < A , F > (
60
65
& self ,
61
66
did : DefId ,
62
67
trait_did : DefId ,
63
68
generics : & ty:: Generics ,
64
- ) -> AutoTraitResult {
69
+ auto_trait_callback : F )
70
+ -> AutoTraitResult < A >
71
+ where F : for <' b , ' cx , ' cx2 > Fn ( & InferCtxt < ' b , ' cx , ' cx2 > , AutoTraitInfo < ' cx2 > ) -> A
72
+ {
65
73
let tcx = self . tcx ;
66
74
let ty = self . tcx . type_of ( did) ;
67
75
@@ -72,7 +80,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
72
80
substs : tcx. mk_substs_trait ( ty, & [ ] ) ,
73
81
} ;
74
82
75
- let trait_pred = ty:: Binder ( trait_ref) ;
83
+ let trait_pred = ty:: Binder :: bind ( trait_ref) ;
76
84
77
85
let bail_out = tcx. infer_ctxt ( ) . enter ( |infcx| {
78
86
let mut selcx = SelectionContext :: with_negative ( & infcx, true ) ;
@@ -149,7 +157,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
149
157
None => return AutoTraitResult :: NegativeImpl ,
150
158
} ;
151
159
152
- let ( full_env, _full_user_env ) = self . evaluate_predicates (
160
+ let ( full_env, full_user_env ) = self . evaluate_predicates (
153
161
& mut infcx,
154
162
did,
155
163
trait_did,
@@ -193,8 +201,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
193
201
let names_map: FxHashMap < String , String > = generics
194
202
. regions
195
203
. iter ( )
196
- . map ( |l| ( l. name . as_str ( ) . to_string ( ) , l. name . to_string ( ) ) )
197
- // TODO(twk): Lifetime branding
204
+ . map ( |l| ( l. name . to_string ( ) , l. name . to_string ( ) ) )
205
+ // TODO(twk): Lifetime branding and why is this map a set?!
206
+ // l.clean(self.cx) was present in the original code
198
207
. collect ( ) ;
199
208
200
209
let body_ids: FxHashSet < _ > = infcx
@@ -213,33 +222,16 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
213
222
. region_constraint_data ( )
214
223
. clone ( ) ;
215
224
216
- let lifetime_predicates = self . handle_lifetimes ( & region_data, & names_map) ;
217
225
let vid_to_region = self . map_vid_to_region ( & region_data) ;
218
226
219
- debug ! (
220
- "find_auto_trait_generics(did={:?}, trait_did={:?}, generics={:?}): computed \
221
- lifetime information '{:?}' '{:?}'",
222
- did, trait_did, generics, lifetime_predicates, vid_to_region
223
- ) ;
227
+ let info = AutoTraitInfo { full_user_env, region_data, names_map, vid_to_region } ;
224
228
225
- /* let new_generics = self.param_env_to_generics(
226
- infcx.tcx,
227
- did,
228
- full_user_env,
229
- generics.clone(),
230
- lifetime_predicates,
231
- vid_to_region,
232
- ); */
233
-
234
- debug ! (
235
- "find_auto_trait_generics(did={:?}, trait_did={:?}, generics={:?}): finished with \
236
- <generics placeholder here>",
237
- did, trait_did, generics /* , new_generics */
238
- ) ;
239
- return AutoTraitResult :: PositiveImpl ;
229
+ return AutoTraitResult :: PositiveImpl ( auto_trait_callback ( & infcx, info) ) ;
240
230
} ) ;
241
231
}
232
+ }
242
233
234
+ impl < ' a , ' tcx > AutoTraitFinder < ' a , ' tcx > {
243
235
// The core logic responsible for computing the bounds for our synthesized impl.
244
236
//
245
237
// To calculate the bounds, we call SelectionContext.select in a loop. Like FulfillmentContext,
@@ -294,7 +286,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
294
286
295
287
let mut already_visited = FxHashSet ( ) ;
296
288
let mut predicates = VecDeque :: new ( ) ;
297
- predicates. push_back ( ty:: Binder ( ty:: TraitPredicate {
289
+ predicates. push_back ( ty:: Binder :: bind ( ty:: TraitPredicate {
298
290
trait_ref : ty:: TraitRef {
299
291
def_id : trait_did,
300
292
substs : infcx. tcx . mk_substs_trait ( ty, & [ ] ) ,
@@ -359,14 +351,12 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
359
351
new_env = ty:: ParamEnv :: new (
360
352
tcx. mk_predicates ( normalized_preds) ,
361
353
param_env. reveal ,
362
- ty:: UniverseIndex :: ROOT ,
363
354
) ;
364
355
}
365
356
366
357
let final_user_env = ty:: ParamEnv :: new (
367
358
tcx. mk_predicates ( user_computed_preds. into_iter ( ) ) ,
368
359
user_env. reveal ,
369
- ty:: UniverseIndex :: ROOT ,
370
360
) ;
371
361
debug ! (
372
362
"evaluate_nested_obligations(ty_did={:?}, trait_did={:?}): succeeded with '{:?}' \
@@ -377,165 +367,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
377
367
return Some ( ( new_env, final_user_env) ) ;
378
368
}
379
369
380
- // This method calculates two things: Lifetime constraints of the form 'a: 'b,
381
- // and region constraints of the form ReVar: 'a
382
- //
383
- // This is essentially a simplified version of lexical_region_resolve. However,
384
- // handle_lifetimes determines what *needs be* true in order for an impl to hold.
385
- // lexical_region_resolve, along with much of the rest of the compiler, is concerned
386
- // with determining if a given set up constraints/predicates *are* met, given some
387
- // starting conditions (e.g. user-provided code). For this reason, it's easier
388
- // to perform the calculations we need on our own, rather than trying to make
389
- // existing inference/solver code do what we want.
390
- pub fn handle_lifetimes < ' cx > (
391
- & self ,
392
- regions : & RegionConstraintData < ' cx > ,
393
- names_map : & FxHashMap < String , String > , // TODO(twk): lifetime branding
394
- ) -> Vec < WherePredicate > {
395
- // Our goal is to 'flatten' the list of constraints by eliminating
396
- // all intermediate RegionVids. At the end, all constraints should
397
- // be between Regions (aka region variables). This gives us the information
398
- // we need to create the Generics.
399
- let mut finished = FxHashMap ( ) ;
400
-
401
- let mut vid_map: FxHashMap < RegionTarget , RegionDeps > = FxHashMap ( ) ;
402
-
403
- // Flattening is done in two parts. First, we insert all of the constraints
404
- // into a map. Each RegionTarget (either a RegionVid or a Region) maps
405
- // to its smaller and larger regions. Note that 'larger' regions correspond
406
- // to sub-regions in Rust code (e.g. in 'a: 'b, 'a is the larger region).
407
- for constraint in regions. constraints . keys ( ) {
408
- match constraint {
409
- & Constraint :: VarSubVar ( r1, r2) => {
410
- {
411
- let deps1 = vid_map
412
- . entry ( RegionTarget :: RegionVid ( r1) )
413
- . or_insert_with ( || Default :: default ( ) ) ;
414
- deps1. larger . insert ( RegionTarget :: RegionVid ( r2) ) ;
415
- }
416
-
417
- let deps2 = vid_map
418
- . entry ( RegionTarget :: RegionVid ( r2) )
419
- . or_insert_with ( || Default :: default ( ) ) ;
420
- deps2. smaller . insert ( RegionTarget :: RegionVid ( r1) ) ;
421
- }
422
- & Constraint :: RegSubVar ( region, vid) => {
423
- let deps = vid_map
424
- . entry ( RegionTarget :: RegionVid ( vid) )
425
- . or_insert_with ( || Default :: default ( ) ) ;
426
- deps. smaller . insert ( RegionTarget :: Region ( region) ) ;
427
- }
428
- & Constraint :: VarSubReg ( vid, region) => {
429
- let deps = vid_map
430
- . entry ( RegionTarget :: RegionVid ( vid) )
431
- . or_insert_with ( || Default :: default ( ) ) ;
432
- deps. larger . insert ( RegionTarget :: Region ( region) ) ;
433
- }
434
- & Constraint :: RegSubReg ( r1, r2) => {
435
- // The constraint is already in the form that we want, so we're done with it
436
- // Desired order is 'larger, smaller', so flip then
437
- if self . region_name ( r1) != self . region_name ( r2) {
438
- finished
439
- . entry ( self . region_name ( r2) . unwrap ( ) )
440
- . or_insert_with ( || Vec :: new ( ) )
441
- . push ( r1) ;
442
- }
443
- }
444
- }
445
- }
446
-
447
- // Here, we 'flatten' the map one element at a time.
448
- // All of the element's sub and super regions are connected
449
- // to each other. For example, if we have a graph that looks like this:
450
- //
451
- // (A, B) - C - (D, E)
452
- // Where (A, B) are subregions, and (D,E) are super-regions
453
- //
454
- // then after deleting 'C', the graph will look like this:
455
- // ... - A - (D, E ...)
456
- // ... - B - (D, E, ...)
457
- // (A, B, ...) - D - ...
458
- // (A, B, ...) - E - ...
459
- //
460
- // where '...' signifies the existing sub and super regions of an entry
461
- // When two adjacent ty::Regions are encountered, we've computed a final
462
- // constraint, and add it to our list. Since we make sure to never re-add
463
- // deleted items, this process will always finish.
464
- while !vid_map. is_empty ( ) {
465
- let target = vid_map. keys ( ) . next ( ) . expect ( "Keys somehow empty" ) . clone ( ) ;
466
- let deps = vid_map. remove ( & target) . expect ( "Entry somehow missing" ) ;
467
-
468
- for smaller in deps. smaller . iter ( ) {
469
- for larger in deps. larger . iter ( ) {
470
- match ( smaller, larger) {
471
- ( & RegionTarget :: Region ( r1) , & RegionTarget :: Region ( r2) ) => {
472
- if self . region_name ( r1) != self . region_name ( r2) {
473
- finished
474
- . entry ( self . region_name ( r2) . unwrap ( ) )
475
- . or_insert_with ( || Vec :: new ( ) )
476
- . push ( r1) // Larger, smaller
477
- }
478
- }
479
- ( & RegionTarget :: RegionVid ( _) , & RegionTarget :: Region ( _) ) => {
480
- if let Entry :: Occupied ( v) = vid_map. entry ( * smaller) {
481
- let smaller_deps = v. into_mut ( ) ;
482
- smaller_deps. larger . insert ( * larger) ;
483
- smaller_deps. larger . remove ( & target) ;
484
- }
485
- }
486
- ( & RegionTarget :: Region ( _) , & RegionTarget :: RegionVid ( _) ) => {
487
- if let Entry :: Occupied ( v) = vid_map. entry ( * larger) {
488
- let deps = v. into_mut ( ) ;
489
- deps. smaller . insert ( * smaller) ;
490
- deps. smaller . remove ( & target) ;
491
- }
492
- }
493
- ( & RegionTarget :: RegionVid ( _) , & RegionTarget :: RegionVid ( _) ) => {
494
- if let Entry :: Occupied ( v) = vid_map. entry ( * smaller) {
495
- let smaller_deps = v. into_mut ( ) ;
496
- smaller_deps. larger . insert ( * larger) ;
497
- smaller_deps. larger . remove ( & target) ;
498
- }
499
-
500
- if let Entry :: Occupied ( v) = vid_map. entry ( * larger) {
501
- let larger_deps = v. into_mut ( ) ;
502
- larger_deps. smaller . insert ( * smaller) ;
503
- larger_deps. smaller . remove ( & target) ;
504
- }
505
- }
506
- }
507
- }
508
- }
509
- }
510
-
511
- let lifetime_predicates = names_map
512
- . iter ( )
513
- . flat_map ( |( name, _lifetime) | {
514
- let empty = Vec :: new ( ) ;
515
- let bounds: FxHashSet < String > = finished // TODO(twk): lifetime branding
516
- . get ( name)
517
- . unwrap_or ( & empty)
518
- . iter ( )
519
- . map ( |region| self . get_lifetime ( region, names_map) )
520
- . collect ( ) ;
521
-
522
- if bounds. is_empty ( ) {
523
- return None ;
524
- }
525
- /* Some(WherePredicate::RegionPredicate {
526
- lifetime: lifetime.clone(),
527
- bounds: bounds.into_iter().collect(),
528
- }) */
529
- None // TODO(twk): use the correct WherePredicate and rebuild the code above
530
- } )
531
- . collect ( ) ;
532
-
533
- lifetime_predicates
534
- }
535
-
536
370
pub fn region_name ( & self , region : Region ) -> Option < String > {
537
371
match region {
538
- & ty:: ReEarlyBound ( r) => Some ( r. name . as_str ( ) . to_string ( ) ) ,
372
+ & ty:: ReEarlyBound ( r) => Some ( r. name . to_string ( ) ) ,
539
373
_ => None ,
540
374
}
541
375
}
0 commit comments