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
@@ -410,23 +413,22 @@ impl ir::AssociatedTyDatum {
410
413
// equality" rules. There are always two; one for a successful normalization,
411
414
// and one for the "fallback" notion of equality.
412
415
//
413
- // Given:
416
+ // Given: (here, `'a` and `T` represent zero or more parameters)
414
417
//
415
418
// trait Foo {
416
- // type Assoc;
419
+ // type Assoc<'a, T>: Bounds where WC ;
417
420
// }
418
421
//
419
422
// we generate the 'fallback' rule:
420
423
//
421
- // forall<T> {
422
- // ProjectionEq(<T as Foo>::Assoc = (Foo::Assoc)<T>) :-
423
- // T: Foo
424
+ // forall<Self, 'a, T> {
425
+ // ProjectionEq(<Self as Foo>::Assoc<'a, T> = (Foo::Assoc<'a, T>)<Self>).
424
426
// }
425
427
//
426
428
// and
427
429
//
428
- // forall<T > {
429
- // ProjectionEq(<T as Foo>::Assoc = U) :-
430
+ // forall<Self, 'a, T, U > {
431
+ // ProjectionEq(<T as Foo>::Assoc<'a, T> = U) :-
430
432
// Normalize(<T as Foo>::Assoc -> U)
431
433
// }
432
434
//
@@ -473,37 +475,76 @@ impl ir::AssociatedTyDatum {
473
475
} ;
474
476
let app_ty = ir:: Ty :: Apply ( app) ;
475
477
478
+ let projection_eq = ir:: ProjectionEq {
479
+ projection : projection. clone ( ) ,
480
+ ty : app_ty. clone ( ) ,
481
+ } ;
482
+
476
483
let mut clauses = vec ! [ ] ;
477
484
478
- // forall<T> {
479
- // ProjectionEq(<T as Foo>::Assoc = (Foo::Assoc)<T>) :-
480
- // T: Foo
485
+ // Fallback rule. The solver uses this to move between the projection
486
+ // and skolemized type.
487
+ //
488
+ // forall<Self> {
489
+ // ProjectionEq(<Self as Foo>::Assoc = (Foo::Assoc)<Self>).
481
490
// }
482
491
clauses. push ( ir:: Binders {
483
492
binders : binders. clone ( ) ,
484
493
value : ir:: ProgramClauseImplication {
485
- consequence : ir:: ProjectionEq {
486
- projection : projection. clone ( ) ,
487
- ty : app_ty. clone ( ) ,
488
- } . cast ( ) ,
489
- conditions : vec ! [ trait_ref. clone( ) . cast( ) ] ,
494
+ consequence : projection_eq. clone ( ) . cast ( ) ,
495
+ conditions : vec ! [ ] ,
490
496
} ,
491
497
} . cast ( ) ) ;
492
498
493
- // The above application type is always well-formed, and `<T as Foo>::Assoc` will
494
- // unify with `(Foo::Assoc)<T>` only if `T: Foo`, because of the above rule, so we have:
499
+ // Well-formedness of projection type.
495
500
//
496
- // forall<T > {
497
- // WellFormed((Foo::Assoc)<T>) .
501
+ // forall<Self > {
502
+ // WellFormed((Foo::Assoc)<Self>) :- Self: Foo, WC .
498
503
// }
499
504
clauses. push ( ir:: Binders {
500
505
binders : binders. clone ( ) ,
501
506
value : ir:: ProgramClauseImplication {
502
- consequence : ir:: DomainGoal :: WellFormedTy ( app_ty) . cast ( ) ,
503
- conditions : vec ! [ ] ,
507
+ consequence : ir:: DomainGoal :: WellFormedTy ( app_ty. clone ( ) ) . cast ( ) ,
508
+ conditions : iter:: once ( trait_ref. clone ( ) . cast ( ) )
509
+ . chain ( self . where_clauses . iter ( ) . cloned ( ) . casted ( ) )
510
+ . collect ( ) ,
504
511
} ,
505
512
} . cast ( ) ) ;
506
513
514
+ // Assuming well-formedness of projection type means we can assume
515
+ // the trait ref as well.
516
+ //
517
+ // Currently we do not use this rule in chalk (it's used in fn bodies),
518
+ // but it's here for completeness.
519
+ //
520
+ // forall<Self> {
521
+ // FromEnv(Self: Foo) :- FromEnv((Foo::Assoc)<Self>).
522
+ // }
523
+ clauses. push ( ir:: Binders {
524
+ binders : binders. clone ( ) ,
525
+ value : ir:: ProgramClauseImplication {
526
+ consequence : ir:: DomainGoal :: FromEnv ( trait_ref. clone ( ) . cast ( ) ) ,
527
+ conditions : vec ! [ ir:: DomainGoal :: FromEnvTy ( app_ty. clone( ) ) . cast( ) ] ,
528
+ }
529
+ } . cast ( ) ) ;
530
+
531
+ // Reverse rule for where clauses.
532
+ //
533
+ // forall<Self> {
534
+ // FromEnv(WC) :- FromEnv((Foo::Assoc)<Self>).
535
+ // }
536
+ //
537
+ // This is really a family of clauses, one for each where clause.
538
+ clauses. extend ( self . where_clauses . iter ( ) . map ( |wc| {
539
+ ir:: Binders {
540
+ binders : binders. iter ( ) . chain ( wc. binders . iter ( ) ) . cloned ( ) . collect ( ) ,
541
+ value : ir:: ProgramClauseImplication {
542
+ consequence : wc. value . clone ( ) . into_from_env_goal ( ) ,
543
+ conditions : vec ! [ ir:: DomainGoal :: FromEnvTy ( app_ty. clone( ) ) . cast( ) ] ,
544
+ }
545
+ } . cast ( )
546
+ } ) ) ;
547
+
507
548
// add new type parameter U
508
549
let mut binders = binders;
509
550
binders. push ( ir:: ParameterKind :: Ty ( ( ) ) ) ;
@@ -515,9 +556,11 @@ impl ir::AssociatedTyDatum {
515
556
// `ProjectionEq(<T as Foo>::Assoc = U)`
516
557
let projection_eq = ir:: ProjectionEq { projection : projection. clone ( ) , ty } ;
517
558
518
- // forall<T> {
559
+ // Projection equality rule from above.
560
+ //
561
+ // forall<T, U> {
519
562
// ProjectionEq(<T as Foo>::Assoc = U) :-
520
- // Normalize(<T as Foo>::Assoc -> U)
563
+ // Normalize(<T as Foo>::Assoc -> U).
521
564
// }
522
565
clauses. push ( ir:: Binders {
523
566
binders : binders. clone ( ) ,
0 commit comments