1
1
use cast:: { Cast , Caster } ;
2
2
use fold:: shift:: Shift ;
3
3
use ir:: { self , ToParameter } ;
4
+ use std:: iter;
4
5
5
6
mod default;
6
7
mod wf;
@@ -181,12 +182,14 @@ impl ir::AssociatedTyValue {
181
182
program : & ir:: Program ,
182
183
impl_datum : & ir:: ImplDatum ,
183
184
) -> Vec < ir:: ProgramClause > {
185
+ let associated_ty = & program. associated_ty_data [ & self . associated_ty_id ] ;
186
+
184
187
// Begin with the innermost parameters (`'a`) and then add those from impl (`T`).
185
188
let all_binders: Vec < _ > = self . value
186
189
. binders
187
190
. iter ( )
191
+ . chain ( impl_datum. binders . binders . iter ( ) )
188
192
. cloned ( )
189
- . chain ( impl_datum. binders . binders . iter ( ) . cloned ( ) )
190
193
. collect ( ) ;
191
194
192
195
// Assemble the full list of conditions for projection to be valid.
@@ -200,7 +203,9 @@ impl ir::AssociatedTyValue {
200
203
. trait_ref
201
204
. trait_ref ( )
202
205
. up_shift ( self . value . len ( ) ) ;
203
- let conditions: Vec < ir:: Goal > = vec ! [ impl_trait_ref. clone( ) . cast( ) ] ;
206
+ let conditions: Vec < ir:: Goal > =
207
+ iter:: once ( impl_trait_ref. clone ( ) . cast ( ) )
208
+ . chain ( associated_ty. where_clauses . iter ( ) . cloned ( ) . casted ( ) ) . collect ( ) ;
204
209
205
210
// Bound parameters + `Self` type of the trait-ref
206
211
let parameters: Vec < _ > = {
@@ -233,14 +238,12 @@ impl ir::AssociatedTyValue {
233
238
binders : all_binders. clone ( ) ,
234
239
value : ir:: ProgramClauseImplication {
235
240
consequence : normalize_goal. clone ( ) ,
236
- conditions : conditions. clone ( ) ,
241
+ conditions : conditions,
237
242
} ,
238
243
} . cast ( ) ;
239
244
240
245
let unselected_projection = ir:: UnselectedProjectionTy {
241
- type_name : program. associated_ty_data [ & self . associated_ty_id ]
242
- . name
243
- . clone ( ) ,
246
+ type_name : associated_ty. name . clone ( ) ,
244
247
parameters : parameters,
245
248
} ;
246
249
@@ -394,23 +397,22 @@ impl ir::AssociatedTyDatum {
394
397
// equality" rules. There are always two; one for a successful normalization,
395
398
// and one for the "fallback" notion of equality.
396
399
//
397
- // Given:
400
+ // Given: (here, `'a` and `T` represent zero or more parameters)
398
401
//
399
402
// trait Foo {
400
- // type Assoc;
403
+ // type Assoc<'a, T>: Bounds where WC ;
401
404
// }
402
405
//
403
406
// we generate the 'fallback' rule:
404
407
//
405
- // forall<T> {
406
- // ProjectionEq(<T as Foo>::Assoc = (Foo::Assoc)<T>) :-
407
- // T: Foo
408
+ // forall<Self, 'a, T> {
409
+ // ProjectionEq(<Self as Foo>::Assoc<'a, T> = (Foo::Assoc<'a, T>)<Self>).
408
410
// }
409
411
//
410
412
// and
411
413
//
412
- // forall<T > {
413
- // ProjectionEq(<T as Foo>::Assoc = U) :-
414
+ // forall<Self, 'a, T, U > {
415
+ // ProjectionEq(<T as Foo>::Assoc<'a, T> = U) :-
414
416
// Normalize(<T as Foo>::Assoc -> U)
415
417
// }
416
418
//
@@ -457,37 +459,76 @@ impl ir::AssociatedTyDatum {
457
459
} ;
458
460
let app_ty = ir:: Ty :: Apply ( app) ;
459
461
462
+ let projection_eq = ir:: ProjectionEq {
463
+ projection : projection. clone ( ) ,
464
+ ty : app_ty. clone ( ) ,
465
+ } ;
466
+
460
467
let mut clauses = vec ! [ ] ;
461
468
462
- // forall<T> {
463
- // ProjectionEq(<T as Foo>::Assoc = (Foo::Assoc)<T>) :-
464
- // T: Foo
469
+ // Fallback rule. The solver uses this to move between the projection
470
+ // and skolemized type.
471
+ //
472
+ // forall<Self> {
473
+ // ProjectionEq(<Self as Foo>::Assoc = (Foo::Assoc)<Self>).
465
474
// }
466
475
clauses. push ( ir:: Binders {
467
476
binders : binders. clone ( ) ,
468
477
value : ir:: ProgramClauseImplication {
469
- consequence : ir:: ProjectionEq {
470
- projection : projection. clone ( ) ,
471
- ty : app_ty. clone ( ) ,
472
- } . cast ( ) ,
473
- conditions : vec ! [ trait_ref. clone( ) . cast( ) ] ,
478
+ consequence : projection_eq. clone ( ) . cast ( ) ,
479
+ conditions : vec ! [ ] ,
474
480
} ,
475
481
} . cast ( ) ) ;
476
482
477
- // The above application type is always well-formed, and `<T as Foo>::Assoc` will
478
- // unify with `(Foo::Assoc)<T>` only if `T: Foo`, because of the above rule, so we have:
483
+ // Well-formedness of projection type.
479
484
//
480
- // forall<T > {
481
- // WellFormed((Foo::Assoc)<T>) .
485
+ // forall<Self > {
486
+ // WellFormed((Foo::Assoc)<Self>) :- Self: Foo, WC .
482
487
// }
483
488
clauses. push ( ir:: Binders {
484
489
binders : binders. clone ( ) ,
485
490
value : ir:: ProgramClauseImplication {
486
- consequence : ir:: DomainGoal :: WellFormedTy ( app_ty) . cast ( ) ,
487
- conditions : vec ! [ ] ,
491
+ consequence : ir:: DomainGoal :: WellFormedTy ( app_ty. clone ( ) ) . cast ( ) ,
492
+ conditions : iter:: once ( trait_ref. clone ( ) . cast ( ) )
493
+ . chain ( self . where_clauses . iter ( ) . cloned ( ) . casted ( ) )
494
+ . collect ( ) ,
488
495
} ,
489
496
} . cast ( ) ) ;
490
497
498
+ // Assuming well-formedness of projection type means we can assume
499
+ // the trait ref as well.
500
+ //
501
+ // Currently we do not use this rule in chalk (it's used in fn bodies),
502
+ // but it's here for completeness.
503
+ //
504
+ // forall<Self> {
505
+ // FromEnv(Self: Foo) :- FromEnv((Foo::Assoc)<Self>).
506
+ // }
507
+ clauses. push ( ir:: Binders {
508
+ binders : binders. clone ( ) ,
509
+ value : ir:: ProgramClauseImplication {
510
+ consequence : ir:: DomainGoal :: FromEnv ( trait_ref. clone ( ) . cast ( ) ) ,
511
+ conditions : vec ! [ ir:: DomainGoal :: FromEnvTy ( app_ty. clone( ) ) . cast( ) ] ,
512
+ }
513
+ } . cast ( ) ) ;
514
+
515
+ // Reverse rule for where clauses.
516
+ //
517
+ // forall<Self> {
518
+ // FromEnv(WC) :- FromEnv((Foo::Assoc)<Self>).
519
+ // }
520
+ //
521
+ // This is really a family of clauses, one for each where clause.
522
+ clauses. extend ( self . where_clauses . iter ( ) . map ( |wc| {
523
+ ir:: Binders {
524
+ binders : binders. iter ( ) . chain ( wc. binders . iter ( ) ) . cloned ( ) . collect ( ) ,
525
+ value : ir:: ProgramClauseImplication {
526
+ consequence : wc. value . clone ( ) . into_from_env_goal ( ) ,
527
+ conditions : vec ! [ ir:: DomainGoal :: FromEnvTy ( app_ty. clone( ) ) . cast( ) ] ,
528
+ }
529
+ } . cast ( )
530
+ } ) ) ;
531
+
491
532
// add new type parameter U
492
533
let mut binders = binders;
493
534
binders. push ( ir:: ParameterKind :: Ty ( ( ) ) ) ;
@@ -499,9 +540,11 @@ impl ir::AssociatedTyDatum {
499
540
// `ProjectionEq(<T as Foo>::Assoc = U)`
500
541
let projection_eq = ir:: ProjectionEq { projection : projection. clone ( ) , ty } ;
501
542
502
- // forall<T> {
543
+ // Projection equality rule from above.
544
+ //
545
+ // forall<T, U> {
503
546
// ProjectionEq(<T as Foo>::Assoc = U) :-
504
- // Normalize(<T as Foo>::Assoc -> U)
547
+ // Normalize(<T as Foo>::Assoc -> U).
505
548
// }
506
549
clauses. push ( ir:: Binders {
507
550
binders : binders. clone ( ) ,
0 commit comments