@@ -75,8 +75,10 @@ fn constituent_types<I: Interner>(db: &dyn RustIrDatabase<I>, ty: &TyKind<I>) ->
7575 TyKind :: Alias ( _) => panic ! ( "this function should not be called for alias" ) ,
7676 TyKind :: Foreign ( _) => panic ! ( "constituent_types of foreign types are unknown!" ) ,
7777 TyKind :: Error => Vec :: new ( ) ,
78- TyKind :: OpaqueType ( _, _) => unimplemented ! ( ) ,
79- TyKind :: AssociatedType ( _, _) => unimplemented ! ( ) ,
78+ TyKind :: OpaqueType ( _, _) => panic ! ( "constituent_types of opaque types are unknown!" ) ,
79+ TyKind :: AssociatedType ( _, _) => {
80+ panic ! ( "constituent_types of associated types are unknown!" )
81+ }
8082 }
8183}
8284
@@ -176,12 +178,16 @@ pub fn push_auto_trait_impls<I: Interner>(
176178 Ok ( ( ) )
177179 }
178180
179- // Unimplemented
180- TyKind :: OpaqueType ( _, _) => Ok ( ( ) ) ,
181- TyKind :: AssociatedType ( _, _) => Ok ( ( ) ) ,
181+ TyKind :: OpaqueType ( opaque_ty_id, _) => {
182+ push_auto_trait_impls_opaque ( builder, auto_trait_id, * opaque_ty_id) ;
183+ Ok ( ( ) )
184+ }
182185
183186 // No auto traits
184- TyKind :: Placeholder ( _) | TyKind :: Dyn ( _) | TyKind :: Alias ( _) => Ok ( ( ) ) ,
187+ TyKind :: AssociatedType ( _, _)
188+ | TyKind :: Placeholder ( _)
189+ | TyKind :: Dyn ( _)
190+ | TyKind :: Alias ( _) => Ok ( ( ) ) ,
185191
186192 // app_ty implements AutoTrait if all constituents of app_ty implement AutoTrait
187193 _ => {
@@ -383,20 +389,56 @@ fn program_clauses_that_could_match<I: Interner>(
383389
384390 match goal {
385391 DomainGoal :: Holds ( WhereClause :: Implemented ( trait_ref) ) => {
386- let trait_id = trait_ref. trait_id ;
392+ let self_ty = trait_ref. self_type_parameter ( interner ) ;
387393
394+ let trait_id = trait_ref. trait_id ;
388395 let trait_datum = db. trait_datum ( trait_id) ;
389396
390- if trait_datum. is_non_enumerable_trait ( ) || trait_datum. is_auto_trait ( ) {
391- 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+ }
392405
393- if let TyKind :: Alias ( AliasTy :: Opaque ( opaque_ty ) ) = self_ty. kind ( interner) {
394- if trait_datum. is_auto_trait ( ) {
395- 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 ) ;
396409 }
397- } else if self_ty. is_general_var ( interner, binders) {
398- return Err ( Floundered ) ;
399410 }
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+ _ => { }
400442 }
401443
402444 // This is needed for the coherence related impls, as well
@@ -423,42 +465,6 @@ fn program_clauses_that_could_match<I: Interner>(
423465 } ) ?;
424466 }
425467
426- // If the self type is a `dyn trait` type, generate program-clauses
427- // that indicates that it implements its own traits.
428- // FIXME: This is presently rather wasteful, in that we don't check that the
429- // these program clauses we are generating are actually relevant to the goal
430- // `goal` that we are actually *trying* to prove (though there is some later
431- // code that will screen out irrelevant stuff).
432- //
433- // In other words, if we were trying to prove `Implemented(dyn
434- // Fn(&u8): Clone)`, we would still generate two clauses that are
435- // totally irrelevant to that goal, because they let us prove other
436- // things but not `Clone`.
437- let self_ty = trait_ref. self_type_parameter ( interner) ;
438- if let TyKind :: Dyn ( _) = self_ty. kind ( interner) {
439- dyn_ty:: build_dyn_self_ty_clauses ( db, builder, self_ty. clone ( ) )
440- }
441-
442- match self_ty. kind ( interner) {
443- TyKind :: OpaqueType ( opaque_ty_id, _)
444- | TyKind :: Alias ( AliasTy :: Opaque ( OpaqueTy { opaque_ty_id, .. } ) ) => {
445- db. opaque_ty_data ( * opaque_ty_id)
446- . to_program_clauses ( builder, environment) ;
447- }
448- _ => { }
449- }
450-
451- // We don't actually do anything here, but we need to record the types it when logging
452- match self_ty. kind ( interner) {
453- TyKind :: Adt ( adt_id, _) => {
454- let _ = db. adt_datum ( * adt_id) ;
455- }
456- TyKind :: FnDef ( fn_def_id, _) => {
457- let _ = db. fn_def_datum ( * fn_def_id) ;
458- }
459- _ => { }
460- }
461-
462468 if let Some ( well_known) = trait_datum. well_known {
463469 builtin_traits:: add_builtin_program_clauses (
464470 db, builder, well_known, trait_ref, binders,
@@ -472,21 +478,26 @@ fn program_clauses_that_could_match<I: Interner>(
472478 . self_type_parameter ( interner) ;
473479
474480 match trait_self_ty. kind ( interner) {
475- TyKind :: OpaqueType ( opaque_ty_id, _)
476- | 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, _) => {
477489 db. opaque_ty_data ( * opaque_ty_id)
478490 . to_program_clauses ( builder, environment) ;
479491 }
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+ }
480498 _ => { }
481499 }
482500
483- // If the self type is a `dyn trait` type, generate program-clauses
484- // for any associated type bindings it contains.
485- // FIXME: see the fixme for the analogous code for Implemented goals.
486- if let TyKind :: Dyn ( _) = trait_self_ty. kind ( interner) {
487- dyn_ty:: build_dyn_self_ty_clauses ( db, builder, trait_self_ty. clone ( ) )
488- }
489-
490501 db. associated_ty_data ( proj. associated_ty_id )
491502 . to_program_clauses ( builder, environment)
492503 }
@@ -702,6 +713,97 @@ fn push_program_clauses_for_associated_type_values_in_impls_of<I: Interner>(
702713 }
703714}
704715
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+
705807/// Examine `T` and push clauses that may be relevant to proving the
706808/// following sorts of goals (and maybe others):
707809///
@@ -764,7 +866,37 @@ fn match_ty<I: Interner>(
764866 builder. push_fact ( WellFormed :: Ty ( ty. clone ( ) ) ) ;
765867 }
766868 TyKind :: BoundVar ( _) | TyKind :: InferenceVar ( _, _) => return Err ( Floundered ) ,
767- TyKind :: Dyn ( _) => { }
869+ TyKind :: Dyn ( dyn_ty) => {
870+ // FIXME(#203)
871+ // - Object safety? (not needed with RFC 2027)
872+ // - Implied bounds
873+ // - Bounds on the associated types
874+ // - Checking that all associated types are specified, including
875+ // those on supertraits.
876+ // - For trait objects with GATs, check that the bounds are fully
877+ // general (`dyn for<'a> StreamingIterator<Item<'a> = &'a ()>` is OK,
878+ // `dyn StreamingIterator<Item<'static> = &'static ()>` is not).
879+ let bounds = dyn_ty
880+ . bounds
881+ . substitute ( interner, & [ ty. clone ( ) . cast :: < GenericArg < I > > ( interner) ] ) ;
882+
883+ let mut wf_goals = Vec :: new ( ) ;
884+
885+ wf_goals. extend ( bounds. iter ( interner) . flat_map ( |bound| {
886+ bound. map_ref ( |bound| -> Vec < _ > {
887+ match bound {
888+ WhereClause :: Implemented ( trait_ref) => {
889+ vec ! [ DomainGoal :: WellFormed ( WellFormed :: Trait ( trait_ref. clone( ) ) ) ]
890+ }
891+ WhereClause :: AliasEq ( _)
892+ | WhereClause :: LifetimeOutlives ( _)
893+ | WhereClause :: TypeOutlives ( _) => vec ! [ ] ,
894+ }
895+ } )
896+ } ) ) ;
897+
898+ builder. push_clause ( WellFormed :: Ty ( ty. clone ( ) ) , wf_goals) ;
899+ }
768900 } )
769901}
770902
0 commit comments