fix: misuse forced_undoable_link

This commit is contained in:
Shunsuke Shibayama 2023-04-07 23:45:10 +09:00
parent 54db53bc02
commit a484f0ff9a
3 changed files with 16 additions and 10 deletions

View file

@ -751,7 +751,7 @@ impl Context {
let (rsub, rsup) = sup_fv.get_subsup().unwrap(); let (rsub, rsup) = sup_fv.get_subsup().unwrap();
// ?T(<: Add(?T)) // ?T(<: Add(?T))
// ?U(:> {1, 2}, <: Add(?U)) ==> {1, 2} // ?U(:> {1, 2}, <: Add(?U)) ==> {1, 2}
sup_fv.forced_undoable_link(&rsub); sup_fv.dummy_link();
if lsub.qual_name() == rsub.qual_name() { if lsub.qual_name() == rsub.qual_name() {
for (lps, rps) in lsub.typarams().iter().zip(rsub.typarams().iter()) { for (lps, rps) in lsub.typarams().iter().zip(rsub.typarams().iter()) {
self.sub_unify_tp(lps, rps, None, loc, false) self.sub_unify_tp(lps, rps, None, loc, false)

View file

@ -476,7 +476,7 @@ impl Hash for Free<Type> {
lev.hash(state); lev.hash(state);
} }
if let Some((sub, sup)) = self.get_subsup() { if let Some((sub, sup)) = self.get_subsup() {
self.forced_undoable_link(&sub); self.dummy_link();
sub.hash(state); sub.hash(state);
sup.hash(state); sup.hash(state);
self.undo(); self.undo();
@ -518,7 +518,7 @@ impl PartialEq for Free<Type> {
} }
if let Some((sub, sup)) = self.get_subsup() { if let Some((sub, sup)) = self.get_subsup() {
if let Some((other_sub, other_sup)) = other.get_subsup() { if let Some((other_sub, other_sup)) = other.get_subsup() {
self.forced_undoable_link(&sub); self.dummy_link();
let res = sub == other_sub && sup == other_sup; let res = sub == other_sub && sup == other_sup;
self.undo(); self.undo();
return res; return res;
@ -648,7 +648,7 @@ impl HasLevel for Free<Type> {
} }
*lev = level; *lev = level;
if let Some((sub, sup)) = self.get_subsup() { if let Some((sub, sup)) = self.get_subsup() {
self.forced_undoable_link(&sub); self.dummy_link();
sub.set_level(level); sub.set_level(level);
sup.set_level(level); sup.set_level(level);
self.undo(); self.undo();
@ -863,6 +863,12 @@ impl<T: Clone> Free<T> {
} }
} }
impl<T: Default + Clone> Free<T> {
pub fn dummy_link(&self) {
self.forced_undoable_link(&T::default());
}
}
impl<T: CanbeFree> Free<T> { impl<T: CanbeFree> Free<T> {
pub fn get_type(&self) -> Option<Type> { pub fn get_type(&self) -> Option<Type> {
self.constraint().and_then(|c| c.get_type().cloned()) self.constraint().and_then(|c| c.get_type().cloned())

View file

@ -1765,7 +1765,7 @@ impl Type {
|| fv || fv
.get_subsup() .get_subsup()
.map(|(sub, sup)| { .map(|(sub, sup)| {
fv.forced_undoable_link(&Type::Never); fv.dummy_link();
let res = sub.contains_tvar(target) || sup.contains_tvar(target); let res = sub.contains_tvar(target) || sup.contains_tvar(target);
fv.undo(); fv.undo();
res res
@ -1805,7 +1805,7 @@ impl Type {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains(target), Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains(target),
Self::FreeVar(fv) => { Self::FreeVar(fv) => {
fv.get_subsup().map_or(false, |(sub, sup)| { fv.get_subsup().map_or(false, |(sub, sup)| {
fv.forced_undoable_link(&Type::Never); fv.dummy_link();
let res = sub.contains(target) || sup.contains(target); let res = sub.contains(target) || sup.contains(target);
fv.undo(); fv.undo();
res res
@ -2168,12 +2168,12 @@ impl Type {
Self::FreeVar(fv) if !fv.constraint_is_uninited() => { Self::FreeVar(fv) if !fv.constraint_is_uninited() => {
let base = set! {(fv.unbound_name().unwrap(), fv.constraint().unwrap())}; let base = set! {(fv.unbound_name().unwrap(), fv.constraint().unwrap())};
if let Some((sub, sup)) = fv.get_subsup() { if let Some((sub, sup)) = fv.get_subsup() {
fv.forced_undoable_link(&Type::Failure); fv.dummy_link();
let res = base.concat(sub.qvars()).concat(sup.qvars()); let res = base.concat(sub.qvars()).concat(sup.qvars());
fv.undo(); fv.undo();
res res
} else if let Some(ty) = fv.get_type() { } else if let Some(ty) = fv.get_type() {
fv.forced_undoable_link(&Type::Failure); fv.dummy_link();
let res = base.concat(ty.qvars()); let res = base.concat(ty.qvars());
fv.undo(); fv.undo();
res res
@ -2514,7 +2514,7 @@ impl Type {
if let Some((sub, sup)) = fv.get_subsup() { if let Some((sub, sup)) = fv.get_subsup() {
// if fv == ?T(:> {1, 2}, <: Sub(?T)), derefine() will cause infinite loop // if fv == ?T(:> {1, 2}, <: Sub(?T)), derefine() will cause infinite loop
// so we need to force linking // so we need to force linking
fv.forced_undoable_link(&sub); fv.dummy_link();
let constraint = Constraint::new_sandwiched(sub.derefine(), sup.derefine()); let constraint = Constraint::new_sandwiched(sub.derefine(), sup.derefine());
let free = Self::FreeVar(Free::new_named_unbound(name, level, constraint)); let free = Self::FreeVar(Free::new_named_unbound(name, level, constraint));
fv.undo(); fv.undo();
@ -2592,7 +2592,7 @@ impl Type {
Self::FreeVar(fv) => { Self::FreeVar(fv) => {
let fv = fv.deep_clone(); let fv = fv.deep_clone();
if let Some((sub, sup)) = fv.get_subsup() { if let Some((sub, sup)) = fv.get_subsup() {
fv.forced_undoable_link(&sub); fv.dummy_link();
let sub = sub._replace(target, to); let sub = sub._replace(target, to);
let sup = sup._replace(target, to); let sup = sup._replace(target, to);
fv.undo(); fv.undo();