Skip to content

Commit 89e5a96

Browse files
committed
Clean up and document program clause generation
1 parent d267a40 commit 89e5a96

File tree

1 file changed

+68
-34
lines changed

1 file changed

+68
-34
lines changed

chalk-solve/src/clauses/program_clauses.rs

Lines changed: 68 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -182,33 +182,44 @@ impl<I: Interner> ToProgramClauses<I> for OpaqueTyDatum<I> {
182182

183183
fn application_ty<I: Interner>(
184184
builder: &mut ClauseBuilder<'_, I>,
185-
id: impl CastTo<TypeName<I>>,
185+
type_name: impl CastTo<TypeName<I>>,
186186
) -> ApplicationTy<I> {
187187
let interner = builder.interner();
188188
ApplicationTy {
189-
name: id.cast(interner),
189+
name: type_name.cast(interner),
190190
substitution: builder.substitution_in_scope(),
191191
}
192192
}
193193

194-
fn interned_application_ty<I: Interner>(interner: &I, appl_ty: &ApplicationTy<I>) -> Ty<I> {
195-
appl_ty.clone().intern(interner)
196-
}
197-
194+
/// Generates the "well-formed" program clauses for an applicative type
195+
/// with the name `type_name`. For example, given a struct definition:
196+
///
197+
/// ```ignore
198+
/// struct Foo<T: Eq> { }
199+
/// ```
200+
///
201+
/// we would generate the clause:
202+
///
203+
/// ```notrust
204+
/// forall<T> {
205+
/// WF(Foo<T>) :- WF(T: Eq).
206+
/// }
207+
/// ```
208+
///
209+
/// # Parameters
210+
/// - builder -- the clause builder. We assume all the generic types from `Foo` are in scope
211+
/// - type_name -- in our example above, the name `Foo`
212+
/// - where_clauses -- the list of where clauses declared on the type (`T: Eq`, in our example)
198213
fn well_formed_program_clauses<'a, I, Wc>(
199214
builder: &'a mut ClauseBuilder<'_, I>,
200-
id: impl CastTo<TypeName<I>>,
215+
type_name: impl CastTo<TypeName<I>>,
201216
where_clauses: Wc,
202217
) where
203218
I: Interner,
204219
Wc: Iterator<Item = &'a QuantifiedWhereClause<I>>,
205220
{
206-
// Given a type definition `struct Foo<T: Eq> { }` generate the clause
207-
// forall<T> {
208-
// WF(Foo<T>) :- WF(T: Eq).
209-
// }
210221
let interner = builder.interner();
211-
let appl_ty = application_ty(builder, id);
222+
let appl_ty = application_ty(builder, type_name);
212223
let ty = appl_ty.clone().intern(interner);
213224
builder.push_clause(
214225
WellFormed::Ty(ty.clone()),
@@ -218,19 +229,34 @@ fn well_formed_program_clauses<'a, I, Wc>(
218229
);
219230
}
220231

232+
/// Generates the "fully visible" program clauses for an applicative type
233+
/// with the name `type_name`. For example, given a struct definition:
234+
///
235+
/// ```ignore
236+
/// struct Foo<T: Eq> { }
237+
/// ```
238+
///
239+
/// we would generate the clause:
240+
///
241+
/// ```notrust
242+
/// forall<T> {
243+
/// IsFullyVisible(Foo<T>) :- IsFullyVisible(T).
244+
/// }
245+
/// ```
246+
///
247+
/// # Parameters
248+
///
249+
/// - builder -- the clause builder. We assume all the generic types from `Foo` are in scope
250+
/// - type_name -- in our example above, the name `Foo`
221251
fn fully_visible_program_clauses<'a, I>(
222252
builder: &'a mut ClauseBuilder<'_, I>,
223-
id: impl CastTo<TypeName<I>>,
253+
type_name: impl CastTo<TypeName<I>>,
224254
) where
225255
I: Interner,
226256
{
227-
// Given a type definition `struct Foo<T: Eq> { }` generate the clause
228-
// forall<T> {
229-
// IsFullyVisible(Foo<T>) :- IsFullyVisible(T).
230-
// }
231257
let interner = builder.interner();
232-
let appl_ty = application_ty(builder, id);
233-
let ty = interned_application_ty(interner, &appl_ty);
258+
let appl_ty = application_ty(builder, type_name);
259+
let ty = appl_ty.clone().intern(interner);
234260
builder.push_clause(
235261
DomainGoal::IsFullyVisible(ty.clone()),
236262
appl_ty
@@ -239,30 +265,38 @@ fn fully_visible_program_clauses<'a, I>(
239265
);
240266
}
241267

268+
/// Generates the "implied bounds" clauses for an applicative
269+
/// type with the name `type_name`. For example, if `type_name`
270+
/// represents a struct `S` that is declared like:
271+
///
272+
/// ```ignore
273+
/// struct S<T> where T: Eq { }
274+
/// ```
275+
///
276+
/// then we would generate the rule:
277+
///
278+
/// ```notrust
279+
/// FromEnv(T: Eq) :- FromEnv(S<T>)
280+
/// ```
281+
///
282+
/// # Parameters
283+
///
284+
/// - builder -- the clause builder. We assume all the generic types from `S` are in scope.
285+
/// - type_name -- in our example above, the name `S`
286+
/// - where_clauses -- the list of where clauses declared on the type (`T: Eq`, in our example).
242287
fn implied_bounds_program_clauses<'a, I, Wc>(
243288
builder: &'a mut ClauseBuilder<'_, I>,
244-
id: impl CastTo<TypeName<I>>,
289+
type_name: impl CastTo<TypeName<I>>,
245290
where_clauses: Wc,
246291
) where
247292
I: Interner,
248293
Wc: Iterator<Item = &'a QuantifiedWhereClause<I>>,
249294
{
250295
let interner = builder.interner();
251-
let appl_ty = application_ty(builder, id);
252-
let ty = interned_application_ty(interner, &appl_ty);
296+
let appl_ty = application_ty(builder, type_name);
297+
let ty = appl_ty.clone().intern(interner);
253298

254299
for qwc in where_clauses {
255-
// Generate implied bounds rules. We have to push the binders from the where-clauses
256-
// too -- e.g., if we had `struct Foo<T: for<'a> Bar<&'a i32>>`, we would
257-
// create a reverse rule like:
258-
//
259-
// ```notrust
260-
// forall<T, 'a> { FromEnv(T: Bar<&'a i32>) :- FromEnv(Foo<T>) }
261-
// ```
262-
//
263-
// In other words, you can assume `T: Bar<&'a i32>`
264-
// for any `'a` *if* you are assuming that `Foo<T>` is
265-
// well formed.
266300
builder.push_binders(&qwc, |builder, wc| {
267301
builder.push_clause(wc.into_from_env_goal(interner), Some(ty.clone().from_env()));
268302
});
@@ -333,7 +367,7 @@ impl<I: Interner> ToProgramClauses<I> for AdtDatum<I> {
333367
fully_visible_program_clauses(builder, id);
334368

335369
let self_appl_ty = application_ty(builder, id);
336-
let self_ty = interned_application_ty(interner, &self_appl_ty);
370+
let self_ty = self_appl_ty.clone().intern(interner);
337371

338372
// Fundamental types often have rules in the form of:
339373
// Goal(FundamentalType<T>) :- Goal(T)

0 commit comments

Comments
 (0)