Merge branch 'main' into fix-type-matching

This commit is contained in:
Shunsuke Shibayama 2023-02-13 02:31:37 +09:00
commit 2ad38717cd
23 changed files with 241 additions and 276 deletions

View file

@ -113,9 +113,7 @@ impl Context {
let constr = fv.constraint().unwrap();
if let Some((l, r)) = constr.get_sub_sup() {
// |Int <: T <: Int| T -> T ==> Int -> Int
if l == r
/*self.same_type_of(l, r)*/
{
if l == r {
fv.forced_link(l);
FreeVar(fv)
} else if r != &Obj && self.is_class(r) && variance == Contravariant {

View file

@ -285,7 +285,7 @@ impl Context {
mode,
ParamKind::NonDefault,
) {
Ok(t) => non_defaults.push(t),
Ok(pt) => non_defaults.push(pt),
Err(es) => {
errs.extend(es);
non_defaults.push(ParamTy::pos(param.inspect().cloned(), Type::Failure));
@ -325,7 +325,7 @@ impl Context {
mode,
ParamKind::Default(default_t),
) {
Ok(t) => defaults.push(t),
Ok(pt) => defaults.push(pt),
Err(es) => {
errs.extend(es);
defaults.push(ParamTy::pos(p.sig.inspect().cloned(), Type::Failure));
@ -379,28 +379,25 @@ impl Context {
mode: RegistrationMode,
kind: ParamKind,
) -> TyCheckResult<Type> {
let spec_t = if let Some(t_spec_with_op) = &sig.t_spec {
self.instantiate_typespec(
&t_spec_with_op.t_spec,
opt_decl_t,
tmp_tv_cache,
mode,
false,
)?
let gen_free_t = || {
let level = if mode == PreRegister {
self.level
} else {
self.level + 1
};
free_var(level, Constraint::new_type_of(Type))
};
let spec_t = if let Some(spec_with_op) = &sig.t_spec {
self.instantiate_typespec(&spec_with_op.t_spec, opt_decl_t, tmp_tv_cache, mode, false)?
} else {
match &sig.pat {
ast::ParamPattern::Lit(lit) => v_enum(set![self.eval_lit(lit)?]),
ast::ParamPattern::Discard(_) => Type::Obj,
ast::ParamPattern::Ref(_) => ref_(gen_free_t()),
ast::ParamPattern::RefMut(_) => ref_mut(gen_free_t(), None),
// ast::ParamPattern::VarName(name) if &name.inspect()[..] == "_" => Type::Obj,
// TODO: Array<Lit>
_ => {
let level = if mode == PreRegister {
self.level
} else {
self.level + 1
};
free_var(level, Constraint::new_type_of(Type))
}
_ => gen_free_t(),
}
};
if let Some(decl_pt) = opt_decl_t {

View file

@ -363,12 +363,16 @@ impl Context {
)?;
if &name.inspect()[..] == "self" {
if let Some(self_t) = self.rec_get_self_t() {
self.sub_unify(&spec_t, &self_t, name.loc(), Some(name.inspect()))?;
self.sub_unify(
&spec_t,
&ref_(self_t),
name.loc(),
Some(name.inspect()),
)?;
} else {
log!(err "self_t is None");
}
}
let spec_t = ref_(spec_t);
let kind = VarKind::parameter(DefId(get_hash(&(&self.name, name))), default);
let vi = VarInfo::new(
spec_t,
@ -409,12 +413,16 @@ impl Context {
)?;
if &name.inspect()[..] == "self" {
if let Some(self_t) = self.rec_get_self_t() {
self.sub_unify(&spec_t, &self_t, name.loc(), Some(name.inspect()))?;
self.sub_unify(
&spec_t,
&ref_mut(self_t, None),
name.loc(),
Some(name.inspect()),
)?;
} else {
log!(err "self_t is None");
}
}
let spec_t = ref_mut(spec_t.clone(), Some(spec_t));
let kind = VarKind::parameter(DefId(get_hash(&(&self.name, name))), default);
let vi = VarInfo::new(
spec_t,

View file

@ -548,6 +548,12 @@ impl Context {
return Ok(());
}
match (maybe_sub, maybe_sup) {
(Type::FreeVar(lfv), _) if lfv.is_linked() => {
self.sub_unify(&lfv.crack(), maybe_sup, loc, param_name)
}
(_, Type::FreeVar(rfv)) if rfv.is_linked() => {
self.sub_unify(maybe_sub, &rfv.crack(), loc, param_name)
}
// lfv's sup can be shrunk (take min), rfv's sub can be expanded (take union)
// lfvのsupは縮小可能(minを取る)、rfvのsubは拡大可能(unionを取る)
// sub_unify(?T[0](:> Never, <: Int), ?U[1](:> Never, <: Nat)): (/* ?U[1] --> ?T[0](:> Never, <: Nat))
@ -605,12 +611,6 @@ impl Context {
}
Ok(())
}
(Type::FreeVar(lfv), _) if lfv.is_linked() => {
self.sub_unify(&lfv.crack(), maybe_sup, loc, param_name)
}
(_, Type::FreeVar(rfv)) if rfv.is_linked() => {
self.sub_unify(maybe_sub, &rfv.crack(), loc, param_name)
}
(_, Type::FreeVar(rfv)) if rfv.is_unbound() => {
// NOTE: cannot `borrow_mut` because of cycle reference
let rfv_ref = unsafe { rfv.as_ptr().as_mut().unwrap() };
@ -849,7 +849,11 @@ impl Context {
(_, Type::Or(l, r)) => self
.sub_unify(maybe_sub, l, loc, param_name)
.or_else(|_e| self.sub_unify(maybe_sub, r, loc, param_name)),
(Type::Ref(l), Type::Ref(r)) => self.sub_unify(l, r, loc, param_name),
(_, Type::Ref(t)) => self.sub_unify(maybe_sub, t, loc, param_name),
(Type::RefMut { before: l, .. }, Type::RefMut { before: r, .. }) => {
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!(),