fix: infinite recursion

This commit is contained in:
Shunsuke Shibayama 2023-04-10 00:38:41 +09:00
parent 2ac004b51e
commit 3ed863cef6
3 changed files with 31 additions and 28 deletions

View file

@ -400,6 +400,26 @@ impl Context {
}
}
},
(_, Proj { .. }) => {
if let Some(cands) = self.get_candidates(rhs) {
for cand in cands.into_iter() {
if self.supertype_of(lhs, &cand) {
return true;
}
}
}
false
}
(Proj { .. }, _) => {
if let Some(cands) = self.get_candidates(lhs) {
for cand in cands.into_iter() {
if self.supertype_of(&cand, rhs) {
return true;
}
}
}
false
}
// true if it can be a supertype, false if it cannot (due to type constraints)
// No type constraints are imposed here, as subsequent type decisions are made according to the possibilities
// ?P(<: Mul ?P) :> Int
@ -454,7 +474,7 @@ impl Context {
}
}
},
(Type::Record(lhs), Type::Record(rhs)) => {
(Record(lhs), Record(rhs)) => {
for (l_k, l_t) in lhs.iter() {
if let Some((r_k, r_t)) = rhs.get_key_value(l_k) {
// public <: private (private fields cannot be public)
@ -678,26 +698,6 @@ impl Context {
self.poly_supertype_of(lhs, lparams, rparams)
}
}
(Proj { .. }, _) => {
if let Some(cands) = self.get_candidates(lhs) {
for cand in cands.into_iter() {
if self.supertype_of(&cand, rhs) {
return true;
}
}
}
false
}
(_, Proj { .. }) => {
if let Some(cands) = self.get_candidates(rhs) {
for cand in cands.into_iter() {
if self.supertype_of(lhs, &cand) {
return true;
}
}
}
false
}
(Structural(l), Structural(r)) => self.structural_supertype_of(l, r),
// TODO: If visibility does not match, it should be reported as a cause of an error
(Structural(l), r) => {

View file

@ -138,8 +138,8 @@ impl Generalizer {
FreeVar(fv) if fv.is_generalized() => Type::FreeVar(fv),
// TODO: Polymorphic generalization
FreeVar(fv) if fv.level().unwrap() > self.level => {
fv.generalize();
if uninit {
fv.generalize();
return Type::FreeVar(fv);
}
if let Some((sub, sup)) = fv.get_subsup() {
@ -162,13 +162,11 @@ impl Generalizer {
self.generalize_t(sub, uninit)
} else {
fv.update_constraint(self.generalize_constraint(&fv), true);
fv.generalize();
Type::FreeVar(fv)
}
} else {
// ?S(: Str) => 'S
fv.update_constraint(self.generalize_constraint(&fv), true);
fv.generalize();
Type::FreeVar(fv)
}
}
@ -515,9 +513,14 @@ impl<'c, 'q, 'l, L: Locational> Dereferencer<'c, 'q, 'l, L> {
Type::FreeVar(fv) if fv.constraint_is_sandwiched() => {
let (sub_t, super_t) = fv.get_subsup().unwrap();
if self.ctx.level <= fv.level().unwrap() {
// if fv == ?T(<: Int, :> Add(?T)), deref_tyvar(super_t) will cause infinite loop
// so we need to force linking
fv.forced_undoable_link(&sub_t);
// we need to force linking to avoid infinite loop
// e.g. fv == ?T(<: Int, :> Add(?T))
// fv == ?T(:> ?T.Output, <: Add(Int))
if sub_t.contains(&Type::FreeVar(fv.clone())) {
fv.forced_undoable_link(&super_t);
} else {
fv.forced_undoable_link(&sub_t);
}
let res = self.validate_subsup(sub_t, super_t);
fv.undo();
match res {