/// Pre-condition: xs and v are disjoint sets of variables.
pub fn generate(
self : Subtype,
xs : Array[Var],
v : Set[Var],
) -> Constraints raise {
match (self.l, self.r) {
(_, TyTop) | (TyBot, _) => Constraints::empty()
(TyVar(y1), TyVar(y2)) if y1 == y2 && !xs.contains(y1) =>
Constraints::empty()
(TyVar(y), s) if xs.contains(y) => {
let t = s.demotion(v)
Map::from_array([(y, { l: TyBot, r: t })])
}
(s, TyVar(y)) if xs.contains(y) => {
let t = s.promotion(v)
Map::from_array([(y, { l: t, r: TyTop })])
}
(TyFun(ys1, r, s), TyFun(ys2, t, u)) if ys1 == ys2 => {
let vy = v.union(Set::from_array(ys1))
let cs = t.zip(r).map(tr => { l: tr.0, r: tr.1 }.generate(xs, vy))
|> meets()
cs.meet({ l: s, r: u }.generate(xs, vy))
}
_ => raise ConstraintGenerationError
}
}