mirror of
https://github.com/erg-lang/erg.git
synced 2025-07-24 05:26:24 +00:00
fix: sub-unification bugs
This commit is contained in:
parent
b318395a32
commit
0079aed860
10 changed files with 190 additions and 153 deletions
|
@ -1184,7 +1184,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
}
|
||||
if let Type::FreeVar(fv) = &lhs {
|
||||
if let Some(fv) = lhs.as_free() {
|
||||
let (sub, sup) = fv.get_subsup().unwrap();
|
||||
if self.is_trait(&sup) && !self.trait_impl_exists(&sub, &sup) {
|
||||
// link to `Never` to prevent double errors from being reported
|
||||
|
|
|
@ -23,70 +23,69 @@ use Variance::*;
|
|||
impl Context {
|
||||
pub const TOP_LEVEL: usize = 1;
|
||||
|
||||
fn generalize_tp(&self, free: TyParam, variance: Variance, uninit: bool) -> TyParam {
|
||||
fn generalize_tp(
|
||||
&self,
|
||||
free: TyParam,
|
||||
variance: Variance,
|
||||
qnames: &Set<Str>,
|
||||
uninit: bool,
|
||||
) -> TyParam {
|
||||
match free {
|
||||
TyParam::Type(t) => TyParam::t(self.generalize_t_inner(*t, variance, uninit)),
|
||||
TyParam::Type(t) => TyParam::t(self.generalize_t_inner(*t, variance, qnames, uninit)),
|
||||
TyParam::FreeVar(fv) if fv.is_generalized() => TyParam::FreeVar(fv),
|
||||
TyParam::FreeVar(fv) if fv.is_linked() => {
|
||||
self.generalize_tp(fv.crack().clone(), variance, uninit)
|
||||
/*let fv_mut = unsafe { fv.as_ptr().as_mut().unwrap() };
|
||||
if let FreeKind::Linked(tp) = fv_mut {
|
||||
*tp = self.generalize_tp(tp.clone(), variance, uninit);
|
||||
} else {
|
||||
assume_unreachable!()
|
||||
}
|
||||
TyParam::FreeVar(fv)*/
|
||||
self.generalize_tp(fv.crack().clone(), variance, qnames, uninit)
|
||||
}
|
||||
// TODO: Polymorphic generalization
|
||||
TyParam::FreeVar(fv) if fv.level() > Some(self.level) => {
|
||||
let constr = self.generalize_constraint(&fv, variance);
|
||||
let constr = self.generalize_constraint(&fv, qnames, variance);
|
||||
fv.update_constraint(constr, true);
|
||||
fv.generalize();
|
||||
TyParam::FreeVar(fv)
|
||||
}
|
||||
TyParam::Array(tps) => TyParam::Array(
|
||||
tps.into_iter()
|
||||
.map(|tp| self.generalize_tp(tp, variance, uninit))
|
||||
.map(|tp| self.generalize_tp(tp, variance, qnames, uninit))
|
||||
.collect(),
|
||||
),
|
||||
TyParam::Tuple(tps) => TyParam::Tuple(
|
||||
tps.into_iter()
|
||||
.map(|tp| self.generalize_tp(tp, variance, uninit))
|
||||
.map(|tp| self.generalize_tp(tp, variance, qnames, uninit))
|
||||
.collect(),
|
||||
),
|
||||
TyParam::Dict(tps) => TyParam::Dict(
|
||||
tps.into_iter()
|
||||
.map(|(k, v)| {
|
||||
(
|
||||
self.generalize_tp(k, variance, uninit),
|
||||
self.generalize_tp(v, variance, uninit),
|
||||
self.generalize_tp(k, variance, qnames, uninit),
|
||||
self.generalize_tp(v, variance, qnames, uninit),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
TyParam::Record(rec) => TyParam::Record(
|
||||
rec.into_iter()
|
||||
.map(|(field, tp)| (field, self.generalize_tp(tp, variance, uninit)))
|
||||
.map(|(field, tp)| (field, self.generalize_tp(tp, variance, qnames, uninit)))
|
||||
.collect(),
|
||||
),
|
||||
TyParam::Lambda(lambda) => {
|
||||
let nd_params = lambda
|
||||
.nd_params
|
||||
.into_iter()
|
||||
.map(|pt| pt.map_type(|t| self.generalize_t_inner(t, variance, uninit)))
|
||||
.map(|pt| pt.map_type(|t| self.generalize_t_inner(t, variance, qnames, uninit)))
|
||||
.collect::<Vec<_>>();
|
||||
let var_params = lambda
|
||||
.var_params
|
||||
.map(|pt| pt.map_type(|t| self.generalize_t_inner(t, variance, uninit)));
|
||||
let var_params = lambda.var_params.map(|pt| {
|
||||
pt.map_type(|t| self.generalize_t_inner(t, variance, qnames, uninit))
|
||||
});
|
||||
let d_params = lambda
|
||||
.d_params
|
||||
.into_iter()
|
||||
.map(|pt| pt.map_type(|t| self.generalize_t_inner(t, variance, uninit)))
|
||||
.map(|pt| pt.map_type(|t| self.generalize_t_inner(t, variance, qnames, uninit)))
|
||||
.collect::<Vec<_>>();
|
||||
let body = lambda
|
||||
.body
|
||||
.into_iter()
|
||||
.map(|tp| self.generalize_tp(tp, variance, uninit))
|
||||
.map(|tp| self.generalize_tp(tp, variance, qnames, uninit))
|
||||
.collect();
|
||||
TyParam::Lambda(TyParamLambda::new(
|
||||
lambda.const_,
|
||||
|
@ -98,24 +97,26 @@ impl Context {
|
|||
}
|
||||
TyParam::FreeVar(_) => free,
|
||||
TyParam::Proj { obj, attr } => {
|
||||
let obj = self.generalize_tp(*obj, variance, uninit);
|
||||
let obj = self.generalize_tp(*obj, variance, qnames, uninit);
|
||||
TyParam::proj(obj, attr)
|
||||
}
|
||||
TyParam::Erased(t) => TyParam::erased(self.generalize_t_inner(*t, variance, uninit)),
|
||||
TyParam::Erased(t) => {
|
||||
TyParam::erased(self.generalize_t_inner(*t, variance, qnames, uninit))
|
||||
}
|
||||
TyParam::App { name, args } => {
|
||||
let args = args
|
||||
.into_iter()
|
||||
.map(|tp| self.generalize_tp(tp, variance, uninit))
|
||||
.map(|tp| self.generalize_tp(tp, variance, qnames, uninit))
|
||||
.collect();
|
||||
TyParam::App { name, args }
|
||||
}
|
||||
TyParam::BinOp { op, lhs, rhs } => {
|
||||
let lhs = self.generalize_tp(*lhs, variance, uninit);
|
||||
let rhs = self.generalize_tp(*rhs, variance, uninit);
|
||||
let lhs = self.generalize_tp(*lhs, variance, qnames, uninit);
|
||||
let rhs = self.generalize_tp(*rhs, variance, qnames, uninit);
|
||||
TyParam::bin(op, lhs, rhs)
|
||||
}
|
||||
TyParam::UnaryOp { op, val } => {
|
||||
let val = self.generalize_tp(*val, variance, uninit);
|
||||
let val = self.generalize_tp(*val, variance, qnames, uninit);
|
||||
TyParam::unary(op, val)
|
||||
}
|
||||
other if other.has_no_unbound_var() => other,
|
||||
|
@ -126,7 +127,7 @@ impl Context {
|
|||
/// Quantification occurs only once in function types.
|
||||
/// Therefore, this method is called only once at the top level, and `generalize_t_inner` is called inside.
|
||||
pub(crate) fn generalize_t(&self, free_type: Type) -> Type {
|
||||
let maybe_unbound_t = self.generalize_t_inner(free_type, Covariant, false);
|
||||
let maybe_unbound_t = self.generalize_t_inner(free_type, Covariant, &set! {}, false);
|
||||
if maybe_unbound_t.is_subr() && maybe_unbound_t.has_qvar() {
|
||||
maybe_unbound_t.quantify()
|
||||
} else {
|
||||
|
@ -141,56 +142,64 @@ impl Context {
|
|||
/// generalize_t(?T(<: Add(?T(<: Eq(?T(<: ...)))) -> ?T) == |'T <: Add('T)| 'T -> 'T
|
||||
/// generalize_t(?T(<: TraitX) -> Int) == TraitX -> Int // 戻り値に現れないなら量化しない
|
||||
/// ```
|
||||
fn generalize_t_inner(&self, free_type: Type, variance: Variance, uninit: bool) -> Type {
|
||||
fn generalize_t_inner(
|
||||
&self,
|
||||
free_type: Type,
|
||||
variance: Variance,
|
||||
qnames: &Set<Str>,
|
||||
uninit: bool,
|
||||
) -> Type {
|
||||
match free_type {
|
||||
FreeVar(fv) if fv.is_linked() => {
|
||||
self.generalize_t_inner(fv.crack().clone(), variance, uninit)
|
||||
/*let fv_mut = unsafe { fv.as_ptr().as_mut().unwrap() };
|
||||
if let FreeKind::Linked(t) = fv_mut {
|
||||
*t = self.generalize_t_inner(t.clone(), variance, uninit);
|
||||
} else {
|
||||
assume_unreachable!()
|
||||
}
|
||||
Type::FreeVar(fv)*/
|
||||
self.generalize_t_inner(fv.crack().clone(), variance, qnames, uninit)
|
||||
}
|
||||
FreeVar(fv) if fv.is_generalized() => Type::FreeVar(fv),
|
||||
// TODO: Polymorphic generalization
|
||||
FreeVar(fv) if fv.level().unwrap() > self.level => {
|
||||
if uninit {
|
||||
// use crate::ty::free::GENERIC_LEVEL;
|
||||
// return named_free_var(fv.unbound_name().unwrap(), GENERIC_LEVEL, Constraint::Uninited);
|
||||
fv.generalize();
|
||||
return Type::FreeVar(fv);
|
||||
}
|
||||
if let Some((l, r)) = fv.get_subsup() {
|
||||
if let Some((sub, sup)) = fv.get_subsup() {
|
||||
// |Int <: T <: Int| T -> T ==> Int -> Int
|
||||
if l == r {
|
||||
let t = self.generalize_t_inner(l, variance, uninit);
|
||||
if sub == sup {
|
||||
let t = self.generalize_t_inner(sub, variance, qnames, uninit);
|
||||
fv.forced_link(&t);
|
||||
FreeVar(fv)
|
||||
} else if r != Obj && self.is_class(&r) && variance == Contravariant {
|
||||
} else if sup != Obj
|
||||
&& !qnames.contains(&fv.unbound_name().unwrap())
|
||||
&& variance == Contravariant
|
||||
{
|
||||
// |T <: Bool| T -> Int ==> Bool -> Int
|
||||
self.generalize_t_inner(r, variance, uninit)
|
||||
} else if l != Never && self.is_class(&l) && variance == Covariant {
|
||||
self.generalize_t_inner(sup, variance, qnames, uninit)
|
||||
} else if sub != Never
|
||||
&& !qnames.contains(&fv.unbound_name().unwrap())
|
||||
&& variance == Covariant
|
||||
{
|
||||
// |T :> Int| X -> T ==> X -> Int
|
||||
self.generalize_t_inner(l, variance, uninit)
|
||||
self.generalize_t_inner(sub, variance, qnames, uninit)
|
||||
} else {
|
||||
fv.update_constraint(self.generalize_constraint(&fv, variance), true);
|
||||
fv.update_constraint(
|
||||
self.generalize_constraint(&fv, qnames, variance),
|
||||
true,
|
||||
);
|
||||
fv.generalize();
|
||||
Type::FreeVar(fv)
|
||||
}
|
||||
} else {
|
||||
// ?S(: Str) => 'S
|
||||
fv.update_constraint(self.generalize_constraint(&fv, variance), true);
|
||||
fv.update_constraint(self.generalize_constraint(&fv, qnames, variance), true);
|
||||
fv.generalize();
|
||||
Type::FreeVar(fv)
|
||||
}
|
||||
}
|
||||
Subr(mut subr) => {
|
||||
let qnames = subr.essential_qnames();
|
||||
subr.non_default_params.iter_mut().for_each(|nd_param| {
|
||||
*nd_param.typ_mut() = self.generalize_t_inner(
|
||||
mem::take(nd_param.typ_mut()),
|
||||
Contravariant,
|
||||
&qnames,
|
||||
uninit,
|
||||
);
|
||||
});
|
||||
|
@ -198,6 +207,7 @@ impl Context {
|
|||
*var_args.typ_mut() = self.generalize_t_inner(
|
||||
mem::take(var_args.typ_mut()),
|
||||
Contravariant,
|
||||
&qnames,
|
||||
uninit,
|
||||
);
|
||||
}
|
||||
|
@ -205,10 +215,11 @@ impl Context {
|
|||
*d_param.typ_mut() = self.generalize_t_inner(
|
||||
mem::take(d_param.typ_mut()),
|
||||
Contravariant,
|
||||
&qnames,
|
||||
uninit,
|
||||
);
|
||||
});
|
||||
let return_t = self.generalize_t_inner(*subr.return_t, Covariant, uninit);
|
||||
let return_t = self.generalize_t_inner(*subr.return_t, Covariant, &qnames, uninit);
|
||||
subr_t(
|
||||
subr.kind,
|
||||
subr.non_default_params,
|
||||
|
@ -220,30 +231,34 @@ impl Context {
|
|||
Record(rec) => {
|
||||
let fields = rec
|
||||
.into_iter()
|
||||
.map(|(name, t)| (name, self.generalize_t_inner(t, variance, uninit)))
|
||||
.map(|(name, t)| (name, self.generalize_t_inner(t, variance, qnames, uninit)))
|
||||
.collect();
|
||||
Type::Record(fields)
|
||||
}
|
||||
Callable { .. } => todo!(),
|
||||
Ref(t) => ref_(self.generalize_t_inner(*t, variance, uninit)),
|
||||
Ref(t) => ref_(self.generalize_t_inner(*t, variance, qnames, uninit)),
|
||||
RefMut { before, after } => {
|
||||
let after = after.map(|aft| self.generalize_t_inner(*aft, variance, uninit));
|
||||
ref_mut(self.generalize_t_inner(*before, variance, uninit), after)
|
||||
let after =
|
||||
after.map(|aft| self.generalize_t_inner(*aft, variance, qnames, uninit));
|
||||
ref_mut(
|
||||
self.generalize_t_inner(*before, variance, qnames, uninit),
|
||||
after,
|
||||
)
|
||||
}
|
||||
Refinement(refine) => {
|
||||
let t = self.generalize_t_inner(*refine.t, variance, uninit);
|
||||
let pred = self.generalize_pred(*refine.pred, variance, uninit);
|
||||
let t = self.generalize_t_inner(*refine.t, variance, qnames, uninit);
|
||||
let pred = self.generalize_pred(*refine.pred, variance, qnames, uninit);
|
||||
refinement(refine.var, t, pred)
|
||||
}
|
||||
Poly { name, mut params } => {
|
||||
let params = params
|
||||
.iter_mut()
|
||||
.map(|p| self.generalize_tp(mem::take(p), variance, uninit))
|
||||
.map(|p| self.generalize_tp(mem::take(p), variance, qnames, uninit))
|
||||
.collect::<Vec<_>>();
|
||||
poly(name, params)
|
||||
}
|
||||
Proj { lhs, rhs } => {
|
||||
let lhs = self.generalize_t_inner(*lhs, variance, uninit);
|
||||
let lhs = self.generalize_t_inner(*lhs, variance, qnames, uninit);
|
||||
proj(lhs, rhs)
|
||||
}
|
||||
ProjCall {
|
||||
|
@ -251,83 +266,94 @@ impl Context {
|
|||
attr_name,
|
||||
mut args,
|
||||
} => {
|
||||
let lhs = self.generalize_tp(*lhs, variance, uninit);
|
||||
let lhs = self.generalize_tp(*lhs, variance, qnames, uninit);
|
||||
for arg in args.iter_mut() {
|
||||
*arg = self.generalize_tp(mem::take(arg), variance, uninit);
|
||||
*arg = self.generalize_tp(mem::take(arg), variance, qnames, uninit);
|
||||
}
|
||||
proj_call(lhs, attr_name, args)
|
||||
}
|
||||
And(l, r) => {
|
||||
let l = self.generalize_t_inner(*l, variance, uninit);
|
||||
let r = self.generalize_t_inner(*r, variance, uninit);
|
||||
let l = self.generalize_t_inner(*l, variance, qnames, uninit);
|
||||
let r = self.generalize_t_inner(*r, variance, qnames, uninit);
|
||||
// not `self.intersection` because types are generalized
|
||||
and(l, r)
|
||||
}
|
||||
Or(l, r) => {
|
||||
let l = self.generalize_t_inner(*l, variance, uninit);
|
||||
let r = self.generalize_t_inner(*r, variance, uninit);
|
||||
let l = self.generalize_t_inner(*l, variance, qnames, uninit);
|
||||
let r = self.generalize_t_inner(*r, variance, qnames, uninit);
|
||||
// not `self.union` because types are generalized
|
||||
or(l, r)
|
||||
}
|
||||
Not(l) => not(self.generalize_t_inner(*l, variance, uninit)),
|
||||
Not(l) => not(self.generalize_t_inner(*l, variance, qnames, uninit)),
|
||||
Structural(t) => self
|
||||
.generalize_t_inner(*t, variance, uninit)
|
||||
.generalize_t_inner(*t, variance, qnames, uninit)
|
||||
.structuralize(),
|
||||
// REVIEW: その他何でもそのまま通していいのか?
|
||||
other => other,
|
||||
}
|
||||
}
|
||||
|
||||
fn generalize_constraint<T: CanbeFree>(&self, fv: &Free<T>, variance: Variance) -> Constraint {
|
||||
fn generalize_constraint<T: CanbeFree>(
|
||||
&self,
|
||||
fv: &Free<T>,
|
||||
qnames: &Set<Str>,
|
||||
variance: Variance,
|
||||
) -> Constraint {
|
||||
if let Some((sub, sup)) = fv.get_subsup() {
|
||||
let sub = self.generalize_t_inner(sub, variance, true);
|
||||
let sup = self.generalize_t_inner(sup, variance, true);
|
||||
let sub = self.generalize_t_inner(sub, variance, qnames, true);
|
||||
let sup = self.generalize_t_inner(sup, variance, qnames, true);
|
||||
Constraint::new_sandwiched(sub, sup)
|
||||
} else if let Some(ty) = fv.get_type() {
|
||||
let t = self.generalize_t_inner(ty, variance, true);
|
||||
let t = self.generalize_t_inner(ty, variance, qnames, true);
|
||||
Constraint::new_type_of(t)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
fn generalize_pred(&self, pred: Predicate, variance: Variance, uninit: bool) -> Predicate {
|
||||
fn generalize_pred(
|
||||
&self,
|
||||
pred: Predicate,
|
||||
variance: Variance,
|
||||
qnames: &Set<Str>,
|
||||
uninit: bool,
|
||||
) -> Predicate {
|
||||
match pred {
|
||||
Predicate::Const(_) => pred,
|
||||
Predicate::Value(ValueObj::Type(mut typ)) => {
|
||||
*typ.typ_mut() =
|
||||
self.generalize_t_inner(mem::take(typ.typ_mut()), variance, uninit);
|
||||
self.generalize_t_inner(mem::take(typ.typ_mut()), variance, qnames, uninit);
|
||||
Predicate::Value(ValueObj::Type(typ))
|
||||
}
|
||||
Predicate::Value(_) => pred,
|
||||
Predicate::Equal { lhs, rhs } => {
|
||||
let rhs = self.generalize_tp(rhs, variance, uninit);
|
||||
let rhs = self.generalize_tp(rhs, variance, qnames, uninit);
|
||||
Predicate::eq(lhs, rhs)
|
||||
}
|
||||
Predicate::GreaterEqual { lhs, rhs } => {
|
||||
let rhs = self.generalize_tp(rhs, variance, uninit);
|
||||
let rhs = self.generalize_tp(rhs, variance, qnames, uninit);
|
||||
Predicate::ge(lhs, rhs)
|
||||
}
|
||||
Predicate::LessEqual { lhs, rhs } => {
|
||||
let rhs = self.generalize_tp(rhs, variance, uninit);
|
||||
let rhs = self.generalize_tp(rhs, variance, qnames, uninit);
|
||||
Predicate::le(lhs, rhs)
|
||||
}
|
||||
Predicate::NotEqual { lhs, rhs } => {
|
||||
let rhs = self.generalize_tp(rhs, variance, uninit);
|
||||
let rhs = self.generalize_tp(rhs, variance, qnames, uninit);
|
||||
Predicate::ne(lhs, rhs)
|
||||
}
|
||||
Predicate::And(lhs, rhs) => {
|
||||
let lhs = self.generalize_pred(*lhs, variance, uninit);
|
||||
let rhs = self.generalize_pred(*rhs, variance, uninit);
|
||||
let lhs = self.generalize_pred(*lhs, variance, qnames, uninit);
|
||||
let rhs = self.generalize_pred(*rhs, variance, qnames, uninit);
|
||||
Predicate::and(lhs, rhs)
|
||||
}
|
||||
Predicate::Or(lhs, rhs) => {
|
||||
let lhs = self.generalize_pred(*lhs, variance, uninit);
|
||||
let rhs = self.generalize_pred(*rhs, variance, uninit);
|
||||
let lhs = self.generalize_pred(*lhs, variance, qnames, uninit);
|
||||
let rhs = self.generalize_pred(*rhs, variance, qnames, uninit);
|
||||
Predicate::or(lhs, rhs)
|
||||
}
|
||||
Predicate::Not(pred) => {
|
||||
let pred = self.generalize_pred(*pred, variance, uninit);
|
||||
let pred = self.generalize_pred(*pred, variance, qnames, uninit);
|
||||
!pred
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ impl Context {
|
|||
expected: &Type,
|
||||
found: &Type,
|
||||
) -> Option<String> {
|
||||
let expected = if let Type::FreeVar(fv) = expected {
|
||||
let expected = if let Some(fv) = expected.as_free() {
|
||||
if fv.is_linked() {
|
||||
fv.crack().clone()
|
||||
} else {
|
||||
|
@ -191,7 +191,7 @@ impl Context {
|
|||
pub(crate) fn get_no_candidate_hint(&self, proj: &Type) -> Option<String> {
|
||||
match proj {
|
||||
Type::Proj { lhs, rhs: _ } => {
|
||||
if let Type::FreeVar(fv) = lhs.as_ref() {
|
||||
if let Some(fv) = lhs.as_free() {
|
||||
let (sub, sup) = fv.get_subsup()?;
|
||||
let (verb, preposition, sequence) = Self::get_verb_and_preposition(&sup)?;
|
||||
let sup = *option_enum_unwrap!(sup.typarams().get(0)?.clone(), TyParam::Type)?;
|
||||
|
|
|
@ -563,7 +563,7 @@ impl Context {
|
|||
// => ?T(<: Structural({ .aaa = ?U }))
|
||||
if self.in_subr() && cfg!(feature = "py_compatible") {
|
||||
let t = free_var(self.level, Constraint::new_type_of(Type));
|
||||
if let Type::FreeVar(fv) = obj.ref_t() {
|
||||
if let Some(fv) = obj.ref_t().as_free() {
|
||||
if fv.get_sub().is_some() {
|
||||
let vis = self.instantiate_vis_modifier(&ident.vis).unwrap();
|
||||
let structural = Type::Record(
|
||||
|
@ -910,7 +910,7 @@ 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, return_t);
|
||||
if let Type::FreeVar(fv) = obj.ref_t() {
|
||||
if let Some(fv) = obj.ref_t().as_free() {
|
||||
if fv.get_sub().is_some() {
|
||||
let vis = self.instantiate_vis_modifier(&attr_name.vis).unwrap();
|
||||
let structural = Type::Record(
|
||||
|
|
|
@ -224,7 +224,7 @@ impl Context {
|
|||
Ok(tp)
|
||||
} else if let Some(t) = tmp_tv_cache.get_tyvar(&name) {
|
||||
let t = t.clone();
|
||||
if let Type::FreeVar(fv) = &t {
|
||||
if let Some(fv) = t.as_free() {
|
||||
if fv
|
||||
.constraint()
|
||||
.map(|cons| cons.is_uninited())
|
||||
|
|
|
@ -307,6 +307,27 @@ impl Context {
|
|||
Ok(vi)
|
||||
}
|
||||
|
||||
fn type_self_param(
|
||||
&self,
|
||||
pat: &ast::ParamPattern,
|
||||
name: &VarName,
|
||||
spec_t: &Type,
|
||||
errs: &mut TyCheckErrors,
|
||||
) {
|
||||
if let Some(self_t) = self.rec_get_self_t() {
|
||||
let self_t = match pat {
|
||||
ast::ParamPattern::Ref(_) => ref_(self_t),
|
||||
ast::ParamPattern::RefMut(_) => ref_mut(self_t, None),
|
||||
_ => self_t,
|
||||
};
|
||||
if let Err(es) = self.sub_unify(spec_t, &self_t, name, Some(name.inspect())) {
|
||||
errs.extend(es);
|
||||
}
|
||||
} else {
|
||||
log!(err "self_t is None");
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO: sig should be immutable
|
||||
/// 宣言が既にある場合、opt_decl_tに宣言の型を渡す
|
||||
fn assign_param(
|
||||
|
@ -387,15 +408,7 @@ impl Context {
|
|||
spec_t
|
||||
};
|
||||
if &name.inspect()[..] == "self" {
|
||||
if let Some(self_t) = self.rec_get_self_t() {
|
||||
if let Err(es) =
|
||||
self.sub_unify(&spec_t, &self_t, name, Some(name.inspect()))
|
||||
{
|
||||
errs.extend(es);
|
||||
}
|
||||
} else {
|
||||
log!(err "self_t is None");
|
||||
}
|
||||
self.type_self_param(&sig.raw.pat, name, &spec_t, &mut errs);
|
||||
}
|
||||
let def_id = DefId(get_hash(&(&self.name, name)));
|
||||
let kind = VarKind::parameter(def_id, is_var_params, default);
|
||||
|
@ -446,15 +459,7 @@ impl Context {
|
|||
Err(errs) => (Type::Failure, errs),
|
||||
};
|
||||
if &name.inspect()[..] == "self" {
|
||||
if let Some(self_t) = self.rec_get_self_t() {
|
||||
if let Err(es) =
|
||||
self.sub_unify(&spec_t, &ref_(self_t), name, Some(name.inspect()))
|
||||
{
|
||||
errs.extend(es);
|
||||
}
|
||||
} else {
|
||||
log!(err "self_t is None");
|
||||
}
|
||||
self.type_self_param(&sig.raw.pat, name, &spec_t, &mut errs);
|
||||
}
|
||||
let kind = VarKind::parameter(
|
||||
DefId(get_hash(&(&self.name, name))),
|
||||
|
@ -506,18 +511,7 @@ impl Context {
|
|||
Err(errs) => (Type::Failure, errs),
|
||||
};
|
||||
if &name.inspect()[..] == "self" {
|
||||
if let Some(self_t) = self.rec_get_self_t() {
|
||||
if let Err(es) = self.sub_unify(
|
||||
&spec_t,
|
||||
&ref_mut(self_t, None),
|
||||
name,
|
||||
Some(name.inspect()),
|
||||
) {
|
||||
errs.extend(es);
|
||||
}
|
||||
} else {
|
||||
log!(err "self_t is None");
|
||||
}
|
||||
self.type_self_param(&sig.raw.pat, name, &spec_t, &mut errs);
|
||||
}
|
||||
let kind = VarKind::parameter(
|
||||
DefId(get_hash(&(&self.name, name))),
|
||||
|
@ -862,7 +856,7 @@ impl Context {
|
|||
let Some((_, vi)) = self.get_var_info(ident.inspect()) else {
|
||||
return;
|
||||
};
|
||||
if let Type::FreeVar(fv) = &vi.t {
|
||||
if let Some(fv) = vi.t.as_free() {
|
||||
fv.link(&typ);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ impl Context {
|
|||
/// occur(X -> ?T, ?T) ==> Error
|
||||
/// occur(?T, ?T -> X) ==> Error
|
||||
/// occur(?T, Option(?T)) ==> Error
|
||||
/// occur(?T, ?T.Output) ==> Error
|
||||
/// occur(?T, ?T.Output) ==> OK
|
||||
pub(crate) fn occur(
|
||||
&self,
|
||||
maybe_sub: &Type,
|
||||
|
@ -127,30 +127,6 @@ impl Context {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
(Type::Proj { lhs, .. }, rhs) => self.occur(lhs, rhs, loc),
|
||||
(Type::ProjCall { lhs, args, .. }, rhs) => {
|
||||
if let TyParam::Type(t) = lhs.as_ref() {
|
||||
self.occur(t, rhs, loc)?;
|
||||
}
|
||||
for arg in args.iter() {
|
||||
if let TyParam::Type(t) = arg {
|
||||
self.occur(t, rhs, loc)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
(lhs, Type::Proj { lhs: rhs, .. }) => self.occur(lhs, rhs, loc),
|
||||
(lhs, Type::ProjCall { lhs: rhs, args, .. }) => {
|
||||
if let TyParam::Type(t) = rhs.as_ref() {
|
||||
self.occur(lhs, t, loc)?;
|
||||
}
|
||||
for arg in args.iter() {
|
||||
if let TyParam::Type(t) = arg {
|
||||
self.occur(lhs, t, loc)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
(lhs, Type::Or(l, r)) | (lhs, Type::And(l, r)) => {
|
||||
self.occur(lhs, l, loc)?;
|
||||
self.occur(lhs, r, loc)
|
||||
|
@ -759,7 +735,6 @@ impl Context {
|
|||
if sup.is_structural() {
|
||||
return Ok(());
|
||||
}
|
||||
// REVIEW: correct?
|
||||
if let Some(new_sup) = self.min(&sup, maybe_sup) {
|
||||
let constr =
|
||||
Constraint::new_sandwiched(mem::take(&mut sub), new_sup.clone());
|
||||
|
@ -781,7 +756,6 @@ impl Context {
|
|||
}
|
||||
Ok(())
|
||||
}
|
||||
(Type::FreeVar(_fv), _r) => todo!(),
|
||||
(Type::Record(lrec), Type::Record(rrec)) => {
|
||||
for (k, l) in lrec.iter() {
|
||||
if let Some(r) = rrec.get(k) {
|
||||
|
@ -992,8 +966,18 @@ impl Context {
|
|||
self.sub_unify(l, r, loc, param_name)
|
||||
}
|
||||
(_, Type::RefMut { before, .. }) => self.sub_unify(maybe_sub, before, loc, param_name),
|
||||
(Type::Proj { .. }, _) => todo!(),
|
||||
(_, Type::Proj { .. }) => todo!(),
|
||||
(_, Type::Proj { lhs, rhs }) => {
|
||||
if let Ok(evaled) = self.eval_proj(*lhs.clone(), rhs.clone(), self.level, loc) {
|
||||
self.sub_unify(maybe_sub, &evaled, loc, param_name)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
(Type::Proj { lhs, rhs }, _) => {
|
||||
if let Ok(evaled) = self.eval_proj(*lhs.clone(), rhs.clone(), self.level, loc) {
|
||||
self.sub_unify(&evaled, maybe_sup, loc, param_name)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
// TODO: Judgment for any number of preds
|
||||
(Refinement(sub), Refinement(sup)) => {
|
||||
// {I: Int or Str | I == 0} <: {I: Int}
|
||||
|
|
|
@ -1934,12 +1934,10 @@ impl ASTLowerer {
|
|||
&self,
|
||||
impl_trait: &Type,
|
||||
class: &Type,
|
||||
typ_ctx: (&Type, &Context),
|
||||
(trait_type, trait_ctx): (&Type, &Context),
|
||||
t_spec: &TypeSpecWithOp,
|
||||
) -> (Set<&VarName>, CompileErrors) {
|
||||
let mut errors = CompileErrors::empty();
|
||||
let trait_type = typ_ctx.0;
|
||||
let trait_ctx = typ_ctx.1;
|
||||
let mut unverified_names = self.module.context.locals.keys().collect::<Set<_>>();
|
||||
for (decl_name, decl_vi) in trait_ctx.decls.iter() {
|
||||
if let Some((name, vi)) = self.module.context.get_var_kv(decl_name.inspect()) {
|
||||
|
|
|
@ -587,6 +587,25 @@ impl<T> Free<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Free<Type> {
|
||||
pub fn deep_clone(&self) -> Self {
|
||||
Self::new_named_unbound(
|
||||
self.unbound_name().unwrap(),
|
||||
self.level().unwrap(),
|
||||
self.constraint().unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
impl Free<TyParam> {
|
||||
pub fn deep_clone(&self) -> Self {
|
||||
Self::new_named_unbound(
|
||||
self.unbound_name().unwrap(),
|
||||
self.level().unwrap(),
|
||||
self.constraint().unwrap(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: StructuralEq + CanbeFree + Clone + Default> StructuralEq for Free<T> {
|
||||
fn structural_eq(&self, other: &Self) -> bool {
|
||||
if let (Some((l, r)), Some((l2, r2))) = (self.get_subsup(), other.get_subsup()) {
|
||||
|
|
|
@ -990,7 +990,7 @@ impl LimitedDisplay for Type {
|
|||
|
||||
impl CanbeFree for Type {
|
||||
fn unbound_name(&self) -> Option<Str> {
|
||||
if let Type::FreeVar(fv) = self {
|
||||
if let Some(fv) = self.as_free() {
|
||||
fv.unbound_name()
|
||||
} else {
|
||||
None
|
||||
|
@ -998,7 +998,7 @@ impl CanbeFree for Type {
|
|||
}
|
||||
|
||||
fn constraint(&self) -> Option<Constraint> {
|
||||
if let Type::FreeVar(fv) = self {
|
||||
if let Some(fv) = self.as_free() {
|
||||
fv.constraint()
|
||||
} else {
|
||||
None
|
||||
|
@ -1006,7 +1006,7 @@ impl CanbeFree for Type {
|
|||
}
|
||||
|
||||
fn update_constraint(&self, new_constraint: Constraint, in_instantiation: bool) {
|
||||
if let Self::FreeVar(fv) = self {
|
||||
if let Some(fv) = self.as_free() {
|
||||
fv.update_constraint(new_constraint, in_instantiation);
|
||||
}
|
||||
}
|
||||
|
@ -1048,6 +1048,17 @@ impl From<Dict<Type, Type>> for Type {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'t> TryFrom<&'t Type> for &'t FreeTyVar {
|
||||
type Error = ();
|
||||
fn try_from(t: &'t Type) -> Result<&'t FreeTyVar, ()> {
|
||||
match t {
|
||||
Type::FreeVar(fv) => Ok(fv),
|
||||
Type::Refinement(refine) => Self::try_from(refine.t.as_ref()),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dict<Field, Type>> for Type {
|
||||
fn from(rec: Dict<Field, Type>) -> Self {
|
||||
Type::Record(rec)
|
||||
|
@ -1582,6 +1593,10 @@ impl Type {
|
|||
matches!(self, Self::Structural(_))
|
||||
}
|
||||
|
||||
pub fn as_free(&self) -> Option<&FreeTyVar> {
|
||||
<&FreeTyVar>::try_from(self).ok()
|
||||
}
|
||||
|
||||
pub fn contains_tvar(&self, target: &FreeTyVar) -> bool {
|
||||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains_tvar(target),
|
||||
|
@ -2331,6 +2346,7 @@ impl Type {
|
|||
match self {
|
||||
Self::FreeVar(fv) if fv.is_linked() => fv.crack().clone()._replace(target, to),
|
||||
Self::FreeVar(fv) => {
|
||||
let fv = fv.deep_clone();
|
||||
if let Some((sub, sup)) = fv.get_subsup() {
|
||||
fv.forced_undoable_link(&sub);
|
||||
let sub = sub._replace(target, to);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue