@@ -11,6 +11,7 @@ use chalk_ir::interner::Interner;
1111use chalk_ir:: * ;
1212use rustc_hash:: FxHashSet ;
1313use std:: iter;
14+ use std:: marker:: PhantomData ;
1415use tracing:: { debug, instrument} ;
1516
1617pub mod builder;
@@ -583,7 +584,7 @@ pub fn program_clauses_that_could_match<I: Interner>(
583584 | DomainGoal :: IsUpstream ( ty)
584585 | DomainGoal :: DownstreamType ( ty)
585586 | DomainGoal :: IsFullyVisible ( ty)
586- | DomainGoal :: IsLocal ( ty) => match_ty ( builder, environment, ty) ?,
587+ | DomainGoal :: IsLocal ( ty) => match_ty ( builder, environment, & ty) ?,
587588 DomainGoal :: FromEnv ( _) => ( ) , // Computed in the environment
588589 DomainGoal :: Normalize ( Normalize { alias, ty : _ } ) => match alias {
589590 AliasTy :: Projection ( proj) => {
@@ -885,43 +886,150 @@ fn match_ty<I: Interner>(
885886 . db
886887 . fn_def_datum ( * fn_def_id)
887888 . 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 , _) => {
889894 // These have no substitutions, so they are trivially WF
890895 builder. push_fact ( WellFormed :: Ty ( ty. clone ( ) ) ) ;
891896 }
892897 TyKind :: Raw ( mutbl, _) => {
898+ // forall<T> WF(*const T) :- WF(T);
893899 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+ ) ;
897904 } ) ;
898905 }
899906 TyKind :: Ref ( mutbl, _, _) => {
907+ // forall<'a, T> WF(&'a T) :- WF(T), T: 'a
900908 builder. push_bound_ty ( |builder, ty| {
901909 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+ ) ;
905922 } )
906923 } ) ;
907924 }
908925 TyKind :: Slice ( _) => {
926+ // forall<T> WF([T]) :- T: Sized, WF(T)
909927 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+ ) ;
911941 } ) ;
912942 }
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 ( _, _) => {
9181026 let ty = generalize:: Generalize :: apply ( builder. db . interner ( ) , ty. clone ( ) ) ;
9191027 builder. push_binders ( ty, |builder, ty| {
9201028 builder. push_fact ( WellFormed :: Ty ( ty. clone ( ) ) ) ;
9211029 } ) ;
9221030 }
9231031 TyKind :: Placeholder ( _) => {
924- builder. push_clause ( WellFormed :: Ty ( ty. clone ( ) ) , Some ( FromEnv :: Ty ( ty . clone ( ) ) ) ) ;
1032+ builder. push_fact ( WellFormed :: Ty ( ty. clone ( ) ) ) ;
9251033 }
9261034 TyKind :: Alias ( AliasTy :: Projection ( proj) ) => builder
9271035 . db
@@ -945,30 +1053,35 @@ fn match_ty<I: Interner>(
9451053 // - Bounds on the associated types
9461054 // - Checking that all associated types are specified, including
9471055 // 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,
9501059 // `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 ! [ ] ,
9631079 }
964- WhereClause :: AliasEq ( _)
965- | WhereClause :: LifetimeOutlives ( _)
966- | WhereClause :: TypeOutlives ( _) => vec ! [ ] ,
967- }
968- } )
969- } ) ) ;
1080+ } )
1081+ } ) ) ;
9701082
971- builder. push_clause ( WellFormed :: Ty ( ty. clone ( ) ) , wf_goals) ;
1083+ builder. push_clause ( WellFormed :: Ty ( ty. clone ( ) ) , wf_goals) ;
1084+ } ) ;
9721085 }
9731086 } )
9741087}
0 commit comments