fix: infinite recursion bug

This commit is contained in:
Shunsuke Shibayama 2024-08-29 22:36:23 +09:00
parent 06412bf7d2
commit 52595bde1c
5 changed files with 136 additions and 52 deletions

View file

@ -626,6 +626,7 @@ macro_rules! set_recursion_limit {
let counter = $crate::macros::RecursionCounter::new(&COUNTER); let counter = $crate::macros::RecursionCounter::new(&COUNTER);
if counter.limit_reached() { if counter.limit_reached() {
$crate::log!(err "Recursion limit reached");
return $returns; return $returns;
} }
}; };

View file

@ -406,11 +406,17 @@ impl<'c> Substituter<'c> {
/// -> Iterable(Int) /// -> Iterable(Int)
/// ``` /// ```
pub(crate) fn substitute_self(qt: &Type, subtype: &Type, ctx: &'c Context) -> Option<Self> { pub(crate) fn substitute_self(qt: &Type, subtype: &Type, ctx: &'c Context) -> Option<Self> {
#[allow(clippy::blocks_in_conditions)]
for t in qt.contained_ts() { for t in qt.contained_ts() {
if t.is_qvar() if t.is_qvar()
&& &t.qual_name()[..] == "Self" && &t.qual_name()[..] == "Self"
&& t.get_super() && t.get_super().is_some_and(|sup| {
.is_some_and(|sup| ctx.supertype_of(&sup, subtype)) let fv = t.as_free().unwrap();
fv.dummy_link();
let res = ctx.supertype_of(&sup, subtype);
fv.undo();
res
})
{ {
let mut _self = Self::new(ctx); let mut _self = Self::new(ctx);
t.undoable_link(subtype, &_self.undoable_linked); t.undoable_link(subtype, &_self.undoable_linked);

View file

@ -248,8 +248,8 @@ impl Constraint {
} else if sup.addr_eq(target) { } else if sup.addr_eq(target) {
Self::new_supertype_of(sub) Self::new_supertype_of(sub)
} else { } else {
let sub = sub.eliminate_sub(target); let sub = sub.eliminate_subsup(target);
let sup = sup.eliminate_sub(target); let sup = sup.eliminate_subsup(target);
Self::new_sandwiched(sub, sup) Self::new_sandwiched(sub, sup)
} }
} }

View file

@ -37,7 +37,7 @@ use erg_parser::ast::Expr;
use erg_parser::token::TokenKind; use erg_parser::token::TokenKind;
pub use const_subr::*; pub use const_subr::*;
use constructors::{dict_t, int_interval, mono}; use constructors::{callable, dict_t, int_interval, mono};
use free::{CanbeFree, Constraint, Free, FreeKind, FreeTyVar, HasLevel, Level, GENERIC_LEVEL}; use free::{CanbeFree, Constraint, Free, FreeKind, FreeTyVar, HasLevel, Level, GENERIC_LEVEL};
pub use predicate::Predicate; pub use predicate::Predicate;
pub use typaram::{IntervalOp, TyParam}; pub use typaram::{IntervalOp, TyParam};
@ -2007,7 +2007,7 @@ impl HasLevel for Type {
Some(min) Some(min)
} }
} }
_ => None, mono_type_pattern!() => None,
} }
} }
@ -2084,7 +2084,7 @@ impl HasLevel for Type {
sub.set_level(level); sub.set_level(level);
sup.set_level(level); sup.set_level(level);
} }
_ => {} mono_type_pattern!() => {} //_ => {}
} }
} }
} }
@ -2874,7 +2874,11 @@ impl Type {
|| after.as_ref().map_or(false, |t| t.contains_tvar(target)) || after.as_ref().map_or(false, |t| t.contains_tvar(target))
} }
Self::Bounded { sub, sup } => sub.contains_tvar(target) || sup.contains_tvar(target), Self::Bounded { sub, sup } => sub.contains_tvar(target) || sup.contains_tvar(target),
_ => false, Self::Callable { param_ts, return_t } => {
param_ts.iter().any(|t| t.contains_tvar(target)) || return_t.contains_tvar(target)
}
Self::Guard(guard) => guard.to.contains_tvar(target),
mono_type_pattern!() => false,
} }
} }
@ -2937,7 +2941,11 @@ impl Type {
|| after.as_ref().map_or(false, |t| t.contains_type(target)) || after.as_ref().map_or(false, |t| t.contains_type(target))
} }
Self::Bounded { sub, sup } => sub.contains_type(target) || sup.contains_type(target), Self::Bounded { sub, sup } => sub.contains_type(target) || sup.contains_type(target),
_ => false, Self::Callable { param_ts, return_t } => {
param_ts.iter().any(|t| t.contains_type(target)) || return_t.contains_type(target)
}
Self::Guard(guard) => guard.to.contains_type(target),
mono_type_pattern!() => false,
} }
} }
@ -2971,13 +2979,18 @@ impl Type {
|| after.as_ref().map_or(false, |t| t.contains_tp(target)) || after.as_ref().map_or(false, |t| t.contains_tp(target))
} }
Self::Bounded { sub, sup } => sub.contains_tp(target) || sup.contains_tp(target), Self::Bounded { sub, sup } => sub.contains_tp(target) || sup.contains_tp(target),
_ => false, Self::Callable { param_ts, return_t } => {
param_ts.iter().any(|t| t.contains_tp(target)) || return_t.contains_tp(target)
}
Self::Guard(guard) => guard.to.contains_tp(target),
mono_type_pattern!() => false,
} }
} }
pub fn contains_value(&self, target: &ValueObj) -> bool { pub fn contains_value(&self, target: &ValueObj) -> bool {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains_value(target), Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains_value(target),
Self::FreeVar(_) => false,
Self::Record(rec) => rec.iter().any(|(_, t)| t.contains_value(target)), Self::Record(rec) => rec.iter().any(|(_, t)| t.contains_value(target)),
Self::NamedTuple(rec) => rec.iter().any(|(_, t)| t.contains_value(target)), Self::NamedTuple(rec) => rec.iter().any(|(_, t)| t.contains_value(target)),
Self::Poly { params, .. } => params.iter().any(|tp| tp.contains_value(target)), Self::Poly { params, .. } => params.iter().any(|tp| tp.contains_value(target)),
@ -3000,7 +3013,11 @@ impl Type {
|| after.as_ref().map_or(false, |t| t.contains_value(target)) || after.as_ref().map_or(false, |t| t.contains_value(target))
} }
Self::Bounded { sub, sup } => sub.contains_value(target) || sup.contains_value(target), Self::Bounded { sub, sup } => sub.contains_value(target) || sup.contains_value(target),
_ => false, Self::Callable { param_ts, return_t } => {
param_ts.iter().any(|t| t.contains_value(target)) || return_t.contains_value(target)
}
Self::Guard(guard) => guard.to.contains_value(target),
mono_type_pattern!() => false,
} }
} }
@ -3039,7 +3056,11 @@ impl Type {
|| after.as_ref().map_or(false, |t| t.contains_type(self)) || after.as_ref().map_or(false, |t| t.contains_type(self))
} }
Self::Bounded { sub, sup } => sub.contains_type(self) || sup.contains_type(self), Self::Bounded { sub, sup } => sub.contains_type(self) || sup.contains_type(self),
_ => false, Self::Callable { param_ts, return_t } => {
param_ts.iter().any(|t| t.contains_type(self)) || return_t.contains_type(self)
}
Self::Guard(guard) => guard.to.contains_type(self),
mono_type_pattern!() => false,
} }
} }
@ -3518,6 +3539,7 @@ impl Type {
base base
} }
} }
Self::FreeVar(_) => set! {},
Self::Ref(ty) => ty.qvars_inner(), Self::Ref(ty) => ty.qvars_inner(),
Self::RefMut { before, after } => before.qvars_inner().concat( Self::RefMut { before, after } => before.qvars_inner().concat(
after after
@ -3541,6 +3563,7 @@ impl Type {
Self::Refinement(refine) => refine.t.qvars_inner().concat(refine.pred.qvars()), Self::Refinement(refine) => refine.t.qvars_inner().concat(refine.pred.qvars()),
// ((|T| T -> T) and U).qvars() == U.qvars() // ((|T| T -> T) and U).qvars() == U.qvars()
// Self::Quantified(quant) => quant.qvars(), // Self::Quantified(quant) => quant.qvars(),
Self::Quantified(_) => set! {},
Self::Poly { params, .. } => params Self::Poly { params, .. } => params
.iter() .iter()
.fold(set! {}, |acc, tp| acc.concat(tp.qvars())), .fold(set! {}, |acc, tp| acc.concat(tp.qvars())),
@ -3551,7 +3574,7 @@ impl Type {
Self::Structural(ty) => ty.qvars_inner(), Self::Structural(ty) => ty.qvars_inner(),
Self::Guard(guard) => guard.to.qvars_inner(), Self::Guard(guard) => guard.to.qvars_inner(),
Self::Bounded { sub, sup } => sub.qvars_inner().concat(sup.qvars_inner()), Self::Bounded { sub, sup } => sub.qvars_inner().concat(sup.qvars_inner()),
_ => set! {}, mono_type_pattern!() => set! {},
} }
} }
@ -3598,6 +3621,7 @@ impl Type {
param_ts.iter().any(|t| t.has_qvar()) || return_t.has_qvar() param_ts.iter().any(|t| t.has_qvar()) || return_t.has_qvar()
} }
Self::Subr(subr) => subr.has_qvar(), Self::Subr(subr) => subr.has_qvar(),
Self::Quantified(_) => false,
// Self::Quantified(quant) => quant.has_qvar(), // Self::Quantified(quant) => quant.has_qvar(),
Self::Record(r) => r.values().any(|t| t.has_qvar()), Self::Record(r) => r.values().any(|t| t.has_qvar()),
Self::NamedTuple(r) => r.iter().any(|(_, t)| t.has_qvar()), Self::NamedTuple(r) => r.iter().any(|(_, t)| t.has_qvar()),
@ -3610,7 +3634,7 @@ impl Type {
Self::Structural(ty) => ty.has_qvar(), Self::Structural(ty) => ty.has_qvar(),
Self::Guard(guard) => guard.to.has_qvar(), Self::Guard(guard) => guard.to.has_qvar(),
Self::Bounded { sub, sup } => sub.has_qvar() || sup.has_qvar(), Self::Bounded { sub, sup } => sub.has_qvar() || sup.has_qvar(),
_ => false, mono_type_pattern!() => false,
} }
} }
@ -3669,7 +3693,7 @@ impl Type {
Self::Bounded { sub, sup } => { Self::Bounded { sub, sup } => {
sub.has_undoable_linked_var() || sup.has_undoable_linked_var() sub.has_undoable_linked_var() || sup.has_undoable_linked_var()
} }
_ => false, mono_type_pattern!() => false,
} }
} }
@ -3719,7 +3743,7 @@ impl Type {
Self::Structural(ty) => ty.has_unbound_var(), Self::Structural(ty) => ty.has_unbound_var(),
Self::Guard(guard) => guard.to.has_unbound_var(), Self::Guard(guard) => guard.to.has_unbound_var(),
Self::Bounded { sub, sup } => sub.has_unbound_var() || sup.has_unbound_var(), Self::Bounded { sub, sup } => sub.has_unbound_var() || sup.has_unbound_var(),
_ => false, mono_type_pattern!() => false,
} }
} }
@ -4065,41 +4089,41 @@ impl Type {
} }
Self::Subr(subr) => Self::Subr(subr.derefine()), Self::Subr(subr) => Self::Subr(subr.derefine()),
Self::Quantified(quant) => quant.derefine().quantify(), Self::Quantified(quant) => quant.derefine().quantify(),
other => other.clone(), mono_type_pattern!() => self.clone(),
} }
} }
/// ```erg /// ```erg
/// (T or U).eliminate_sub(T) == U /// (T or U).eliminate_subsup(T) == U
/// ?X(<: T or U).eliminate_sub(T) == ?X(<: U) /// ?X(<: T or U).eliminate_subsup(T) == ?X(<: U)
/// ``` /// ```
pub fn eliminate_sub(self, target: &Type) -> Self { pub fn eliminate_subsup(self, target: &Type) -> Self {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().eliminate_sub(target), Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().eliminate_subsup(target),
Self::FreeVar(ref fv) if fv.constraint_is_sandwiched() => { Self::FreeVar(ref fv) if fv.constraint_is_sandwiched() => {
let (sub, sup) = fv.get_subsup().unwrap(); let (sub, sup) = fv.get_subsup().unwrap();
fv.do_avoiding_recursion(|| { fv.do_avoiding_recursion(|| {
let sub = sub.eliminate_sub(target); let sub = sub.eliminate_subsup(target);
let sup = sup.eliminate_sub(target); let sup = sup.eliminate_subsup(target);
self.update_tyvar(sub, sup, None, false); self.update_tyvar(sub, sup, None, false);
}); });
self self
} }
Self::And(l, r) => { Self::And(l, r) => {
if l.addr_eq(target) { if l.addr_eq(target) {
return r.eliminate_sub(target); return r.eliminate_subsup(target);
} else if r.addr_eq(target) { } else if r.addr_eq(target) {
return l.eliminate_sub(target); return l.eliminate_subsup(target);
} }
l.eliminate_sub(target) & r.eliminate_sub(target) l.eliminate_subsup(target) & r.eliminate_subsup(target)
} }
Self::Or(l, r) => { Self::Or(l, r) => {
if l.addr_eq(target) { if l.addr_eq(target) {
return r.eliminate_sub(target); return r.eliminate_subsup(target);
} else if r.addr_eq(target) { } else if r.addr_eq(target) {
return l.eliminate_sub(target); return l.eliminate_subsup(target);
} }
l.eliminate_sub(target) | r.eliminate_sub(target) l.eliminate_subsup(target) | r.eliminate_subsup(target)
} }
other => other, other => other,
} }
@ -4115,6 +4139,7 @@ impl Type {
} }
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().eliminate_recursion(target), Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().eliminate_recursion(target),
Self::FreeVar(_) => self,
Self::Refinement(mut refine) => { Self::Refinement(mut refine) => {
refine.t = Box::new(refine.t.eliminate_recursion(target)); refine.t = Box::new(refine.t.eliminate_recursion(target));
refine.pred = Box::new(refine.pred.map_t(&mut |t| t.eliminate_recursion(target))); refine.pred = Box::new(refine.pred.map_t(&mut |t| t.eliminate_recursion(target)));
@ -4176,7 +4201,7 @@ impl Type {
sub: Box::new(sub.eliminate_recursion(target)), sub: Box::new(sub.eliminate_recursion(target)),
sup: Box::new(sup.eliminate_recursion(target)), sup: Box::new(sup.eliminate_recursion(target)),
}, },
other => other, mono_type_pattern!() => self,
} }
} }
@ -4344,7 +4369,7 @@ impl Type {
sub: Box::new(sub._replace(target, to)), sub: Box::new(sub._replace(target, to)),
sup: Box::new(sup._replace(target, to)), sup: Box::new(sup._replace(target, to)),
}, },
other => other, mono_type_pattern!() => self,
} }
} }
@ -4430,7 +4455,7 @@ impl Type {
sub: Box::new(sub._replace_tp(target, to)), sub: Box::new(sub._replace_tp(target, to)),
sup: Box::new(sup._replace_tp(target, to)), sup: Box::new(sup._replace_tp(target, to)),
}, },
other => other, mono_type_pattern!() => self,
} }
} }
@ -4507,7 +4532,7 @@ impl Type {
sub: Box::new(sub.map_tp(f)), sub: Box::new(sub.map_tp(f)),
sup: Box::new(sup.map_tp(f)), sup: Box::new(sup.map_tp(f)),
}, },
other => other, mono_type_pattern!() => self,
} }
} }
@ -4629,6 +4654,7 @@ impl Type {
pub fn normalize(self) -> Self { pub fn normalize(self) -> Self {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().normalize(), Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().normalize(),
Self::FreeVar(_) => self,
Self::Poly { name, params } => { Self::Poly { name, params } => {
let params = params.into_iter().map(|tp| tp.normalize()).collect(); let params = params.into_iter().map(|tp| tp.normalize()).collect();
Self::Poly { name, params } Self::Poly { name, params }
@ -4684,6 +4710,7 @@ impl Type {
Self::Or(l, r) => l.normalize() | r.normalize(), Self::Or(l, r) => l.normalize() | r.normalize(),
Self::Not(ty) => !ty.normalize(), Self::Not(ty) => !ty.normalize(),
Self::Structural(ty) => ty.normalize().structuralize(), Self::Structural(ty) => ty.normalize().structuralize(),
Self::Quantified(quant) => quant.normalize().quantify(),
Self::Guard(guard) => Self::Guard(GuardType::new( Self::Guard(guard) => Self::Guard(GuardType::new(
guard.namespace, guard.namespace,
guard.target, guard.target,
@ -4693,7 +4720,12 @@ impl Type {
sub: Box::new(sub.normalize()), sub: Box::new(sub.normalize()),
sup: Box::new(sup.normalize()), sup: Box::new(sup.normalize()),
}, },
other => other, Self::Callable { param_ts, return_t } => {
let param_ts = param_ts.into_iter().map(|t| t.normalize()).collect();
let return_t = return_t.normalize();
callable(param_ts, return_t)
}
mono_type_pattern!() => self,
} }
} }
@ -4735,10 +4767,12 @@ impl Type {
}*/ }*/
return; return;
} }
let to = to.clone().eliminate_sub(self).eliminate_recursion(self);
match self { match self {
Self::FreeVar(fv) => fv.link(&to), Self::FreeVar(fv) => {
Self::Refinement(refine) => refine.t.destructive_link(&to), let to = to.clone().eliminate_subsup(self).eliminate_recursion(self);
fv.link(&to);
}
Self::Refinement(refine) => refine.t.destructive_link(to),
_ => { _ => {
if DEBUG_MODE { if DEBUG_MODE {
panic!("{self} is not a free variable"); panic!("{self} is not a free variable");
@ -4756,10 +4790,12 @@ impl Type {
self.inc_undo_count(); self.inc_undo_count();
return; return;
} }
let to = to.clone().eliminate_sub(self);
match self { match self {
Self::FreeVar(fv) => fv.undoable_link(&to), Self::FreeVar(fv) => {
Self::Refinement(refine) => refine.t.undoable_link(&to, list), let to = to.clone().eliminate_subsup(self);
fv.undoable_link(&to);
}
Self::Refinement(refine) => refine.t.undoable_link(to, list),
_ => { _ => {
if DEBUG_MODE { if DEBUG_MODE {
panic!("{self} is not a free variable") panic!("{self} is not a free variable")
@ -4903,6 +4939,7 @@ impl Type {
.union(&sup.contained_ts()) .union(&sup.contained_ts())
}) })
} }
Self::FreeVar(_) => set! { self.clone() },
Self::Refinement(refine) => refine.t.contained_ts(), Self::Refinement(refine) => refine.t.contained_ts(),
Self::Ref(t) => t.contained_ts(), Self::Ref(t) => t.contained_ts(),
Self::RefMut { before, .. } => before.contained_ts(), Self::RefMut { before, .. } => before.contained_ts(),
@ -4944,7 +4981,8 @@ impl Type {
ts.extend(params.iter().flat_map(|tp| tp.contained_ts())); ts.extend(params.iter().flat_map(|tp| tp.contained_ts()));
ts ts
} }
_ => set! { self.clone() }, Self::Guard(guard) => guard.to.contained_ts(),
mono_type_pattern!() => set! { self.clone() },
} }
} }
@ -4958,6 +4996,7 @@ impl Type {
Self::FreeVar(fv) if fv.is_generalized() => { Self::FreeVar(fv) if fv.is_generalized() => {
fv.update_init(); fv.update_init();
} }
Self::FreeVar(_) => {}
// TODO: T(:> X, <: Y).dereference() // TODO: T(:> X, <: Y).dereference()
Self::Refinement(refine) => { Self::Refinement(refine) => {
refine.t.dereference(); refine.t.dereference();
@ -5034,7 +5073,7 @@ impl Type {
Self::Guard(guard) => { Self::Guard(guard) => {
guard.to.dereference(); guard.to.dereference();
} }
_ => {} mono_type_pattern!() => {}
} }
} }

View file

@ -1125,11 +1125,16 @@ impl TyParam {
base base
} }
} }
Self::FreeVar(_) => set! {},
Self::Type(t) => t.qvars(), Self::Type(t) => t.qvars(),
Self::Proj { obj, .. } => obj.qvars(), Self::Proj { obj, .. } => obj.qvars(),
Self::ProjCall { obj, args, .. } => args
.iter()
.fold(obj.qvars(), |acc, arg| acc.concat(arg.qvars())),
Self::List(ts) | Self::Tuple(ts) => { Self::List(ts) | Self::Tuple(ts) => {
ts.iter().fold(set! {}, |acc, t| acc.concat(t.qvars())) ts.iter().fold(set! {}, |acc, t| acc.concat(t.qvars()))
} }
Self::UnsizedList(elem) => elem.qvars(),
Self::Set(ts) => ts.iter().fold(set! {}, |acc, t| acc.concat(t.qvars())), Self::Set(ts) => ts.iter().fold(set! {}, |acc, t| acc.concat(t.qvars())),
Self::Dict(ts) => ts.iter().fold(set! {}, |acc, (k, v)| { Self::Dict(ts) => ts.iter().fold(set! {}, |acc, (k, v)| {
acc.concat(k.qvars().concat(v.qvars())) acc.concat(k.qvars().concat(v.qvars()))
@ -1146,7 +1151,7 @@ impl TyParam {
Self::App { args, .. } => args.iter().fold(set! {}, |acc, p| acc.concat(p.qvars())), Self::App { args, .. } => args.iter().fold(set! {}, |acc, p| acc.concat(p.qvars())),
Self::Erased(t) => t.qvars(), Self::Erased(t) => t.qvars(),
Self::Value(val) => val.qvars(), Self::Value(val) => val.qvars(),
_ => set! {}, Self::Mono(_) | Self::Failure => set! {},
} }
} }
@ -1154,9 +1159,12 @@ impl TyParam {
match self { match self {
Self::FreeVar(fv) if fv.is_unbound() && fv.is_generalized() => true, Self::FreeVar(fv) if fv.is_unbound() && fv.is_generalized() => true,
Self::FreeVar(fv) if fv.is_linked() => fv.crack().has_qvar(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().has_qvar(),
Self::FreeVar(_) => false,
Self::Type(t) => t.has_qvar(), Self::Type(t) => t.has_qvar(),
Self::Proj { obj, .. } => obj.has_qvar(), Self::Proj { obj, .. } => obj.has_qvar(),
Self::ProjCall { obj, args, .. } => obj.has_qvar() || args.iter().any(|t| t.has_qvar()),
Self::List(tps) | Self::Tuple(tps) => tps.iter().any(|tp| tp.has_qvar()), Self::List(tps) | Self::Tuple(tps) => tps.iter().any(|tp| tp.has_qvar()),
Self::UnsizedList(elem) => elem.has_qvar(),
Self::Set(tps) => tps.iter().any(|tp| tp.has_qvar()), Self::Set(tps) => tps.iter().any(|tp| tp.has_qvar()),
Self::Dict(tps) => tps.iter().any(|(k, v)| k.has_qvar() || v.has_qvar()), Self::Dict(tps) => tps.iter().any(|(k, v)| k.has_qvar() || v.has_qvar()),
Self::Record(rec) | Self::DataClass { fields: rec, .. } => { Self::Record(rec) | Self::DataClass { fields: rec, .. } => {
@ -1168,7 +1176,7 @@ impl TyParam {
Self::App { args, .. } => args.iter().any(|p| p.has_qvar()), Self::App { args, .. } => args.iter().any(|p| p.has_qvar()),
Self::Erased(t) => t.has_qvar(), Self::Erased(t) => t.has_qvar(),
Self::Value(val) => val.has_qvar(), Self::Value(val) => val.has_qvar(),
_ => false, Self::Mono(_) | Self::Failure => false,
} }
} }
@ -1178,7 +1186,11 @@ impl TyParam {
Self::Type(t) => t.contains_tvar(target), Self::Type(t) => t.contains_tvar(target),
Self::Erased(t) => t.contains_tvar(target), Self::Erased(t) => t.contains_tvar(target),
Self::Proj { obj, .. } => obj.contains_tvar(target), Self::Proj { obj, .. } => obj.contains_tvar(target),
Self::ProjCall { obj, args, .. } => {
obj.contains_tvar(target) || args.iter().any(|t| t.contains_tvar(target))
}
Self::List(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.contains_tvar(target)), Self::List(ts) | Self::Tuple(ts) => ts.iter().any(|t| t.contains_tvar(target)),
Self::UnsizedList(elem) => elem.contains_tvar(target),
Self::Set(ts) => ts.iter().any(|t| t.contains_tvar(target)), Self::Set(ts) => ts.iter().any(|t| t.contains_tvar(target)),
Self::Dict(ts) => ts Self::Dict(ts) => ts
.iter() .iter()
@ -1528,8 +1540,12 @@ impl TyParam {
} }
match self { match self {
Self::FreeVar(fv) => { Self::FreeVar(fv) => {
let to = to.clone().eliminate_recursion(self); if to.contains_tp(self) {
fv.link(&to); let to = to.clone().eliminate_recursion(self);
fv.link(&to);
} else {
fv.link(to);
}
} }
Self::Type(t) => { Self::Type(t) => {
if let Ok(to) = <&Type>::try_from(to) { if let Ok(to) = <&Type>::try_from(to) {
@ -1558,8 +1574,12 @@ impl TyParam {
} }
match self { match self {
Self::FreeVar(fv) => { Self::FreeVar(fv) => {
let to = to.clone().eliminate_recursion(self); if to.contains_tp(self) {
fv.undoable_link(&to); let to = to.clone().eliminate_recursion(self);
fv.undoable_link(&to);
} else {
fv.undoable_link(to);
}
} }
Self::Type(t) => { Self::Type(t) => {
if let Ok(to) = <&Type>::try_from(to) { if let Ok(to) = <&Type>::try_from(to) {
@ -1672,6 +1692,7 @@ impl TyParam {
Self::FreeVar(fv) if fv.is_generalized() => { Self::FreeVar(fv) if fv.is_generalized() => {
fv.update_init(); fv.update_init();
} }
Self::FreeVar(_) => {}
Self::Type(t) => t.dereference(), Self::Type(t) => t.dereference(),
Self::Value(val) => val.dereference(), Self::Value(val) => val.dereference(),
Self::App { args, .. } => { Self::App { args, .. } => {
@ -1729,7 +1750,7 @@ impl TyParam {
rhs.dereference(); rhs.dereference();
} }
Self::Erased(t) => t.dereference(), Self::Erased(t) => t.dereference(),
_ => {} Self::Mono(_) | Self::Failure => {}
} }
} }
@ -1756,6 +1777,7 @@ impl TyParam {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().variables(), Self::FreeVar(fv) if fv.is_linked() => fv.crack().variables(),
Self::FreeVar(fv) if fv.get_type().is_some() => fv.get_type().unwrap().variables(), Self::FreeVar(fv) if fv.get_type().is_some() => fv.get_type().unwrap().variables(),
Self::FreeVar(_) => set! {},
Self::Mono(name) => set! { name.clone() }, Self::Mono(name) => set! { name.clone() },
Self::App { name, args } => { Self::App { name, args } => {
let mut set = set! { name.clone() }; let mut set = set! { name.clone() };
@ -1791,7 +1813,7 @@ impl TyParam {
} }
Self::Type(t) | Self::Erased(t) => t.variables(), Self::Type(t) | Self::Erased(t) => t.variables(),
Self::Value(val) => val.variables(), Self::Value(val) => val.variables(),
_ => set! {}, Self::Failure => set! {},
} }
} }
@ -1799,6 +1821,12 @@ impl TyParam {
pub fn map(self, f: &mut impl FnMut(TyParam) -> TyParam) -> TyParam { pub fn map(self, f: &mut impl FnMut(TyParam) -> TyParam) -> TyParam {
match self { match self {
TyParam::FreeVar(fv) if fv.is_linked() => f(fv.unwrap_linked()), TyParam::FreeVar(fv) if fv.is_linked() => f(fv.unwrap_linked()),
TyParam::FreeVar(fv) if fv.get_type().is_some() => {
let typ = fv.get_type().unwrap();
fv.update_type(typ.map_tp(f));
TyParam::FreeVar(fv)
}
TyParam::FreeVar(_) => self,
TyParam::App { name, args } => { TyParam::App { name, args } => {
let new_args = args.into_iter().map(f).collect::<Vec<_>>(); let new_args = args.into_iter().map(f).collect::<Vec<_>>();
TyParam::app(name, new_args) TyParam::app(name, new_args)
@ -1845,13 +1873,21 @@ impl TyParam {
args: args.into_iter().map(f).collect::<Vec<_>>(), args: args.into_iter().map(f).collect::<Vec<_>>(),
}, },
TyParam::Value(val) => TyParam::Value(val.map_tp(f)), TyParam::Value(val) => TyParam::Value(val.map_tp(f)),
self_ => self_, TyParam::Type(t) => TyParam::t(t.map_tp(f)),
TyParam::Erased(t) => TyParam::erased(t.map_tp(f)),
TyParam::Mono(_) | TyParam::Failure => self,
} }
} }
pub fn map_t(self, f: &mut impl FnMut(Type) -> Type) -> TyParam { pub fn map_t(self, f: &mut impl FnMut(Type) -> Type) -> TyParam {
match self { match self {
TyParam::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().map_t(f), TyParam::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().map_t(f),
TyParam::FreeVar(fv) if fv.get_type().is_some() => {
let typ = fv.get_type().unwrap();
fv.update_type(f(typ));
TyParam::FreeVar(fv)
}
TyParam::FreeVar(_) => self,
TyParam::App { name, args } => { TyParam::App { name, args } => {
let new_args = args.into_iter().map(|tp| tp.map_t(f)).collect::<Vec<_>>(); let new_args = args.into_iter().map(|tp| tp.map_t(f)).collect::<Vec<_>>();
TyParam::app(name, new_args) TyParam::app(name, new_args)
@ -1900,7 +1936,9 @@ impl TyParam {
} }
} }
TyParam::Value(val) => TyParam::Value(val.map_t(f)), TyParam::Value(val) => TyParam::Value(val.map_t(f)),
self_ => self_, TyParam::Type(t) => TyParam::t(f(*t)),
TyParam::Erased(t) => TyParam::erased(f(*t)),
TyParam::Mono(_) | TyParam::Failure => self,
} }
} }