mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-28 20:14:45 +00:00
fix: eliminate unsafe operations
This commit is contained in:
parent
cb6931e856
commit
60ea11aa3e
7 changed files with 31 additions and 33 deletions
|
@ -456,9 +456,9 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if lfv.is_linked() {
|
if lfv.is_linked() {
|
||||||
self.supertype_of(lfv.unsafe_crack(), rhs)
|
self.supertype_of(&lfv.crack(), rhs)
|
||||||
} else if rfv.is_linked() {
|
} else if rfv.is_linked() {
|
||||||
self.supertype_of(lhs, rfv.unsafe_crack())
|
self.supertype_of(lhs, &rfv.crack())
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -908,7 +908,7 @@ impl Context {
|
||||||
|
|
||||||
pub fn fields(&self, t: &Type) -> Dict<Field, Type> {
|
pub fn fields(&self, t: &Type) -> Dict<Field, Type> {
|
||||||
match t {
|
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::Record(fields) => fields.clone(),
|
||||||
Type::NamedTuple(fields) => fields.iter().cloned().collect(),
|
Type::NamedTuple(fields) => fields.iter().cloned().collect(),
|
||||||
Type::Refinement(refine) => self.fields(&refine.t),
|
Type::Refinement(refine) => self.fields(&refine.t),
|
||||||
|
@ -996,10 +996,10 @@ impl Context {
|
||||||
}
|
}
|
||||||
match (sup_p, sub_p) {
|
match (sup_p, sub_p) {
|
||||||
(TyParam::FreeVar(fv), _) if fv.is_linked() => {
|
(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() => {
|
(_, 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 {
|
(TyParam::Erased(t), _) => match variance {
|
||||||
Variance::Contravariant => {
|
Variance::Contravariant => {
|
||||||
|
@ -1300,10 +1300,10 @@ impl Context {
|
||||||
} else { Some(Any) }
|
} else { Some(Any) }
|
||||||
},
|
},
|
||||||
(TyParam::FreeVar(fv), p) if fv.is_linked() => {
|
(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() => {
|
(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(_)),
|
l @ (TyParam::FreeVar(_) | TyParam::Erased(_)),
|
||||||
|
@ -1414,7 +1414,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
match (lhs, rhs) {
|
match (lhs, rhs) {
|
||||||
(FreeVar(fv), other) | (other, FreeVar(fv)) if fv.is_linked() => {
|
(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(l), Refinement(r)) => Type::Refinement(self.union_refinement(l, r)),
|
||||||
(Refinement(refine), other) | (other, Refinement(refine))
|
(Refinement(refine), other) | (other, Refinement(refine))
|
||||||
|
@ -1662,7 +1662,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
match (lhs, rhs) {
|
match (lhs, rhs) {
|
||||||
(FreeVar(fv), other) | (other, FreeVar(fv)) if fv.is_linked() => {
|
(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)),
|
(Refinement(l), Refinement(r)) => Type::Refinement(self.intersection_refinement(l, r)),
|
||||||
(Structural(l), Structural(r)) => self.intersection(l, r).structuralize(),
|
(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}
|
// {i = Int; j = Int} and not {i = Int} == {j = Int}
|
||||||
// not {i = Int} and {i = Int; j = 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() {
|
(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::Record(rec2) => Type::Record(rec.clone().diff(rec2)),
|
||||||
_ => Type::Never,
|
_ => Type::Never,
|
||||||
},
|
},
|
||||||
|
@ -1974,7 +1974,7 @@ impl Context {
|
||||||
#[allow(clippy::only_used_in_recursion)]
|
#[allow(clippy::only_used_in_recursion)]
|
||||||
pub(crate) fn complement(&self, ty: &Type) -> Type {
|
pub(crate) fn complement(&self, ty: &Type) -> Type {
|
||||||
match ty {
|
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(),
|
Not(t) => *t.clone(),
|
||||||
Refinement(r) => Type::Refinement(r.clone().invert()),
|
Refinement(r) => Type::Refinement(r.clone().invert()),
|
||||||
Guard(guard) => Type::Guard(GuardType::new(
|
Guard(guard) => Type::Guard(GuardType::new(
|
||||||
|
@ -1999,7 +1999,7 @@ impl Context {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
match lhs {
|
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::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)),
|
Type::Or(l, r) => self.union(&self.diff(l, rhs), &self.diff(r, rhs)),
|
||||||
_ => lhs.clone(),
|
_ => lhs.clone(),
|
||||||
|
|
|
@ -3713,7 +3713,7 @@ impl Context {
|
||||||
match p {
|
match p {
|
||||||
TyParam::Value(v) => Ok(v_enum(set![v])),
|
TyParam::Value(v) => Ok(v_enum(set![v])),
|
||||||
TyParam::Erased(t) => Ok((*t).clone()),
|
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) => {
|
TyParam::FreeVar(fv) => {
|
||||||
if let Some(t) = fv.get_type() {
|
if let Some(t) = fv.get_type() {
|
||||||
Ok(t)
|
Ok(t)
|
||||||
|
|
|
@ -170,7 +170,7 @@ impl Generalizer {
|
||||||
/// ```
|
/// ```
|
||||||
fn generalize_t(&mut self, free_type: Type, uninit: bool) -> Type {
|
fn generalize_t(&mut self, free_type: Type, uninit: bool) -> Type {
|
||||||
match free_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),
|
FreeVar(fv) if fv.is_generalized() => Type::FreeVar(fv),
|
||||||
// TODO: Polymorphic generalization
|
// TODO: Polymorphic generalization
|
||||||
FreeVar(fv) if fv.level().unwrap() > self.level => {
|
FreeVar(fv) if fv.level().unwrap() > self.level => {
|
||||||
|
|
|
@ -983,7 +983,7 @@ impl Context {
|
||||||
// (obj: Failure).foo: Failure
|
// (obj: Failure).foo: Failure
|
||||||
Type::Failure => Triple::Ok(VarInfo::ILLEGAL),
|
Type::Failure => Triple::Ok(VarInfo::ILLEGAL),
|
||||||
Type::FreeVar(fv) if fv.is_linked() => {
|
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() => {
|
Type::FreeVar(fv) if fv.get_super().is_some() => {
|
||||||
let sup = fv.get_super().unwrap();
|
let sup = fv.get_super().unwrap();
|
||||||
|
@ -1846,7 +1846,7 @@ impl Context {
|
||||||
Type::FreeVar(fv) if fv.is_linked() => self.substitute_call(
|
Type::FreeVar(fv) if fv.is_linked() => self.substitute_call(
|
||||||
obj,
|
obj,
|
||||||
attr_name,
|
attr_name,
|
||||||
fv.unsafe_crack(),
|
&fv.crack(),
|
||||||
pos_args,
|
pos_args,
|
||||||
kw_args,
|
kw_args,
|
||||||
(var_args, kw_var_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<Vec<&'a TypeContext>> {
|
pub fn get_nominal_super_type_ctxs<'a>(&'a self, t: &Type) -> Option<Vec<&'a TypeContext>> {
|
||||||
match t {
|
match t {
|
||||||
Type::FreeVar(fv) if fv.is_linked() => {
|
Type::FreeVar(fv) if fv.is_linked() => self.get_nominal_super_type_ctxs(&fv.crack()),
|
||||||
self.get_nominal_super_type_ctxs(fv.unsafe_crack())
|
|
||||||
}
|
|
||||||
Type::FreeVar(fv) => {
|
Type::FreeVar(fv) => {
|
||||||
if let Some(sup) = fv.get_super() {
|
if let Some(sup) = fv.get_super() {
|
||||||
self.get_nominal_super_type_ctxs(&sup)
|
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> {
|
pub(crate) fn get_nominal_type_ctx<'a>(&'a self, typ: &Type) -> Option<&'a TypeContext> {
|
||||||
match typ {
|
match typ {
|
||||||
Type::FreeVar(fv) if fv.is_linked() => {
|
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);
|
return Some(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3287,7 +3285,7 @@ impl Context {
|
||||||
) -> Option<&'a mut TypeContext> {
|
) -> Option<&'a mut TypeContext> {
|
||||||
match typ {
|
match typ {
|
||||||
Type::FreeVar(fv) if fv.is_linked() => {
|
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);
|
return Some(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3957,7 +3955,7 @@ impl Context {
|
||||||
match typ {
|
match typ {
|
||||||
Type::And(_l, _r) => false,
|
Type::And(_l, _r) => false,
|
||||||
Type::Never => true,
|
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::FreeVar(_) => false,
|
||||||
Type::Or(l, r) => self.is_class(l) && self.is_class(r),
|
Type::Or(l, r) => self.is_class(l) && self.is_class(r),
|
||||||
Type::Proj { lhs, rhs } => self
|
Type::Proj { lhs, rhs } => self
|
||||||
|
@ -3980,7 +3978,7 @@ impl Context {
|
||||||
pub fn is_trait(&self, typ: &Type) -> bool {
|
pub fn is_trait(&self, typ: &Type) -> bool {
|
||||||
match typ {
|
match typ {
|
||||||
Type::Never => false,
|
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::FreeVar(_) => false,
|
||||||
Type::And(l, r) | Type::Or(l, r) => self.is_trait(l) && self.is_trait(r),
|
Type::And(l, r) | Type::Or(l, r) => self.is_trait(l) && self.is_trait(r),
|
||||||
Type::Proj { lhs, rhs } => self
|
Type::Proj { lhs, rhs } => self
|
||||||
|
|
|
@ -84,8 +84,8 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match (maybe_sub, maybe_sup) {
|
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(&fv.crack(), maybe_sup),
|
||||||
(_, FreeVar(fv)) if fv.is_linked() => self.occur(maybe_sub, fv.unsafe_crack()),
|
(_, FreeVar(fv)) if fv.is_linked() => self.occur(maybe_sub, &fv.crack()),
|
||||||
(Subr(subr), FreeVar(fv)) if fv.is_unbound() => {
|
(Subr(subr), FreeVar(fv)) if fv.is_unbound() => {
|
||||||
for default_t in subr.default_params.iter().map(|pt| pt.typ()) {
|
for default_t in subr.default_params.iter().map(|pt| pt.typ()) {
|
||||||
self.occur_inner(default_t, maybe_sup)?;
|
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<()> {
|
fn occur_inner(&self, maybe_sub: &Type, maybe_sup: &Type) -> TyCheckResult<()> {
|
||||||
match (maybe_sub, maybe_sup) {
|
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(&fv.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(maybe_sub, &fv.crack()),
|
||||||
(FreeVar(sub), FreeVar(sup)) => {
|
(FreeVar(sub), FreeVar(sup)) => {
|
||||||
if sub.addr_eq(sup) {
|
if sub.addr_eq(sup) {
|
||||||
Err(TyCheckErrors::from(TyCheckError::subtyping_error(
|
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) {
|
match (maybe_sub, maybe_sup) {
|
||||||
(FreeVar(sub_fv), _) if sub_fv.is_linked() => {
|
(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() => {
|
(_, 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's sup can be shrunk (take min), rfv's sub can be expanded (take union)
|
||||||
// lfvのsupは縮小可能(minを取る)、rfvのsubは拡大可能(unionを取る)
|
// lfvのsupは縮小可能(minを取る)、rfvのsubは拡大可能(unionを取る)
|
||||||
|
@ -1851,8 +1851,8 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> {
|
||||||
}
|
}
|
||||||
return None;
|
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(&fv.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(lhs, &fv.crack()),
|
||||||
// TODO: unify(?T, ?U) ?
|
// TODO: unify(?T, ?U) ?
|
||||||
(Type::FreeVar(_), Type::FreeVar(_)) => {}
|
(Type::FreeVar(_), Type::FreeVar(_)) => {}
|
||||||
(Type::FreeVar(fv), _) if fv.constraint_is_sandwiched() => {
|
(Type::FreeVar(fv), _) if fv.constraint_is_sandwiched() => {
|
||||||
|
|
|
@ -1105,7 +1105,7 @@ impl<T: Clone + Send + Sync + 'static> Free<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unwrap_linked(self) -> T {
|
pub fn unwrap_linked(&self) -> T {
|
||||||
match self.clone_inner() {
|
match self.clone_inner() {
|
||||||
FreeKind::Linked(t) | FreeKind::UndoableLinked { t, .. } => t,
|
FreeKind::Linked(t) | FreeKind::UndoableLinked { t, .. } => t,
|
||||||
FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => {
|
FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => {
|
||||||
|
|
|
@ -3550,7 +3550,7 @@ impl Type {
|
||||||
/// ```
|
/// ```
|
||||||
fn qvars_inner(&self) -> Set<(Str, Constraint)> {
|
fn qvars_inner(&self) -> Set<(Str, Constraint)> {
|
||||||
match self {
|
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() => {
|
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() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue