diff --git a/crates/erg_compiler/context/compare.rs b/crates/erg_compiler/context/compare.rs index 8acac4f0..dea8f8c4 100644 --- a/crates/erg_compiler/context/compare.rs +++ b/crates/erg_compiler/context/compare.rs @@ -456,9 +456,9 @@ impl Context { } } if lfv.is_linked() { - self.supertype_of(lfv.unsafe_crack(), rhs) + self.supertype_of(&lfv.crack(), rhs) } else if rfv.is_linked() { - self.supertype_of(lhs, rfv.unsafe_crack()) + self.supertype_of(lhs, &rfv.crack()) } else { false } @@ -908,7 +908,7 @@ impl Context { pub fn fields(&self, t: &Type) -> Dict { match t { - Type::FreeVar(fv) if fv.is_linked() => self.fields(fv.unsafe_crack()), + Type::FreeVar(fv) if fv.is_linked() => self.fields(&fv.crack()), Type::Record(fields) => fields.clone(), Type::NamedTuple(fields) => fields.iter().cloned().collect(), Type::Refinement(refine) => self.fields(&refine.t), @@ -996,10 +996,10 @@ impl Context { } match (sup_p, sub_p) { (TyParam::FreeVar(fv), _) if fv.is_linked() => { - self.supertype_of_tp(fv.unsafe_crack(), sub_p, variance) + self.supertype_of_tp(&fv.crack(), sub_p, variance) } (_, TyParam::FreeVar(fv)) if fv.is_linked() => { - self.supertype_of_tp(sup_p, fv.unsafe_crack(), variance) + self.supertype_of_tp(sup_p, &fv.crack(), variance) } (TyParam::Erased(t), _) => match variance { Variance::Contravariant => { @@ -1300,10 +1300,10 @@ impl Context { } else { Some(Any) } }, (TyParam::FreeVar(fv), p) if fv.is_linked() => { - self.try_cmp(fv.unsafe_crack(), p) + self.try_cmp(&fv.crack(), p) } (p, TyParam::FreeVar(fv)) if fv.is_linked() => { - self.try_cmp(p, fv.unsafe_crack()) + self.try_cmp(p, &fv.crack()) } ( l @ (TyParam::FreeVar(_) | TyParam::Erased(_)), @@ -1414,7 +1414,7 @@ impl Context { } match (lhs, rhs) { (FreeVar(fv), other) | (other, FreeVar(fv)) if fv.is_linked() => { - self.union(fv.unsafe_crack(), other) + self.union(&fv.crack(), other) } (Refinement(l), Refinement(r)) => Type::Refinement(self.union_refinement(l, r)), (Refinement(refine), other) | (other, Refinement(refine)) @@ -1662,7 +1662,7 @@ impl Context { } match (lhs, rhs) { (FreeVar(fv), other) | (other, FreeVar(fv)) if fv.is_linked() => { - self.intersection(fv.unsafe_crack(), other) + self.intersection(&fv.crack(), other) } (Refinement(l), Refinement(r)) => Type::Refinement(self.intersection_refinement(l, r)), (Structural(l), Structural(r)) => self.intersection(l, r).structuralize(), @@ -1679,7 +1679,7 @@ impl Context { // {i = Int; j = Int} and not {i = Int} == {j = Int} // not {i = Int} and {i = Int; j = Int} == {j = Int} (other @ Record(rec), Not(t)) | (Not(t), other @ Record(rec)) => match t.as_ref() { - Type::FreeVar(fv) => self.intersection(fv.unsafe_crack(), other), + Type::FreeVar(fv) => self.intersection(&fv.crack(), other), Type::Record(rec2) => Type::Record(rec.clone().diff(rec2)), _ => Type::Never, }, @@ -1974,7 +1974,7 @@ impl Context { #[allow(clippy::only_used_in_recursion)] pub(crate) fn complement(&self, ty: &Type) -> Type { match ty { - FreeVar(fv) if fv.is_linked() => self.complement(fv.unsafe_crack()), + FreeVar(fv) if fv.is_linked() => self.complement(&fv.crack()), Not(t) => *t.clone(), Refinement(r) => Type::Refinement(r.clone().invert()), Guard(guard) => Type::Guard(GuardType::new( @@ -1999,7 +1999,7 @@ impl Context { _ => {} } match lhs { - Type::FreeVar(fv) if fv.is_linked() => self.diff(fv.unsafe_crack(), rhs), + Type::FreeVar(fv) if fv.is_linked() => self.diff(&fv.crack(), rhs), // Type::And(l, r) => self.intersection(&self.diff(l, rhs), &self.diff(r, rhs)), Type::Or(l, r) => self.union(&self.diff(l, rhs), &self.diff(r, rhs)), _ => lhs.clone(), diff --git a/crates/erg_compiler/context/eval.rs b/crates/erg_compiler/context/eval.rs index 1a14858a..6fc5a7d0 100644 --- a/crates/erg_compiler/context/eval.rs +++ b/crates/erg_compiler/context/eval.rs @@ -3713,7 +3713,7 @@ impl Context { match p { TyParam::Value(v) => Ok(v_enum(set![v])), TyParam::Erased(t) => Ok((*t).clone()), - TyParam::FreeVar(fv) if fv.is_linked() => self.get_tp_t(fv.unsafe_crack()), + TyParam::FreeVar(fv) if fv.is_linked() => self.get_tp_t(&fv.crack()), TyParam::FreeVar(fv) => { if let Some(t) = fv.get_type() { Ok(t) diff --git a/crates/erg_compiler/context/generalize.rs b/crates/erg_compiler/context/generalize.rs index 93121cfc..13a0049a 100644 --- a/crates/erg_compiler/context/generalize.rs +++ b/crates/erg_compiler/context/generalize.rs @@ -170,7 +170,7 @@ impl Generalizer { /// ``` fn generalize_t(&mut self, free_type: Type, uninit: bool) -> Type { match free_type { - FreeVar(fv) if fv.is_linked() => self.generalize_t(fv.unsafe_crack().clone(), uninit), + FreeVar(fv) if fv.is_linked() => self.generalize_t(fv.unwrap_linked(), uninit), FreeVar(fv) if fv.is_generalized() => Type::FreeVar(fv), // TODO: Polymorphic generalization FreeVar(fv) if fv.level().unwrap() > self.level => { diff --git a/crates/erg_compiler/context/inquire.rs b/crates/erg_compiler/context/inquire.rs index 9c2ffcd9..a36dfc7f 100644 --- a/crates/erg_compiler/context/inquire.rs +++ b/crates/erg_compiler/context/inquire.rs @@ -983,7 +983,7 @@ impl Context { // (obj: Failure).foo: Failure Type::Failure => Triple::Ok(VarInfo::ILLEGAL), Type::FreeVar(fv) if fv.is_linked() => { - self.get_attr_info_from_attributive(fv.unsafe_crack(), ident, namespace) + self.get_attr_info_from_attributive(&fv.crack(), ident, namespace) } Type::FreeVar(fv) if fv.get_super().is_some() => { let sup = fv.get_super().unwrap(); @@ -1846,7 +1846,7 @@ impl Context { Type::FreeVar(fv) if fv.is_linked() => self.substitute_call( obj, attr_name, - fv.unsafe_crack(), + &fv.crack(), pos_args, kw_args, (var_args, kw_var_args), @@ -3002,9 +3002,7 @@ impl Context { pub fn get_nominal_super_type_ctxs<'a>(&'a self, t: &Type) -> Option> { match t { - Type::FreeVar(fv) if fv.is_linked() => { - self.get_nominal_super_type_ctxs(fv.unsafe_crack()) - } + Type::FreeVar(fv) if fv.is_linked() => self.get_nominal_super_type_ctxs(&fv.crack()), Type::FreeVar(fv) => { if let Some(sup) = fv.get_super() { self.get_nominal_super_type_ctxs(&sup) @@ -3110,7 +3108,7 @@ impl Context { pub(crate) fn get_nominal_type_ctx<'a>(&'a self, typ: &Type) -> Option<&'a TypeContext> { match typ { Type::FreeVar(fv) if fv.is_linked() => { - if let Some(res) = self.get_nominal_type_ctx(fv.unsafe_crack()) { + if let Some(res) = self.get_nominal_type_ctx(&fv.crack()) { return Some(res); } } @@ -3287,7 +3285,7 @@ impl Context { ) -> Option<&'a mut TypeContext> { match typ { Type::FreeVar(fv) if fv.is_linked() => { - if let Some(res) = self.get_mut_nominal_type_ctx(fv.unsafe_crack()) { + if let Some(res) = self.get_mut_nominal_type_ctx(&fv.crack()) { return Some(res); } } @@ -3957,7 +3955,7 @@ impl Context { match typ { Type::And(_l, _r) => false, Type::Never => true, - Type::FreeVar(fv) if fv.is_linked() => self.is_class(fv.unsafe_crack()), + Type::FreeVar(fv) if fv.is_linked() => self.is_class(&fv.crack()), Type::FreeVar(_) => false, Type::Or(l, r) => self.is_class(l) && self.is_class(r), Type::Proj { lhs, rhs } => self @@ -3980,7 +3978,7 @@ impl Context { pub fn is_trait(&self, typ: &Type) -> bool { match typ { Type::Never => false, - Type::FreeVar(fv) if fv.is_linked() => self.is_class(fv.unsafe_crack()), + Type::FreeVar(fv) if fv.is_linked() => self.is_class(&fv.crack()), Type::FreeVar(_) => false, Type::And(l, r) | Type::Or(l, r) => self.is_trait(l) && self.is_trait(r), Type::Proj { lhs, rhs } => self diff --git a/crates/erg_compiler/context/unify.rs b/crates/erg_compiler/context/unify.rs index 0629f89f..3dc1d551 100644 --- a/crates/erg_compiler/context/unify.rs +++ b/crates/erg_compiler/context/unify.rs @@ -84,8 +84,8 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> { } } match (maybe_sub, maybe_sup) { - (FreeVar(fv), _) if fv.is_linked() => self.occur(fv.unsafe_crack(), maybe_sup), - (_, FreeVar(fv)) if fv.is_linked() => self.occur(maybe_sub, fv.unsafe_crack()), + (FreeVar(fv), _) if fv.is_linked() => self.occur(&fv.crack(), maybe_sup), + (_, FreeVar(fv)) if fv.is_linked() => self.occur(maybe_sub, &fv.crack()), (Subr(subr), FreeVar(fv)) if fv.is_unbound() => { for default_t in subr.default_params.iter().map(|pt| pt.typ()) { self.occur_inner(default_t, maybe_sup)?; @@ -173,8 +173,8 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> { fn occur_inner(&self, maybe_sub: &Type, maybe_sup: &Type) -> TyCheckResult<()> { match (maybe_sub, maybe_sup) { - (FreeVar(fv), _) if fv.is_linked() => self.occur_inner(fv.unsafe_crack(), maybe_sup), - (_, FreeVar(fv)) if fv.is_linked() => self.occur_inner(maybe_sub, fv.unsafe_crack()), + (FreeVar(fv), _) if fv.is_linked() => self.occur_inner(&fv.crack(), maybe_sup), + (_, FreeVar(fv)) if fv.is_linked() => self.occur_inner(maybe_sub, &fv.crack()), (FreeVar(sub), FreeVar(sup)) => { if sub.addr_eq(sup) { Err(TyCheckErrors::from(TyCheckError::subtyping_error( @@ -1000,10 +1000,10 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> { } match (maybe_sub, maybe_sup) { (FreeVar(sub_fv), _) if sub_fv.is_linked() => { - self.sub_unify(sub_fv.unsafe_crack(), maybe_sup)?; + self.sub_unify(&sub_fv.unwrap_linked(), maybe_sup)?; } (_, FreeVar(sup_fv)) if sup_fv.is_linked() => { - self.sub_unify(maybe_sub, sup_fv.unsafe_crack())?; + self.sub_unify(maybe_sub, &sup_fv.unwrap_linked())?; } // lfv's sup can be shrunk (take min), rfv's sub can be expanded (take union) // lfvのsupは縮小可能(minを取る)、rfvのsubは拡大可能(unionを取る) @@ -1851,8 +1851,8 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> { } return None; } - (Type::FreeVar(fv), _) if fv.is_linked() => return self.unify(fv.unsafe_crack(), rhs), - (_, Type::FreeVar(fv)) if fv.is_linked() => return self.unify(lhs, fv.unsafe_crack()), + (Type::FreeVar(fv), _) if fv.is_linked() => return self.unify(&fv.crack(), rhs), + (_, Type::FreeVar(fv)) if fv.is_linked() => return self.unify(lhs, &fv.crack()), // TODO: unify(?T, ?U) ? (Type::FreeVar(_), Type::FreeVar(_)) => {} (Type::FreeVar(fv), _) if fv.constraint_is_sandwiched() => { diff --git a/crates/erg_compiler/ty/free.rs b/crates/erg_compiler/ty/free.rs index ecf7b110..36edcd83 100644 --- a/crates/erg_compiler/ty/free.rs +++ b/crates/erg_compiler/ty/free.rs @@ -1105,7 +1105,7 @@ impl Free { } } - pub fn unwrap_linked(self) -> T { + pub fn unwrap_linked(&self) -> T { match self.clone_inner() { FreeKind::Linked(t) | FreeKind::UndoableLinked { t, .. } => t, FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => { diff --git a/crates/erg_compiler/ty/mod.rs b/crates/erg_compiler/ty/mod.rs index eb85caa0..5c798dd7 100644 --- a/crates/erg_compiler/ty/mod.rs +++ b/crates/erg_compiler/ty/mod.rs @@ -3550,7 +3550,7 @@ impl Type { /// ``` fn qvars_inner(&self) -> Set<(Str, Constraint)> { match self { - Self::FreeVar(fv) if fv.is_linked() => fv.unsafe_crack().qvars_inner(), + Self::FreeVar(fv) if fv.is_linked() => fv.unwrap_linked().qvars_inner(), Self::FreeVar(fv) if !fv.constraint_is_uninited() => { let base = set! {(fv.unbound_name().unwrap(), fv.constraint().unwrap())}; if let Some((sub, sup)) = fv.get_subsup() {