@@ -75,8 +75,10 @@ fn constituent_types<I: Interner>(db: &dyn RustIrDatabase<I>, ty: &TyKind<I>) ->
75
75
TyKind :: Alias ( _) => panic ! ( "this function should not be called for alias" ) ,
76
76
TyKind :: Foreign ( _) => panic ! ( "constituent_types of foreign types are unknown!" ) ,
77
77
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
+ }
80
82
}
81
83
}
82
84
@@ -176,12 +178,16 @@ pub fn push_auto_trait_impls<I: Interner>(
176
178
Ok ( ( ) )
177
179
}
178
180
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
+ }
182
185
183
186
// No auto traits
184
- TyKind :: Placeholder ( _) | TyKind :: Dyn ( _) | TyKind :: Alias ( _) => Ok ( ( ) ) ,
187
+ TyKind :: AssociatedType ( _, _)
188
+ | TyKind :: Placeholder ( _)
189
+ | TyKind :: Dyn ( _)
190
+ | TyKind :: Alias ( _) => Ok ( ( ) ) ,
185
191
186
192
// app_ty implements AutoTrait if all constituents of app_ty implement AutoTrait
187
193
_ => {
@@ -383,20 +389,56 @@ fn program_clauses_that_could_match<I: Interner>(
383
389
384
390
match goal {
385
391
DomainGoal :: Holds ( WhereClause :: Implemented ( trait_ref) ) => {
386
- let trait_id = trait_ref. trait_id ;
392
+ let self_ty = trait_ref. self_type_parameter ( interner ) ;
387
393
394
+ let trait_id = trait_ref. trait_id ;
388
395
let trait_datum = db. trait_datum ( trait_id) ;
389
396
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
+ }
392
405
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 ) ;
396
409
}
397
- } else if self_ty. is_general_var ( interner, binders) {
398
- return Err ( Floundered ) ;
399
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
+ _ => { }
400
442
}
401
443
402
444
// This is needed for the coherence related impls, as well
@@ -423,42 +465,6 @@ fn program_clauses_that_could_match<I: Interner>(
423
465
} ) ?;
424
466
}
425
467
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
-
462
468
if let Some ( well_known) = trait_datum. well_known {
463
469
builtin_traits:: add_builtin_program_clauses (
464
470
db, builder, well_known, trait_ref, binders,
@@ -472,21 +478,26 @@ fn program_clauses_that_could_match<I: Interner>(
472
478
. self_type_parameter ( interner) ;
473
479
474
480
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, _) => {
477
489
db. opaque_ty_data ( * opaque_ty_id)
478
490
. to_program_clauses ( builder, environment) ;
479
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
+ }
480
498
_ => { }
481
499
}
482
500
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
-
490
501
db. associated_ty_data ( proj. associated_ty_id )
491
502
. to_program_clauses ( builder, environment)
492
503
}
@@ -702,6 +713,97 @@ fn push_program_clauses_for_associated_type_values_in_impls_of<I: Interner>(
702
713
}
703
714
}
704
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
+
705
807
/// Examine `T` and push clauses that may be relevant to proving the
706
808
/// following sorts of goals (and maybe others):
707
809
///
@@ -764,7 +866,37 @@ fn match_ty<I: Interner>(
764
866
builder. push_fact ( WellFormed :: Ty ( ty. clone ( ) ) ) ;
765
867
}
766
868
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
+ }
768
900
} )
769
901
}
770
902
0 commit comments