@@ -389,20 +389,56 @@ fn program_clauses_that_could_match<I: Interner>(
389389
390390 match goal {
391391 DomainGoal :: Holds ( WhereClause :: Implemented ( trait_ref) ) => {
392- let trait_id = trait_ref. trait_id ;
392+ let self_ty = trait_ref. self_type_parameter ( interner ) ;
393393
394+ let trait_id = trait_ref. trait_id ;
394395 let trait_datum = db. trait_datum ( trait_id) ;
395396
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+ }
398405
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 ) ;
402409 }
403- } else if self_ty. is_general_var ( interner, binders) {
404- return Err ( Floundered ) ;
405410 }
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+ _ => { }
406442 }
407443
408444 // This is needed for the coherence related impls, as well
@@ -429,42 +465,6 @@ fn program_clauses_that_could_match<I: Interner>(
429465 } ) ?;
430466 }
431467
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-
468468 if let Some ( well_known) = trait_datum. well_known {
469469 builtin_traits:: add_builtin_program_clauses (
470470 db, builder, well_known, trait_ref, binders,
@@ -478,21 +478,26 @@ fn program_clauses_that_could_match<I: Interner>(
478478 . self_type_parameter ( interner) ;
479479
480480 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, _) => {
483489 db. opaque_ty_data ( * opaque_ty_id)
484490 . to_program_clauses ( builder, environment) ;
485491 }
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+ }
486498 _ => { }
487499 }
488500
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-
496501 db. associated_ty_data ( proj. associated_ty_id )
497502 . to_program_clauses ( builder, environment)
498503 }
@@ -708,6 +713,97 @@ fn push_program_clauses_for_associated_type_values_in_impls_of<I: Interner>(
708713 }
709714}
710715
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+
711807/// Examine `T` and push clauses that may be relevant to proving the
712808/// following sorts of goals (and maybe others):
713809///
0 commit comments