@@ -11,6 +11,7 @@ use chalk_ir::interner::Interner;
11
11
use chalk_ir:: * ;
12
12
use rustc_hash:: FxHashSet ;
13
13
use std:: iter;
14
+ use std:: marker:: PhantomData ;
14
15
use tracing:: { debug, instrument} ;
15
16
16
17
pub mod builder;
@@ -583,7 +584,7 @@ pub fn program_clauses_that_could_match<I: Interner>(
583
584
| DomainGoal :: IsUpstream ( ty)
584
585
| DomainGoal :: DownstreamType ( ty)
585
586
| DomainGoal :: IsFullyVisible ( ty)
586
- | DomainGoal :: IsLocal ( ty) => match_ty ( builder, environment, ty) ?,
587
+ | DomainGoal :: IsLocal ( ty) => match_ty ( builder, environment, & ty) ?,
587
588
DomainGoal :: FromEnv ( _) => ( ) , // Computed in the environment
588
589
DomainGoal :: Normalize ( Normalize { alias, ty : _ } ) => match alias {
589
590
AliasTy :: Projection ( proj) => {
@@ -885,43 +886,150 @@ fn match_ty<I: Interner>(
885
886
. db
886
887
. fn_def_datum ( * fn_def_id)
887
888
. to_program_clauses ( builder, environment) ,
888
- TyKind :: Str | TyKind :: Never | TyKind :: Scalar ( _) | TyKind :: Foreign ( _) => {
889
+ TyKind :: Str
890
+ | TyKind :: Never
891
+ | TyKind :: Scalar ( _)
892
+ | TyKind :: Foreign ( _)
893
+ | TyKind :: Tuple ( 0 , _) => {
889
894
// These have no substitutions, so they are trivially WF
890
895
builder. push_fact ( WellFormed :: Ty ( ty. clone ( ) ) ) ;
891
896
}
892
897
TyKind :: Raw ( mutbl, _) => {
898
+ // forall<T> WF(*const T) :- WF(T);
893
899
builder. push_bound_ty ( |builder, ty| {
894
- builder. push_fact ( WellFormed :: Ty (
895
- TyKind :: Raw ( * mutbl, ty) . intern ( builder. interner ( ) ) ,
896
- ) ) ;
900
+ builder. push_clause (
901
+ WellFormed :: Ty ( TyKind :: Raw ( * mutbl, ty. clone ( ) ) . intern ( builder. interner ( ) ) ) ,
902
+ Some ( WellFormed :: Ty ( ty) ) ,
903
+ ) ;
897
904
} ) ;
898
905
}
899
906
TyKind :: Ref ( mutbl, _, _) => {
907
+ // forall<'a, T> WF(&'a T) :- WF(T), T: 'a
900
908
builder. push_bound_ty ( |builder, ty| {
901
909
builder. push_bound_lifetime ( |builder, lifetime| {
902
- builder. push_fact ( WellFormed :: Ty (
903
- TyKind :: Ref ( * mutbl, lifetime, ty) . intern ( builder. interner ( ) ) ,
904
- ) ) ;
910
+ let ref_ty = TyKind :: Ref ( * mutbl, lifetime. clone ( ) , ty. clone ( ) )
911
+ . intern ( builder. interner ( ) ) ;
912
+ builder. push_clause (
913
+ WellFormed :: Ty ( ref_ty) ,
914
+ [
915
+ DomainGoal :: WellFormed ( WellFormed :: Ty ( ty. clone ( ) ) ) ,
916
+ DomainGoal :: Holds ( WhereClause :: TypeOutlives ( TypeOutlives {
917
+ ty,
918
+ lifetime,
919
+ } ) ) ,
920
+ ] ,
921
+ ) ;
905
922
} )
906
923
} ) ;
907
924
}
908
925
TyKind :: Slice ( _) => {
926
+ // forall<T> WF([T]) :- T: Sized, WF(T)
909
927
builder. push_bound_ty ( |builder, ty| {
910
- builder. push_fact ( WellFormed :: Ty ( TyKind :: Slice ( ty) . intern ( builder. interner ( ) ) ) ) ;
928
+ let sized = builder. db . well_known_trait_id ( WellKnownTrait :: Sized ) ;
929
+ builder. push_clause (
930
+ WellFormed :: Ty ( TyKind :: Slice ( ty. clone ( ) ) . intern ( builder. interner ( ) ) ) ,
931
+ sized
932
+ . map ( |id| {
933
+ DomainGoal :: Holds ( WhereClause :: Implemented ( TraitRef {
934
+ trait_id : id,
935
+ substitution : Substitution :: from1 ( interner, ty. clone ( ) ) ,
936
+ } ) )
937
+ } )
938
+ . into_iter ( )
939
+ . chain ( Some ( DomainGoal :: WellFormed ( WellFormed :: Ty ( ty) ) ) ) ,
940
+ ) ;
911
941
} ) ;
912
942
}
913
- TyKind :: Tuple ( _, _)
914
- | TyKind :: Array ( _, _)
915
- | TyKind :: Closure ( _, _)
916
- | TyKind :: Generator ( _, _)
917
- | TyKind :: GeneratorWitness ( _, _) => {
943
+ TyKind :: Array ( ..) => {
944
+ // forall<T. const N: usize> WF([T, N]) :- T: Sized
945
+ let interner = builder. interner ( ) ;
946
+ let binders = Binders :: new (
947
+ VariableKinds :: from_iter (
948
+ interner,
949
+ [
950
+ VariableKind :: Ty ( TyVariableKind :: General ) ,
951
+ VariableKind :: Const (
952
+ TyKind :: Scalar ( Scalar :: Uint ( UintTy :: Usize ) ) . intern ( interner) ,
953
+ ) ,
954
+ ] ,
955
+ ) ,
956
+ PhantomData :: < I > ,
957
+ ) ;
958
+ builder. push_binders ( binders, |builder, PhantomData | {
959
+ let placeholders_in_scope = builder. placeholders_in_scope ( ) ;
960
+ let placeholder_count = placeholders_in_scope. len ( ) ;
961
+ let ty = placeholders_in_scope[ placeholder_count - 2 ]
962
+ . assert_ty_ref ( interner)
963
+ . clone ( ) ;
964
+ let size = placeholders_in_scope[ placeholder_count - 1 ]
965
+ . assert_const_ref ( interner)
966
+ . clone ( ) ;
967
+
968
+ let sized = builder. db . well_known_trait_id ( WellKnownTrait :: Sized ) ;
969
+ let array_ty = TyKind :: Array ( ty. clone ( ) , size) . intern ( interner) ;
970
+ builder. push_clause (
971
+ WellFormed :: Ty ( array_ty) ,
972
+ sized
973
+ . map ( |id| {
974
+ DomainGoal :: Holds ( WhereClause :: Implemented ( TraitRef {
975
+ trait_id : id,
976
+ substitution : Substitution :: from1 ( interner, ty. clone ( ) ) ,
977
+ } ) )
978
+ } )
979
+ . into_iter ( )
980
+ . chain ( Some ( DomainGoal :: WellFormed ( WellFormed :: Ty ( ty) ) ) ) ,
981
+ ) ;
982
+ } ) ;
983
+ }
984
+ TyKind :: Tuple ( len, _) => {
985
+ // WF((T0, ..., Tn, U)) :- T0: Sized, ..., Tn: Sized, WF(T0), ..., WF(Tn), WF(U)
986
+ let interner = builder. interner ( ) ;
987
+ let binders = Binders :: new (
988
+ VariableKinds :: from_iter (
989
+ interner,
990
+ iter:: repeat_with ( || VariableKind :: Ty ( TyVariableKind :: General ) ) . take ( * len) ,
991
+ ) ,
992
+ PhantomData :: < I > ,
993
+ ) ;
994
+ builder. push_binders ( binders, |builder, PhantomData | {
995
+ let placeholders_in_scope = builder. placeholders_in_scope ( ) ;
996
+
997
+ let substs = Substitution :: from_iter (
998
+ builder. interner ( ) ,
999
+ & placeholders_in_scope[ placeholders_in_scope. len ( ) - len..] ,
1000
+ ) ;
1001
+
1002
+ let tuple_ty = TyKind :: Tuple ( * len, substs. clone ( ) ) . intern ( interner) ;
1003
+ let sized = builder. db . well_known_trait_id ( WellKnownTrait :: Sized ) ;
1004
+ builder. push_clause (
1005
+ WellFormed :: Ty ( tuple_ty) ,
1006
+ substs. as_slice ( interner) [ ..* len - 1 ]
1007
+ . iter ( )
1008
+ . filter_map ( |s| {
1009
+ let ty_var = s. assert_ty_ref ( interner) . clone ( ) ;
1010
+ sized. map ( |id| {
1011
+ DomainGoal :: Holds ( WhereClause :: Implemented ( TraitRef {
1012
+ trait_id : id,
1013
+ substitution : Substitution :: from1 ( interner, ty_var) ,
1014
+ } ) )
1015
+ } )
1016
+ } )
1017
+ . chain ( substs. iter ( interner) . map ( |subst| {
1018
+ DomainGoal :: WellFormed ( WellFormed :: Ty (
1019
+ subst. assert_ty_ref ( interner) . clone ( ) ,
1020
+ ) )
1021
+ } ) ) ,
1022
+ ) ;
1023
+ } ) ;
1024
+ }
1025
+ TyKind :: Closure ( _, _) | TyKind :: Generator ( _, _) | TyKind :: GeneratorWitness ( _, _) => {
918
1026
let ty = generalize:: Generalize :: apply ( builder. db . interner ( ) , ty. clone ( ) ) ;
919
1027
builder. push_binders ( ty, |builder, ty| {
920
1028
builder. push_fact ( WellFormed :: Ty ( ty. clone ( ) ) ) ;
921
1029
} ) ;
922
1030
}
923
1031
TyKind :: Placeholder ( _) => {
924
- builder. push_clause ( WellFormed :: Ty ( ty. clone ( ) ) , Some ( FromEnv :: Ty ( ty . clone ( ) ) ) ) ;
1032
+ builder. push_fact ( WellFormed :: Ty ( ty. clone ( ) ) ) ;
925
1033
}
926
1034
TyKind :: Alias ( AliasTy :: Projection ( proj) ) => builder
927
1035
. db
@@ -945,30 +1053,35 @@ fn match_ty<I: Interner>(
945
1053
// - Bounds on the associated types
946
1054
// - Checking that all associated types are specified, including
947
1055
// those on supertraits.
948
- // - For trait objects with GATs, check that the bounds are fully
949
- // general (`dyn for<'a> StreamingIterator<Item<'a> = &'a ()>` is OK,
1056
+ // - For trait objects with GATs, if we allow them in the future,
1057
+ // check that the bounds are fully general (
1058
+ // `dyn for<'a> StreamingIterator<Item<'a> = &'a ()>` is OK,
950
1059
// `dyn StreamingIterator<Item<'static> = &'static ()>` is not).
951
- let bounds = dyn_ty
952
- . bounds
953
- . clone ( )
954
- . substitute ( interner, & [ ty. clone ( ) . cast :: < GenericArg < I > > ( interner) ] ) ;
955
-
956
- let mut wf_goals = Vec :: new ( ) ;
957
-
958
- wf_goals. extend ( bounds. iter ( interner) . flat_map ( |bound| {
959
- bound. map_ref ( |bound| -> Vec < _ > {
960
- match bound {
961
- WhereClause :: Implemented ( trait_ref) => {
962
- vec ! [ DomainGoal :: WellFormed ( WellFormed :: Trait ( trait_ref. clone( ) ) ) ]
1060
+ let generalized_ty =
1061
+ generalize:: Generalize :: apply ( builder. db . interner ( ) , dyn_ty. clone ( ) ) ;
1062
+ builder. push_binders ( generalized_ty, |builder, dyn_ty| {
1063
+ let bounds = dyn_ty
1064
+ . bounds
1065
+ . clone ( )
1066
+ . substitute ( interner, & [ ty. clone ( ) . cast :: < GenericArg < I > > ( interner) ] ) ;
1067
+
1068
+ let mut wf_goals = Vec :: new ( ) ;
1069
+
1070
+ wf_goals. extend ( bounds. iter ( interner) . flat_map ( |bound| {
1071
+ bound. map_ref ( |bound| -> Vec < _ > {
1072
+ match bound {
1073
+ WhereClause :: Implemented ( trait_ref) => {
1074
+ vec ! [ DomainGoal :: WellFormed ( WellFormed :: Trait ( trait_ref. clone( ) ) ) ]
1075
+ }
1076
+ WhereClause :: AliasEq ( _)
1077
+ | WhereClause :: LifetimeOutlives ( _)
1078
+ | WhereClause :: TypeOutlives ( _) => vec ! [ ] ,
963
1079
}
964
- WhereClause :: AliasEq ( _)
965
- | WhereClause :: LifetimeOutlives ( _)
966
- | WhereClause :: TypeOutlives ( _) => vec ! [ ] ,
967
- }
968
- } )
969
- } ) ) ;
1080
+ } )
1081
+ } ) ) ;
970
1082
971
- builder. push_clause ( WellFormed :: Ty ( ty. clone ( ) ) , wf_goals) ;
1083
+ builder. push_clause ( WellFormed :: Ty ( ty. clone ( ) ) , wf_goals) ;
1084
+ } ) ;
972
1085
}
973
1086
} )
974
1087
}
0 commit comments