fix: recursion bugs of structural types

This commit is contained in:
Shunsuke Shibayama 2024-09-10 23:21:39 +09:00
parent 948a14b1af
commit beee3b8800
5 changed files with 27 additions and 5 deletions

View file

@ -7,7 +7,7 @@ use erg_common::dict::Dict;
use erg_common::set::Set;
use erg_common::style::colors::DEBUG_ERROR;
use erg_common::traits::StructuralEq;
use erg_common::{assume_unreachable, log};
use erg_common::{assume_unreachable, log, set_recursion_limit};
use erg_common::{Str, Triple};
use crate::context::eval::UndoableLinkedList;
@ -355,6 +355,7 @@ impl Context {
/// 単一化、評価等はここでは行わない、スーパータイプになる **可能性があるか** だけ判定する
/// ので、lhsが(未連携)型変数の場合は単一化せずにtrueを返す
pub(crate) fn structural_supertype_of(&self, lhs: &Type, rhs: &Type) -> bool {
set_recursion_limit!(false, 128);
match (lhs, rhs) {
// Proc :> Func if params are compatible
// * default params can be omitted (e.g. (Int, x := Int) -> Int <: (Int) -> Int)

View file

@ -1294,9 +1294,11 @@ impl Context {
})
.collect::<Vec<_>>();
let return_t = free_var(self.level, Constraint::new_type_of(Type));
let subr_t = fn_met(obj.t(), nd_params, None, d_params, None, return_t);
let mut subr_t = fn_met(obj.t(), nd_params, None, d_params, None, return_t);
if let Some(fv) = obj.ref_t().as_free() {
if let Some((_sub, sup)) = fv.get_subsup() {
// avoid recursion
*subr_t.mut_self_t().unwrap() = Never;
let vis = self
.instantiate_vis_modifier(&attr_name.vis)
.unwrap_or(VisibilityModifier::Public);

View file

@ -739,6 +739,9 @@ impl<T: Send + Clone> Free<T> {
pub fn forced_as_ref(&self) -> &FreeKind<T> {
unsafe { self.as_ptr().as_ref() }.unwrap()
}
pub fn forced_as_mut(&mut self) -> &mut FreeKind<T> {
unsafe { self.as_ptr().as_mut() }.unwrap()
}
}
impl Free<Type> {

View file

@ -3886,6 +3886,18 @@ impl Type {
}
}
pub fn mut_self_t(&mut self) -> Option<&mut Type> {
match self {
Self::FreeVar(fv) if fv.is_linked() => {
fv.forced_as_mut().linked_mut().and_then(|t| t.mut_self_t())
}
Self::Refinement(refine) => refine.t.mut_self_t(),
Self::Subr(subr) => subr.mut_self_t(),
Self::Quantified(quant) => quant.mut_self_t(),
_ => None,
}
}
pub fn non_default_params(&self) -> Option<&Vec<ParamTy>> {
match self {
Self::FreeVar(fv) if fv.is_linked() => fv
@ -3999,6 +4011,10 @@ impl Type {
pub fn mut_return_t(&mut self) -> Option<&mut Type> {
match self {
Self::FreeVar(fv) if fv.is_linked() => fv
.forced_as_mut()
.linked_mut()
.and_then(|t| t.mut_return_t()),
Self::Refinement(refine) => refine.t.mut_return_t(),
Self::Subr(SubrType { return_t, .. }) | Self::Callable { return_t, .. } => {
Some(return_t)