Skip to content

Commit 4e0f1e2

Browse files
committed
Implement program clause generation for FnDef
1 parent 768e7a2 commit 4e0f1e2

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

chalk-solve/src/clauses.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,10 @@ fn match_type_name<I: Interner>(
412412
TypeName::Slice => builder.push_fact(WellFormed::Ty(application.clone().intern(interner))),
413413
TypeName::Raw(_) => builder.push_fact(WellFormed::Ty(application.clone().intern(interner))),
414414
TypeName::Ref(_) => builder.push_fact(WellFormed::Ty(application.clone().intern(interner))),
415+
TypeName::FnDef(fn_def_id) => builder
416+
.db
417+
.fn_def_datum(fn_def_id)
418+
.to_program_clauses(builder),
415419
}
416420
}
417421

chalk-solve/src/clauses/program_clauses.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,63 @@ impl<I: Interner> ToProgramClauses<I> for AdtDatum<I> {
337337
}
338338
}
339339

340+
impl<I: Interner> ToProgramClauses<I> for FnDefDatum<I> {
341+
fn to_program_clauses(&self, builder: &mut ClauseBuilder<'_, I>) {
342+
debug_heading!("FnDatum::to_program_clauses(self={:?})", self);
343+
344+
let interner = builder.interner();
345+
let binders = self.binders.map_ref(|b| &b.where_clauses);
346+
builder.push_binders(&binders, |builder, where_clauses| {
347+
let self_appl_ty = &ApplicationTy {
348+
name: self.id.cast(interner),
349+
substitution: builder.substitution_in_scope(),
350+
};
351+
let self_ty = self_appl_ty.clone().intern(interner);
352+
353+
// forall<T> {
354+
// WF(foo<T>) :- WF(T: Eq).
355+
// }
356+
builder.push_clause(
357+
WellFormed::Ty(self_ty.clone()),
358+
where_clauses
359+
.iter()
360+
.cloned()
361+
.map(|qwc| qwc.into_well_formed_goal(interner)),
362+
);
363+
364+
// forall<T> {
365+
// IsFullyVisible(foo<T>) :- IsFullyVisible(T).
366+
// }
367+
builder.push_clause(
368+
DomainGoal::IsFullyVisible(self_ty.clone()),
369+
self_appl_ty
370+
.type_parameters(interner)
371+
.map(|ty| DomainGoal::IsFullyVisible(ty).cast::<Goal<_>>(interner)),
372+
);
373+
374+
for qwc in where_clauses {
375+
// Generate implied bounds rules. We have to push the binders from the where-clauses
376+
// too -- e.g., if we had `fn foo<T: for<'a> Bar<&'a i32>>()`, we would
377+
// create a reverse rule like:
378+
//
379+
// ```notrust
380+
// forall<T, 'a> { FromEnv(T: Bar<&'a i32>) :- FromEnv(foo<T>) }
381+
// ```
382+
//
383+
// In other words, you can assume `T: Bar<&'a i32>`
384+
// for any `'a` *if* you are assuming that `foo<T>` is
385+
// well formed.
386+
builder.push_binders(&qwc, |builder, wc| {
387+
builder.push_clause(
388+
wc.into_from_env_goal(interner),
389+
Some(self_ty.clone().from_env()),
390+
);
391+
});
392+
}
393+
});
394+
}
395+
}
396+
340397
impl<I: Interner> ToProgramClauses<I> for TraitDatum<I> {
341398
/// Given the following trait declaration: `trait Ord<T> where Self: Eq<T> { ... }`, generate:
342399
///

0 commit comments

Comments
 (0)