fix: sub-unification bugs

This commit is contained in:
Shunsuke Shibayama 2023-03-22 15:38:47 +09:00
parent b318395a32
commit 0079aed860
10 changed files with 190 additions and 153 deletions

View file

@ -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(); let (sub, sup) = fv.get_subsup().unwrap();
if self.is_trait(&sup) && !self.trait_impl_exists(&sub, &sup) { if self.is_trait(&sup) && !self.trait_impl_exists(&sub, &sup) {
// link to `Never` to prevent double errors from being reported // link to `Never` to prevent double errors from being reported

View file

@ -23,70 +23,69 @@ use Variance::*;
impl Context { impl Context {
pub const TOP_LEVEL: usize = 1; 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 { 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_generalized() => TyParam::FreeVar(fv),
TyParam::FreeVar(fv) if fv.is_linked() => { TyParam::FreeVar(fv) if fv.is_linked() => {
self.generalize_tp(fv.crack().clone(), variance, uninit) self.generalize_tp(fv.crack().clone(), variance, qnames, 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)*/
} }
// TODO: Polymorphic generalization // TODO: Polymorphic generalization
TyParam::FreeVar(fv) if fv.level() > Some(self.level) => { 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.update_constraint(constr, true);
fv.generalize(); fv.generalize();
TyParam::FreeVar(fv) TyParam::FreeVar(fv)
} }
TyParam::Array(tps) => TyParam::Array( TyParam::Array(tps) => TyParam::Array(
tps.into_iter() tps.into_iter()
.map(|tp| self.generalize_tp(tp, variance, uninit)) .map(|tp| self.generalize_tp(tp, variance, qnames, uninit))
.collect(), .collect(),
), ),
TyParam::Tuple(tps) => TyParam::Tuple( TyParam::Tuple(tps) => TyParam::Tuple(
tps.into_iter() tps.into_iter()
.map(|tp| self.generalize_tp(tp, variance, uninit)) .map(|tp| self.generalize_tp(tp, variance, qnames, uninit))
.collect(), .collect(),
), ),
TyParam::Dict(tps) => TyParam::Dict( TyParam::Dict(tps) => TyParam::Dict(
tps.into_iter() tps.into_iter()
.map(|(k, v)| { .map(|(k, v)| {
( (
self.generalize_tp(k, variance, uninit), self.generalize_tp(k, variance, qnames, uninit),
self.generalize_tp(v, variance, uninit), self.generalize_tp(v, variance, qnames, uninit),
) )
}) })
.collect(), .collect(),
), ),
TyParam::Record(rec) => TyParam::Record( TyParam::Record(rec) => TyParam::Record(
rec.into_iter() 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(), .collect(),
), ),
TyParam::Lambda(lambda) => { TyParam::Lambda(lambda) => {
let nd_params = lambda let nd_params = lambda
.nd_params .nd_params
.into_iter() .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<_>>(); .collect::<Vec<_>>();
let var_params = lambda let var_params = lambda.var_params.map(|pt| {
.var_params pt.map_type(|t| self.generalize_t_inner(t, variance, qnames, uninit))
.map(|pt| pt.map_type(|t| self.generalize_t_inner(t, variance, uninit))); });
let d_params = lambda let d_params = lambda
.d_params .d_params
.into_iter() .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<_>>(); .collect::<Vec<_>>();
let body = lambda let body = lambda
.body .body
.into_iter() .into_iter()
.map(|tp| self.generalize_tp(tp, variance, uninit)) .map(|tp| self.generalize_tp(tp, variance, qnames, uninit))
.collect(); .collect();
TyParam::Lambda(TyParamLambda::new( TyParam::Lambda(TyParamLambda::new(
lambda.const_, lambda.const_,
@ -98,24 +97,26 @@ impl Context {
} }
TyParam::FreeVar(_) => free, TyParam::FreeVar(_) => free,
TyParam::Proj { obj, attr } => { 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::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 } => { TyParam::App { name, args } => {
let args = args let args = args
.into_iter() .into_iter()
.map(|tp| self.generalize_tp(tp, variance, uninit)) .map(|tp| self.generalize_tp(tp, variance, qnames, uninit))
.collect(); .collect();
TyParam::App { name, args } TyParam::App { name, args }
} }
TyParam::BinOp { op, lhs, rhs } => { TyParam::BinOp { op, lhs, rhs } => {
let lhs = self.generalize_tp(*lhs, variance, uninit); let lhs = self.generalize_tp(*lhs, variance, qnames, uninit);
let rhs = self.generalize_tp(*rhs, variance, uninit); let rhs = self.generalize_tp(*rhs, variance, qnames, uninit);
TyParam::bin(op, lhs, rhs) TyParam::bin(op, lhs, rhs)
} }
TyParam::UnaryOp { op, val } => { 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) TyParam::unary(op, val)
} }
other if other.has_no_unbound_var() => other, other if other.has_no_unbound_var() => other,
@ -126,7 +127,7 @@ impl Context {
/// Quantification occurs only once in function types. /// 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. /// 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 { 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() { if maybe_unbound_t.is_subr() && maybe_unbound_t.has_qvar() {
maybe_unbound_t.quantify() maybe_unbound_t.quantify()
} else { } else {
@ -141,56 +142,64 @@ impl Context {
/// generalize_t(?T(<: Add(?T(<: Eq(?T(<: ...)))) -> ?T) == |'T <: Add('T)| 'T -> 'T /// generalize_t(?T(<: Add(?T(<: Eq(?T(<: ...)))) -> ?T) == |'T <: Add('T)| 'T -> 'T
/// generalize_t(?T(<: TraitX) -> Int) == TraitX -> Int // 戻り値に現れないなら量化しない /// 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 { match free_type {
FreeVar(fv) if fv.is_linked() => { FreeVar(fv) if fv.is_linked() => {
self.generalize_t_inner(fv.crack().clone(), variance, uninit) self.generalize_t_inner(fv.crack().clone(), variance, qnames, 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)*/
} }
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 => {
if uninit { if uninit {
// use crate::ty::free::GENERIC_LEVEL;
// return named_free_var(fv.unbound_name().unwrap(), GENERIC_LEVEL, Constraint::Uninited);
fv.generalize(); fv.generalize();
return Type::FreeVar(fv); 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 // |Int <: T <: Int| T -> T ==> Int -> Int
if l == r { if sub == sup {
let t = self.generalize_t_inner(l, variance, uninit); let t = self.generalize_t_inner(sub, variance, qnames, uninit);
fv.forced_link(&t); fv.forced_link(&t);
FreeVar(fv) 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 // |T <: Bool| T -> Int ==> Bool -> Int
self.generalize_t_inner(r, variance, uninit) self.generalize_t_inner(sup, variance, qnames, uninit)
} else if l != Never && self.is_class(&l) && variance == Covariant { } else if sub != Never
&& !qnames.contains(&fv.unbound_name().unwrap())
&& variance == Covariant
{
// |T :> Int| X -> T ==> X -> Int // |T :> Int| X -> T ==> X -> Int
self.generalize_t_inner(l, variance, uninit) self.generalize_t_inner(sub, variance, qnames, uninit)
} else { } else {
fv.update_constraint(self.generalize_constraint(&fv, variance), true); fv.update_constraint(
self.generalize_constraint(&fv, qnames, variance),
true,
);
fv.generalize(); fv.generalize();
Type::FreeVar(fv) Type::FreeVar(fv)
} }
} else { } else {
// ?S(: Str) => 'S // ?S(: Str) => 'S
fv.update_constraint(self.generalize_constraint(&fv, variance), true); fv.update_constraint(self.generalize_constraint(&fv, qnames, variance), true);
fv.generalize(); fv.generalize();
Type::FreeVar(fv) Type::FreeVar(fv)
} }
} }
Subr(mut subr) => { Subr(mut subr) => {
let qnames = subr.essential_qnames();
subr.non_default_params.iter_mut().for_each(|nd_param| { subr.non_default_params.iter_mut().for_each(|nd_param| {
*nd_param.typ_mut() = self.generalize_t_inner( *nd_param.typ_mut() = self.generalize_t_inner(
mem::take(nd_param.typ_mut()), mem::take(nd_param.typ_mut()),
Contravariant, Contravariant,
&qnames,
uninit, uninit,
); );
}); });
@ -198,6 +207,7 @@ impl Context {
*var_args.typ_mut() = self.generalize_t_inner( *var_args.typ_mut() = self.generalize_t_inner(
mem::take(var_args.typ_mut()), mem::take(var_args.typ_mut()),
Contravariant, Contravariant,
&qnames,
uninit, uninit,
); );
} }
@ -205,10 +215,11 @@ impl Context {
*d_param.typ_mut() = self.generalize_t_inner( *d_param.typ_mut() = self.generalize_t_inner(
mem::take(d_param.typ_mut()), mem::take(d_param.typ_mut()),
Contravariant, Contravariant,
&qnames,
uninit, 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_t(
subr.kind, subr.kind,
subr.non_default_params, subr.non_default_params,
@ -220,30 +231,34 @@ impl Context {
Record(rec) => { Record(rec) => {
let fields = rec let fields = rec
.into_iter() .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(); .collect();
Type::Record(fields) Type::Record(fields)
} }
Callable { .. } => todo!(), 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 } => { RefMut { before, after } => {
let after = after.map(|aft| self.generalize_t_inner(*aft, variance, uninit)); let after =
ref_mut(self.generalize_t_inner(*before, variance, uninit), 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) => { Refinement(refine) => {
let t = self.generalize_t_inner(*refine.t, variance, uninit); let t = self.generalize_t_inner(*refine.t, variance, qnames, uninit);
let pred = self.generalize_pred(*refine.pred, variance, uninit); let pred = self.generalize_pred(*refine.pred, variance, qnames, uninit);
refinement(refine.var, t, pred) refinement(refine.var, t, pred)
} }
Poly { name, mut params } => { Poly { name, mut params } => {
let params = params let params = params
.iter_mut() .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<_>>(); .collect::<Vec<_>>();
poly(name, params) poly(name, params)
} }
Proj { lhs, rhs } => { 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) proj(lhs, rhs)
} }
ProjCall { ProjCall {
@ -251,83 +266,94 @@ impl Context {
attr_name, attr_name,
mut args, 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() { 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) proj_call(lhs, attr_name, args)
} }
And(l, r) => { And(l, r) => {
let l = self.generalize_t_inner(*l, variance, uninit); let l = self.generalize_t_inner(*l, variance, qnames, uninit);
let r = self.generalize_t_inner(*r, variance, uninit); let r = self.generalize_t_inner(*r, variance, qnames, uninit);
// not `self.intersection` because types are generalized // not `self.intersection` because types are generalized
and(l, r) and(l, r)
} }
Or(l, r) => { Or(l, r) => {
let l = self.generalize_t_inner(*l, variance, uninit); let l = self.generalize_t_inner(*l, variance, qnames, uninit);
let r = self.generalize_t_inner(*r, variance, uninit); let r = self.generalize_t_inner(*r, variance, qnames, uninit);
// not `self.union` because types are generalized // not `self.union` because types are generalized
or(l, r) 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 Structural(t) => self
.generalize_t_inner(*t, variance, uninit) .generalize_t_inner(*t, variance, qnames, uninit)
.structuralize(), .structuralize(),
// REVIEW: その他何でもそのまま通していいのか? // REVIEW: その他何でもそのまま通していいのか?
other => other, 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() { if let Some((sub, sup)) = fv.get_subsup() {
let sub = self.generalize_t_inner(sub, variance, true); let sub = self.generalize_t_inner(sub, variance, qnames, true);
let sup = self.generalize_t_inner(sup, variance, true); let sup = self.generalize_t_inner(sup, variance, qnames, true);
Constraint::new_sandwiched(sub, sup) Constraint::new_sandwiched(sub, sup)
} else if let Some(ty) = fv.get_type() { } 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) Constraint::new_type_of(t)
} else { } else {
unreachable!() 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 { match pred {
Predicate::Const(_) => pred, Predicate::Const(_) => pred,
Predicate::Value(ValueObj::Type(mut typ)) => { Predicate::Value(ValueObj::Type(mut typ)) => {
*typ.typ_mut() = *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(ValueObj::Type(typ))
} }
Predicate::Value(_) => pred, Predicate::Value(_) => pred,
Predicate::Equal { lhs, rhs } => { 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::eq(lhs, rhs)
} }
Predicate::GreaterEqual { 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::ge(lhs, rhs)
} }
Predicate::LessEqual { 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::le(lhs, rhs)
} }
Predicate::NotEqual { 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::ne(lhs, rhs)
} }
Predicate::And(lhs, rhs) => { Predicate::And(lhs, rhs) => {
let lhs = self.generalize_pred(*lhs, variance, uninit); let lhs = self.generalize_pred(*lhs, variance, qnames, uninit);
let rhs = self.generalize_pred(*rhs, variance, uninit); let rhs = self.generalize_pred(*rhs, variance, qnames, uninit);
Predicate::and(lhs, rhs) Predicate::and(lhs, rhs)
} }
Predicate::Or(lhs, rhs) => { Predicate::Or(lhs, rhs) => {
let lhs = self.generalize_pred(*lhs, variance, uninit); let lhs = self.generalize_pred(*lhs, variance, qnames, uninit);
let rhs = self.generalize_pred(*rhs, variance, uninit); let rhs = self.generalize_pred(*rhs, variance, qnames, uninit);
Predicate::or(lhs, rhs) Predicate::or(lhs, rhs)
} }
Predicate::Not(pred) => { Predicate::Not(pred) => {
let pred = self.generalize_pred(*pred, variance, uninit); let pred = self.generalize_pred(*pred, variance, qnames, uninit);
!pred !pred
} }
} }

View file

@ -72,7 +72,7 @@ impl Context {
expected: &Type, expected: &Type,
found: &Type, found: &Type,
) -> Option<String> { ) -> Option<String> {
let expected = if let Type::FreeVar(fv) = expected { let expected = if let Some(fv) = expected.as_free() {
if fv.is_linked() { if fv.is_linked() {
fv.crack().clone() fv.crack().clone()
} else { } else {
@ -191,7 +191,7 @@ impl Context {
pub(crate) fn get_no_candidate_hint(&self, proj: &Type) -> Option<String> { pub(crate) fn get_no_candidate_hint(&self, proj: &Type) -> Option<String> {
match proj { match proj {
Type::Proj { lhs, rhs: _ } => { 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 (sub, sup) = fv.get_subsup()?;
let (verb, preposition, sequence) = Self::get_verb_and_preposition(&sup)?; let (verb, preposition, sequence) = Self::get_verb_and_preposition(&sup)?;
let sup = *option_enum_unwrap!(sup.typarams().get(0)?.clone(), TyParam::Type)?; let sup = *option_enum_unwrap!(sup.typarams().get(0)?.clone(), TyParam::Type)?;

View file

@ -563,7 +563,7 @@ impl Context {
// => ?T(<: Structural({ .aaa = ?U })) // => ?T(<: Structural({ .aaa = ?U }))
if self.in_subr() && cfg!(feature = "py_compatible") { if self.in_subr() && cfg!(feature = "py_compatible") {
let t = free_var(self.level, Constraint::new_type_of(Type)); 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() { if fv.get_sub().is_some() {
let vis = self.instantiate_vis_modifier(&ident.vis).unwrap(); let vis = self.instantiate_vis_modifier(&ident.vis).unwrap();
let structural = Type::Record( let structural = Type::Record(
@ -910,7 +910,7 @@ impl Context {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let return_t = free_var(self.level, Constraint::new_type_of(Type)); 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); 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() { if fv.get_sub().is_some() {
let vis = self.instantiate_vis_modifier(&attr_name.vis).unwrap(); let vis = self.instantiate_vis_modifier(&attr_name.vis).unwrap();
let structural = Type::Record( let structural = Type::Record(

View file

@ -224,7 +224,7 @@ impl Context {
Ok(tp) Ok(tp)
} else if let Some(t) = tmp_tv_cache.get_tyvar(&name) { } else if let Some(t) = tmp_tv_cache.get_tyvar(&name) {
let t = t.clone(); let t = t.clone();
if let Type::FreeVar(fv) = &t { if let Some(fv) = t.as_free() {
if fv if fv
.constraint() .constraint()
.map(|cons| cons.is_uninited()) .map(|cons| cons.is_uninited())

View file

@ -307,6 +307,27 @@ impl Context {
Ok(vi) 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 /// TODO: sig should be immutable
/// 宣言が既にある場合、opt_decl_tに宣言の型を渡す /// 宣言が既にある場合、opt_decl_tに宣言の型を渡す
fn assign_param( fn assign_param(
@ -387,15 +408,7 @@ impl Context {
spec_t spec_t
}; };
if &name.inspect()[..] == "self" { if &name.inspect()[..] == "self" {
if let Some(self_t) = self.rec_get_self_t() { self.type_self_param(&sig.raw.pat, name, &spec_t, &mut errs);
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");
}
} }
let def_id = DefId(get_hash(&(&self.name, name))); let def_id = DefId(get_hash(&(&self.name, name)));
let kind = VarKind::parameter(def_id, is_var_params, default); let kind = VarKind::parameter(def_id, is_var_params, default);
@ -446,15 +459,7 @@ impl Context {
Err(errs) => (Type::Failure, errs), Err(errs) => (Type::Failure, errs),
}; };
if &name.inspect()[..] == "self" { if &name.inspect()[..] == "self" {
if let Some(self_t) = self.rec_get_self_t() { self.type_self_param(&sig.raw.pat, name, &spec_t, &mut errs);
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");
}
} }
let kind = VarKind::parameter( let kind = VarKind::parameter(
DefId(get_hash(&(&self.name, name))), DefId(get_hash(&(&self.name, name))),
@ -506,18 +511,7 @@ impl Context {
Err(errs) => (Type::Failure, errs), Err(errs) => (Type::Failure, errs),
}; };
if &name.inspect()[..] == "self" { if &name.inspect()[..] == "self" {
if let Some(self_t) = self.rec_get_self_t() { self.type_self_param(&sig.raw.pat, name, &spec_t, &mut errs);
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");
}
} }
let kind = VarKind::parameter( let kind = VarKind::parameter(
DefId(get_hash(&(&self.name, name))), DefId(get_hash(&(&self.name, name))),
@ -862,7 +856,7 @@ impl Context {
let Some((_, vi)) = self.get_var_info(ident.inspect()) else { let Some((_, vi)) = self.get_var_info(ident.inspect()) else {
return; return;
}; };
if let Type::FreeVar(fv) = &vi.t { if let Some(fv) = vi.t.as_free() {
fv.link(&typ); fv.link(&typ);
} }
} }

View file

@ -28,7 +28,7 @@ impl Context {
/// occur(X -> ?T, ?T) ==> Error /// occur(X -> ?T, ?T) ==> Error
/// occur(?T, ?T -> X) ==> Error /// occur(?T, ?T -> X) ==> Error
/// occur(?T, Option(?T)) ==> Error /// occur(?T, Option(?T)) ==> Error
/// occur(?T, ?T.Output) ==> Error /// occur(?T, ?T.Output) ==> OK
pub(crate) fn occur( pub(crate) fn occur(
&self, &self,
maybe_sub: &Type, maybe_sub: &Type,
@ -127,30 +127,6 @@ impl Context {
} }
Ok(()) 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)) => { (lhs, Type::Or(l, r)) | (lhs, Type::And(l, r)) => {
self.occur(lhs, l, loc)?; self.occur(lhs, l, loc)?;
self.occur(lhs, r, loc) self.occur(lhs, r, loc)
@ -759,7 +735,6 @@ impl Context {
if sup.is_structural() { if sup.is_structural() {
return Ok(()); return Ok(());
} }
// REVIEW: correct?
if let Some(new_sup) = self.min(&sup, maybe_sup) { if let Some(new_sup) = self.min(&sup, maybe_sup) {
let constr = let constr =
Constraint::new_sandwiched(mem::take(&mut sub), new_sup.clone()); Constraint::new_sandwiched(mem::take(&mut sub), new_sup.clone());
@ -781,7 +756,6 @@ impl Context {
} }
Ok(()) Ok(())
} }
(Type::FreeVar(_fv), _r) => todo!(),
(Type::Record(lrec), Type::Record(rrec)) => { (Type::Record(lrec), Type::Record(rrec)) => {
for (k, l) in lrec.iter() { for (k, l) in lrec.iter() {
if let Some(r) = rrec.get(k) { if let Some(r) = rrec.get(k) {
@ -992,8 +966,18 @@ impl Context {
self.sub_unify(l, r, loc, param_name) self.sub_unify(l, r, loc, param_name)
} }
(_, Type::RefMut { before, .. }) => self.sub_unify(maybe_sub, before, loc, param_name), (_, Type::RefMut { before, .. }) => self.sub_unify(maybe_sub, before, loc, param_name),
(Type::Proj { .. }, _) => todo!(), (_, Type::Proj { lhs, rhs }) => {
(_, Type::Proj { .. }) => todo!(), 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 // TODO: Judgment for any number of preds
(Refinement(sub), Refinement(sup)) => { (Refinement(sub), Refinement(sup)) => {
// {I: Int or Str | I == 0} <: {I: Int} // {I: Int or Str | I == 0} <: {I: Int}

View file

@ -1934,12 +1934,10 @@ impl ASTLowerer {
&self, &self,
impl_trait: &Type, impl_trait: &Type,
class: &Type, class: &Type,
typ_ctx: (&Type, &Context), (trait_type, trait_ctx): (&Type, &Context),
t_spec: &TypeSpecWithOp, t_spec: &TypeSpecWithOp,
) -> (Set<&VarName>, CompileErrors) { ) -> (Set<&VarName>, CompileErrors) {
let mut errors = CompileErrors::empty(); 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<_>>(); let mut unverified_names = self.module.context.locals.keys().collect::<Set<_>>();
for (decl_name, decl_vi) in trait_ctx.decls.iter() { for (decl_name, decl_vi) in trait_ctx.decls.iter() {
if let Some((name, vi)) = self.module.context.get_var_kv(decl_name.inspect()) { if let Some((name, vi)) = self.module.context.get_var_kv(decl_name.inspect()) {

View file

@ -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> { impl<T: StructuralEq + CanbeFree + Clone + Default> StructuralEq for Free<T> {
fn structural_eq(&self, other: &Self) -> bool { fn structural_eq(&self, other: &Self) -> bool {
if let (Some((l, r)), Some((l2, r2))) = (self.get_subsup(), other.get_subsup()) { if let (Some((l, r)), Some((l2, r2))) = (self.get_subsup(), other.get_subsup()) {

View file

@ -990,7 +990,7 @@ impl LimitedDisplay for Type {
impl CanbeFree for Type { impl CanbeFree for Type {
fn unbound_name(&self) -> Option<Str> { fn unbound_name(&self) -> Option<Str> {
if let Type::FreeVar(fv) = self { if let Some(fv) = self.as_free() {
fv.unbound_name() fv.unbound_name()
} else { } else {
None None
@ -998,7 +998,7 @@ impl CanbeFree for Type {
} }
fn constraint(&self) -> Option<Constraint> { fn constraint(&self) -> Option<Constraint> {
if let Type::FreeVar(fv) = self { if let Some(fv) = self.as_free() {
fv.constraint() fv.constraint()
} else { } else {
None None
@ -1006,7 +1006,7 @@ impl CanbeFree for Type {
} }
fn update_constraint(&self, new_constraint: Constraint, in_instantiation: bool) { 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); 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 { impl From<Dict<Field, Type>> for Type {
fn from(rec: Dict<Field, Type>) -> Self { fn from(rec: Dict<Field, Type>) -> Self {
Type::Record(rec) Type::Record(rec)
@ -1582,6 +1593,10 @@ impl Type {
matches!(self, Self::Structural(_)) matches!(self, Self::Structural(_))
} }
pub fn as_free(&self) -> Option<&FreeTyVar> {
<&FreeTyVar>::try_from(self).ok()
}
pub fn contains_tvar(&self, target: &FreeTyVar) -> bool { pub fn contains_tvar(&self, target: &FreeTyVar) -> bool {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains_tvar(target), Self::FreeVar(fv) if fv.is_linked() => fv.crack().contains_tvar(target),
@ -2331,6 +2346,7 @@ impl Type {
match self { match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().clone()._replace(target, to), Self::FreeVar(fv) if fv.is_linked() => fv.crack().clone()._replace(target, to),
Self::FreeVar(fv) => { Self::FreeVar(fv) => {
let fv = fv.deep_clone();
if let Some((sub, sup)) = fv.get_subsup() { if let Some((sub, sup)) = fv.get_subsup() {
fv.forced_undoable_link(&sub); fv.forced_undoable_link(&sub);
let sub = sub._replace(target, to); let sub = sub._replace(target, to);