Skip to content

Commit f099845

Browse files
committed
extract impl_wf_environment helper
1 parent 10013b1 commit f099845

File tree

2 files changed

+66
-58
lines changed

2 files changed

+66
-58
lines changed

chalk-ir/src/cast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ reflexive_impl!(for(I: Interner) TraitRef<I>);
8080
reflexive_impl!(for(I: Interner) DomainGoal<I>);
8181
reflexive_impl!(for(I: Interner) Goal<I>);
8282
reflexive_impl!(for(I: Interner) WhereClause<I>);
83+
reflexive_impl!(for(I: Interner) ProgramClause<I>);
8384

8485
impl<I: Interner> CastTo<WhereClause<I>> for TraitRef<I> {
8586
fn cast_to(self, _interner: &I) -> WhereClause<I> {

chalk-solve/src/wf.rs

Lines changed: 65 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -246,65 +246,37 @@ where
246246
|gb, impl_substitution, (trait_ref, where_clauses), associated_ty_value_ids| {
247247
let interner = gb.interner();
248248

249-
// if (WC) { ... }
250-
gb.implies(
251-
where_clauses
249+
// if (WC && input types are well formed) { ... }
250+
let impl_wf = Self::impl_wf_environment(interner, &where_clauses, &trait_ref);
251+
gb.implies(impl_wf, |gb| {
252+
let db = gb.db();
253+
254+
let assoc_ty_goals = associated_ty_value_ids
252255
.iter()
253-
.cloned()
254-
.map(|qwc| qwc.into_from_env_goal(interner)),
255-
|gb| {
256-
// We retrieve all the input types of the type on which we implement the trait: we will
257-
// *assume* that these types are well-formed, e.g. we will be able to derive that
258-
// `K: Hash` holds without writing any where clause.
259-
//
260-
// Example:
261-
// ```
262-
// struct HashSet<K> where K: Hash { ... }
263-
//
264-
// impl<K> Foo for HashSet<K> {
265-
// // Inside here, we can rely on the fact that `K: Hash` holds
266-
// }
267-
// ```
268-
let mut header_input_types = Vec::new();
269-
trait_ref.fold(interner, &mut header_input_types);
270-
271-
gb.implies(
272-
header_input_types
273-
.into_iter()
274-
.map(|ty| ty.into_from_env_goal(interner)),
275-
|gb| {
276-
let db = gb.db();
277-
278-
let assoc_ty_goals =
279-
associated_ty_value_ids.iter().filter_map(|&id| {
280-
Self::compute_assoc_ty_goal(db, &impl_substitution, id)
281-
});
282-
283-
// We retrieve all the input types of the where clauses appearing on the trait impl,
284-
// e.g. in:
285-
// ```
286-
// impl<T, K> Foo for (T, K) where T: Iterator<Item = (HashSet<K>, Vec<Box<T>>)> { ... }
287-
// ```
288-
// we would retrieve `HashSet<K>`, `Box<T>`, `Vec<Box<T>>`, `(HashSet<K>, Vec<Box<T>>)`.
289-
// We will have to prove that these types are well-formed (e.g. an additional `K: Hash`
290-
// bound would be needed here).
291-
let mut input_types = Vec::new();
292-
where_clauses.fold(interner, &mut input_types);
293-
294-
// Things to prove well-formed: input types of the where-clauses, projection types
295-
// appearing in the header, associated type values, and of course the trait ref.
296-
debug!("verify_trait_impl: input_types={:?}", input_types);
297-
let goals = input_types
298-
.into_iter()
299-
.map(|ty| ty.well_formed().cast(interner))
300-
.chain(assoc_ty_goals)
301-
.chain(Some(trait_ref.well_formed().cast(interner)));
302-
303-
gb.all(goals)
304-
},
305-
)
306-
},
307-
)
256+
.filter_map(|&id| Self::compute_assoc_ty_goal(db, &impl_substitution, id));
257+
258+
// We retrieve all the input types of the where clauses appearing on the trait impl,
259+
// e.g. in:
260+
// ```
261+
// impl<T, K> Foo for (T, K) where T: Iterator<Item = (HashSet<K>, Vec<Box<T>>)> { ... }
262+
// ```
263+
// we would retrieve `HashSet<K>`, `Box<T>`, `Vec<Box<T>>`, `(HashSet<K>, Vec<Box<T>>)`.
264+
// We will have to prove that these types are well-formed (e.g. an additional `K: Hash`
265+
// bound would be needed here).
266+
let mut input_types = Vec::new();
267+
where_clauses.fold(interner, &mut input_types);
268+
269+
// Things to prove well-formed: input types of the where-clauses, projection types
270+
// appearing in the header, associated type values, and of course the trait ref.
271+
debug!("verify_trait_impl: input_types={:?}", input_types);
272+
let goals = input_types
273+
.into_iter()
274+
.map(|ty| ty.well_formed().cast(interner))
275+
.chain(assoc_ty_goals)
276+
.chain(Some(trait_ref.clone().well_formed().cast(interner)));
277+
278+
gb.all(goals)
279+
})
308280
},
309281
);
310282

@@ -327,6 +299,41 @@ where
327299
}
328300
}
329301

302+
/// Creates the conditions that an impl (and its contents of an impl)
303+
/// can assume to be true when proving that it is well-formed.
304+
fn impl_wf_environment<'i>(
305+
interner: &'i I,
306+
where_clauses: &'i [QuantifiedWhereClause<I>],
307+
trait_ref: &'i TraitRef<I>,
308+
) -> impl Iterator<Item = ProgramClause<I>> + 'i {
309+
// if (WC) { ... }
310+
let wc = where_clauses
311+
.iter()
312+
.cloned()
313+
.map(move |qwc| qwc.into_from_env_goal(interner).cast(interner));
314+
315+
// We retrieve all the input types of the type on which we implement the trait: we will
316+
// *assume* that these types are well-formed, e.g. we will be able to derive that
317+
// `K: Hash` holds without writing any where clause.
318+
//
319+
// Example:
320+
// ```
321+
// struct HashSet<K> where K: Hash { ... }
322+
//
323+
// impl<K> Foo for HashSet<K> {
324+
// // Inside here, we can rely on the fact that `K: Hash` holds
325+
// }
326+
// ```
327+
let mut header_input_types = Vec::new();
328+
trait_ref.fold(interner, &mut header_input_types);
329+
330+
let types_wf = header_input_types
331+
.into_iter()
332+
.map(move |ty| ty.into_from_env_goal(interner).cast(interner));
333+
334+
wc.chain(types_wf)
335+
}
336+
330337
/// Associated type values are special because they can be parametric (independently of
331338
/// the impl), so we issue a special goal which is quantified using the binders of the
332339
/// associated type value, for example in:

0 commit comments

Comments
 (0)