@@ -41,6 +41,7 @@ impl Program {
4141 }
4242}
4343
44+ /// A trait for retrieving all types appearing in some Chalk construction.
4445trait FoldInputTypes {
4546 fn fold ( & self , accumulator : & mut Vec < Ty > ) ;
4647}
@@ -77,7 +78,10 @@ impl FoldInputTypes for Ty {
7778 accumulator. push ( self . clone ( ) ) ;
7879 proj. parameters . fold ( accumulator) ;
7980 }
80- _ => ( ) ,
81+
82+ // Type parameters and higher-kinded types do not carry any input types (so we can sort
83+ // of assume they are always WF).
84+ Ty :: Var ( ..) | Ty :: ForAll ( ..) => ( ) ,
8185 }
8286 }
8387}
@@ -108,13 +112,15 @@ impl FoldInputTypes for DomainGoal {
108112 DomainGoal :: Implemented ( ref tr) => tr. fold ( accumulator) ,
109113 DomainGoal :: Normalize ( ref n) => n. fold ( accumulator) ,
110114 DomainGoal :: UnselectedNormalize ( ref n) => n. fold ( accumulator) ,
115+ DomainGoal :: WellFormed ( ..) | DomainGoal :: FromEnv ( ..) => panic ! ( "unexpected where clause" ) ,
111116 _ => ( ) ,
112117 }
113118 }
114119}
115120
116121impl WfSolver {
117122 fn verify_struct_decl ( & self , struct_datum : & StructDatum ) -> bool {
123+ // We retrieve all the input types of the struct fields.
118124 let mut input_types = Vec :: new ( ) ;
119125 struct_datum. binders . value . fields . fold ( & mut input_types) ;
120126 struct_datum. binders . value . where_clauses . fold ( & mut input_types) ;
@@ -124,7 +130,6 @@ impl WfSolver {
124130 }
125131
126132 let goals = input_types. into_iter ( ) . map ( |ty| WellFormed :: Ty ( ty) . cast ( ) ) ;
127-
128133 let goal = goals. fold1 ( |goal, leaf| Goal :: And ( Box :: new ( goal) , Box :: new ( leaf) ) )
129134 . expect ( "at least one goal" ) ;
130135
@@ -137,6 +142,8 @@ impl WfSolver {
137142 . map ( |wc| wc. into_from_env_clause ( ) )
138143 . collect ( ) ;
139144
145+ // We ask that the above input types are well-formed provided that all the where-clauses
146+ // on the struct definition hold.
140147 let goal = Goal :: Implies ( hypotheses, Box :: new ( goal) )
141148 . quantify ( QuantifierKind :: ForAll , struct_datum. binders . binders . clone ( ) ) ;
142149
@@ -152,9 +159,62 @@ impl WfSolver {
152159 _ => return true
153160 } ;
154161
162+ // We retrieve all the input types of the where clauses appearing on the trait impl,
163+ // e.g. in:
164+ // ```
165+ // impl<T, K> Foo for (Set<K>, Vec<Box<T>>) { ... }
166+ // ```
167+ // we would retrieve `Set<K>`, `Box<T>`, `Vec<Box<T>>`, `(Set<K>, Vec<Box<T>>)`.
168+ // We will have to prove that these types are well-formed.
155169 let mut input_types = Vec :: new ( ) ;
156170 impl_datum. binders . value . where_clauses . fold ( & mut input_types) ;
157171
172+ // We partition the input types of the type on which we implement the trait in two categories:
173+ // * projection types, e.g. `<T as Iterator>::Item`: we will have to prove that these types
174+ // are well-formed, e.g. that we can show that `T: Iterator` holds
175+ // * any other types, e.g. `HashSet<K>`: we will *assume* that these types are well-formed, e.g.
176+ // we will be able to derive that `K: Hash` holds without writing any where clause.
177+ //
178+ // Examples:
179+ // ```
180+ // struct HashSet<K> where K: Hash { ... }
181+ //
182+ // impl<K> Foo for HashSet<K> {
183+ // // Inside here, we can rely on the fact that `K: Hash` holds
184+ // }
185+ // ```
186+ //
187+ // ```
188+ // impl<T> Foo for <T as Iterator>::Item {
189+ // // The impl is not well-formed, as an exception we do not assume that
190+ // // `<T as Iterator>::Item` is well-formed and instead want to prove it.
191+ // }
192+ // ```
193+ //
194+ // ```
195+ // impl<T> Foo for <T as Iterator>::Item where T: Iterator {
196+ // // Now ok.
197+ // }
198+ // ```
199+ let mut header_input_types = Vec :: new ( ) ;
200+ trait_ref. fold ( & mut header_input_types) ;
201+ let ( header_projection_types, header_other_types) : ( Vec < _ > , Vec < _ > ) =
202+ header_input_types. into_iter ( )
203+ . partition ( |ty| ty. is_projection ( ) ) ;
204+
205+ // Associated type values are special because they can be parametric (independently of
206+ // the impl), so we issue a special goal which is quantified using the binders of the
207+ // associated type value, for example in:
208+ // ```
209+ // trait Foo {
210+ // type Item<'a>
211+ // }
212+ //
213+ // impl<T> Foo for Box<T> {
214+ // type Item<'a> = Box<&'a T>;
215+ // }
216+ // ```
217+ // we would issue the following subgoal: `forall<'a> { WellFormed(Box<&'a T>) }`.
158218 let compute_assoc_ty_goal = |assoc_ty : & AssociatedTyValue | {
159219 let mut input_types = Vec :: new ( ) ;
160220 assoc_ty. value . value . ty . fold ( & mut input_types) ;
@@ -176,12 +236,8 @@ impl WfSolver {
176236 . iter ( )
177237 . filter_map ( compute_assoc_ty_goal) ;
178238
179- let mut header_input_types = Vec :: new ( ) ;
180- trait_ref. fold ( & mut header_input_types) ;
181- let ( header_projection_types, header_other_types) : ( Vec < _ > , Vec < _ > ) =
182- header_input_types. into_iter ( )
183- . partition ( |ty| ty. is_projection ( ) ) ;
184-
239+ // Things to prove well-formed: input types of the where-clauses, projection types
240+ // appearing in the header, associated type values, and of course the trait ref.
185241 let goals =
186242 input_types. into_iter ( )
187243 . chain ( header_projection_types. into_iter ( ) )
@@ -191,6 +247,10 @@ impl WfSolver {
191247
192248 let goal = goals. fold1 ( |goal, leaf| Goal :: And ( Box :: new ( goal) , Box :: new ( leaf) ) )
193249 . expect ( "at least one goal" ) ;
250+
251+ // Assumptions: types appearing in the header which are not projection types are
252+ // assumed to be well-formed, and where clauses declared on the impl are assumed
253+ // to hold.
194254 let hypotheses =
195255 impl_datum. binders
196256 . value
0 commit comments