@@ -389,20 +389,56 @@ fn program_clauses_that_could_match<I: Interner>(
389
389
390
390
match goal {
391
391
DomainGoal :: Holds ( WhereClause :: Implemented ( trait_ref) ) => {
392
- let trait_id = trait_ref. trait_id ;
392
+ let self_ty = trait_ref. self_type_parameter ( interner ) ;
393
393
394
+ let trait_id = trait_ref. trait_id ;
394
395
let trait_datum = db. trait_datum ( trait_id) ;
395
396
396
- if trait_datum. is_non_enumerable_trait ( ) || trait_datum. is_auto_trait ( ) {
397
- let self_ty = trait_ref. self_type_parameter ( interner) ;
397
+ match self_ty. kind ( interner) {
398
+ TyKind :: Alias ( alias) => {
399
+ // An alias could normalize to anything, including `dyn trait`
400
+ // or an opaque type, so push a clause that asks for the
401
+ // self type to be normalized and return.
402
+ push_alias_implemented_clause ( builder, trait_ref, alias) ;
403
+ return Ok ( clauses) ;
404
+ }
398
405
399
- if let TyKind :: Alias ( AliasTy :: Opaque ( opaque_ty ) ) = self_ty. kind ( interner) {
400
- if trait_datum. is_auto_trait ( ) {
401
- push_auto_trait_impls_opaque ( builder , trait_id , opaque_ty . opaque_ty_id )
406
+ _ if self_ty. is_general_var ( interner, binders ) => {
407
+ if trait_datum. is_non_enumerable_trait ( ) || trait_datum . is_auto_trait ( ) {
408
+ return Err ( Floundered ) ;
402
409
}
403
- } else if self_ty. is_general_var ( interner, binders) {
404
- return Err ( Floundered ) ;
405
410
}
411
+
412
+ TyKind :: OpaqueType ( opaque_ty_id, _) => {
413
+ db. opaque_ty_data ( * opaque_ty_id)
414
+ . to_program_clauses ( builder, environment) ;
415
+ }
416
+
417
+ TyKind :: Dyn ( _) => {
418
+ // If the self type is a `dyn trait` type, generate program-clauses
419
+ // that indicates that it implements its own traits.
420
+ // FIXME: This is presently rather wasteful, in that we don't check that the
421
+ // these program clauses we are generating are actually relevant to the goal
422
+ // `goal` that we are actually *trying* to prove (though there is some later
423
+ // code that will screen out irrelevant stuff).
424
+ //
425
+ // In other words, if we were trying to prove `Implemented(dyn
426
+ // Fn(&u8): Clone)`, we would still generate two clauses that are
427
+ // totally irrelevant to that goal, because they let us prove other
428
+ // things but not `Clone`.
429
+ dyn_ty:: build_dyn_self_ty_clauses ( db, builder, self_ty. clone ( ) )
430
+ }
431
+
432
+ // We don't actually do anything here, but we need to record the types when logging
433
+ TyKind :: Adt ( adt_id, _) => {
434
+ let _ = db. adt_datum ( * adt_id) ;
435
+ }
436
+
437
+ TyKind :: FnDef ( fn_def_id, _) => {
438
+ let _ = db. fn_def_datum ( * fn_def_id) ;
439
+ }
440
+
441
+ _ => { }
406
442
}
407
443
408
444
// This is needed for the coherence related impls, as well
@@ -429,42 +465,6 @@ fn program_clauses_that_could_match<I: Interner>(
429
465
} ) ?;
430
466
}
431
467
432
- // If the self type is a `dyn trait` type, generate program-clauses
433
- // that indicates that it implements its own traits.
434
- // FIXME: This is presently rather wasteful, in that we don't check that the
435
- // these program clauses we are generating are actually relevant to the goal
436
- // `goal` that we are actually *trying* to prove (though there is some later
437
- // code that will screen out irrelevant stuff).
438
- //
439
- // In other words, if we were trying to prove `Implemented(dyn
440
- // Fn(&u8): Clone)`, we would still generate two clauses that are
441
- // totally irrelevant to that goal, because they let us prove other
442
- // things but not `Clone`.
443
- let self_ty = trait_ref. self_type_parameter ( interner) ;
444
- if let TyKind :: Dyn ( _) = self_ty. kind ( interner) {
445
- dyn_ty:: build_dyn_self_ty_clauses ( db, builder, self_ty. clone ( ) )
446
- }
447
-
448
- match self_ty. kind ( interner) {
449
- TyKind :: OpaqueType ( opaque_ty_id, _)
450
- | TyKind :: Alias ( AliasTy :: Opaque ( OpaqueTy { opaque_ty_id, .. } ) ) => {
451
- db. opaque_ty_data ( * opaque_ty_id)
452
- . to_program_clauses ( builder, environment) ;
453
- }
454
- _ => { }
455
- }
456
-
457
- // We don't actually do anything here, but we need to record the types it when logging
458
- match self_ty. kind ( interner) {
459
- TyKind :: Adt ( adt_id, _) => {
460
- let _ = db. adt_datum ( * adt_id) ;
461
- }
462
- TyKind :: FnDef ( fn_def_id, _) => {
463
- let _ = db. fn_def_datum ( * fn_def_id) ;
464
- }
465
- _ => { }
466
- }
467
-
468
468
if let Some ( well_known) = trait_datum. well_known {
469
469
builtin_traits:: add_builtin_program_clauses (
470
470
db, builder, well_known, trait_ref, binders,
@@ -478,21 +478,26 @@ fn program_clauses_that_could_match<I: Interner>(
478
478
. self_type_parameter ( interner) ;
479
479
480
480
match trait_self_ty. kind ( interner) {
481
- TyKind :: OpaqueType ( opaque_ty_id, _)
482
- | TyKind :: Alias ( AliasTy :: Opaque ( OpaqueTy { opaque_ty_id, .. } ) ) => {
481
+ TyKind :: Alias ( alias) => {
482
+ // An alias could normalize to anything, including an
483
+ // opaque type, so push a clause that asks for the self
484
+ // type to be normalized and return.
485
+ push_alias_alias_eq_clause ( builder, proj, & alias_eq. ty , alias) ;
486
+ return Ok ( clauses) ;
487
+ }
488
+ TyKind :: OpaqueType ( opaque_ty_id, _) => {
483
489
db. opaque_ty_data ( * opaque_ty_id)
484
490
. to_program_clauses ( builder, environment) ;
485
491
}
492
+ // If the self type is a `dyn trait` type, generate program-clauses
493
+ // for any associated type bindings it contains.
494
+ // FIXME: see the fixme for the analogous code for Implemented goals.
495
+ TyKind :: Dyn ( _) => {
496
+ dyn_ty:: build_dyn_self_ty_clauses ( db, builder, trait_self_ty. clone ( ) )
497
+ }
486
498
_ => { }
487
499
}
488
500
489
- // If the self type is a `dyn trait` type, generate program-clauses
490
- // for any associated type bindings it contains.
491
- // FIXME: see the fixme for the analogous code for Implemented goals.
492
- if let TyKind :: Dyn ( _) = trait_self_ty. kind ( interner) {
493
- dyn_ty:: build_dyn_self_ty_clauses ( db, builder, trait_self_ty. clone ( ) )
494
- }
495
-
496
501
db. associated_ty_data ( proj. associated_ty_id )
497
502
. to_program_clauses ( builder, environment)
498
503
}
@@ -708,6 +713,97 @@ fn push_program_clauses_for_associated_type_values_in_impls_of<I: Interner>(
708
713
}
709
714
}
710
715
716
+ fn push_alias_implemented_clause < I : Interner > (
717
+ builder : & mut ClauseBuilder < ' _ , I > ,
718
+ trait_ref : & TraitRef < I > ,
719
+ alias : & AliasTy < I > ,
720
+ ) {
721
+ let interner = builder. interner ( ) ;
722
+ assert_eq ! (
723
+ * trait_ref. self_type_parameter( interner) . kind( interner) ,
724
+ TyKind :: Alias ( alias. clone( ) )
725
+ ) ;
726
+
727
+ let binders = Binders :: with_fresh_type_var ( interner, |ty_var| ty_var) ;
728
+
729
+ // forall<..., T> {
730
+ // <X as Y>::Z: Trait :- T: Trait, <X as Y>::Z == T
731
+ // }
732
+ builder. push_binders ( & binders, |builder, bound_var| {
733
+ let fresh_self_subst = Substitution :: from_iter (
734
+ interner,
735
+ std:: iter:: once ( bound_var. clone ( ) . cast ( interner) ) . chain (
736
+ trait_ref. substitution . as_slice ( interner) [ 1 ..]
737
+ . iter ( )
738
+ . cloned ( ) ,
739
+ ) ,
740
+ ) ;
741
+ let fresh_self_trait_ref = TraitRef {
742
+ trait_id : trait_ref. trait_id ,
743
+ substitution : fresh_self_subst,
744
+ } ;
745
+ builder. push_clause (
746
+ DomainGoal :: Holds ( WhereClause :: Implemented ( trait_ref. clone ( ) ) ) ,
747
+ & [
748
+ DomainGoal :: Holds ( WhereClause :: Implemented ( fresh_self_trait_ref) ) ,
749
+ DomainGoal :: Holds ( WhereClause :: AliasEq ( AliasEq {
750
+ alias : alias. clone ( ) ,
751
+ ty : bound_var,
752
+ } ) ) ,
753
+ ] ,
754
+ ) ;
755
+ } ) ;
756
+ }
757
+
758
+ fn push_alias_alias_eq_clause < I : Interner > (
759
+ builder : & mut ClauseBuilder < ' _ , I > ,
760
+ projection_ty : & ProjectionTy < I > ,
761
+ ty : & Ty < I > ,
762
+ alias : & AliasTy < I > ,
763
+ ) {
764
+ let interner = builder. interner ( ) ;
765
+ assert_eq ! (
766
+ * projection_ty. self_type_parameter( interner) . kind( interner) ,
767
+ TyKind :: Alias ( alias. clone( ) )
768
+ ) ;
769
+
770
+ let binders = Binders :: with_fresh_type_var ( interner, |ty_var| ty_var) ;
771
+
772
+ // forall<..., T> {
773
+ // <<X as Y>::A as Z>::B == U :- <T as Z>::B == U, <X as Y>::A == T
774
+ // }
775
+ builder. push_binders ( & binders, |builder, bound_var| {
776
+ let fresh_self_subst = Substitution :: from_iter (
777
+ interner,
778
+ std:: iter:: once ( bound_var. clone ( ) . cast ( interner) ) . chain (
779
+ projection_ty. substitution . as_slice ( interner) [ 1 ..]
780
+ . iter ( )
781
+ . cloned ( ) ,
782
+ ) ,
783
+ ) ;
784
+ let fresh_alias = AliasTy :: Projection ( ProjectionTy {
785
+ associated_ty_id : projection_ty. associated_ty_id ,
786
+ substitution : fresh_self_subst,
787
+ } ) ;
788
+ builder. push_clause (
789
+ DomainGoal :: Holds ( WhereClause :: AliasEq ( AliasEq {
790
+ alias : AliasTy :: Projection ( projection_ty. clone ( ) ) ,
791
+ ty : ty. clone ( ) ,
792
+ } ) ) ,
793
+ & [
794
+ DomainGoal :: Holds ( WhereClause :: AliasEq ( AliasEq {
795
+ alias : fresh_alias,
796
+ ty : ty. clone ( ) ,
797
+ } ) ) ,
798
+ DomainGoal :: Holds ( WhereClause :: AliasEq ( AliasEq {
799
+ alias : alias. clone ( ) ,
800
+ ty : bound_var,
801
+ } ) ) ,
802
+ ] ,
803
+ ) ;
804
+ } ) ;
805
+ }
806
+
711
807
/// Examine `T` and push clauses that may be relevant to proving the
712
808
/// following sorts of goals (and maybe others):
713
809
///
0 commit comments