fix: record type subtyping

This commit is contained in:
Shunsuke Shibayama 2023-08-19 23:20:35 +09:00
parent 95595ef67c
commit 6ce41ef8bd
5 changed files with 19 additions and 3 deletions

View file

@ -527,6 +527,7 @@ impl Context {
}
(Bool, Guard { .. }) => true,
(Mono(n), NamedTuple(_)) => &n[..] == "GenericNamedTuple" || &n[..] == "GenericTuple",
(Mono(n), Record(_)) => &n[..] == "Record",
(Type, Subr(subr)) => self.supertype_of(&Type, &subr.return_t),
(Type, Poly { name, params }) if &name[..] == "Array" || &name[..] == "Set" => {
let elem_t = self.convert_tp_into_type(params[0].clone()).unwrap();

View file

@ -1695,6 +1695,14 @@ impl Context {
/* record */
let mut record = Self::builtin_mono_class(RECORD, 2);
record.register_superclass(Obj, &obj);
let mut record_eq = Self::builtin_methods(Some(mono(EQ)), 2);
record_eq.register_builtin_erg_impl(
OP_EQ,
fn1_met(mono(RECORD), mono(RECORD), Bool),
Const,
Visibility::BUILTIN_PUBLIC,
);
record.register_trait(mono(RECORD), record_eq);
/* GenericNamedTuple */
let mut generic_named_tuple = Self::builtin_mono_class(GENERIC_NAMED_TUPLE, 2);
generic_named_tuple.register_superclass(mono(GENERIC_TUPLE), &generic_tuple);

View file

@ -550,15 +550,14 @@ impl Context {
return Ok(t);
}
}
if let Some(decl_t) = opt_decl_t {
return Ok(decl_t.typ().clone());
}
if let Some((typ, _)) = self.get_type(ident.inspect()) {
Ok(typ.clone())
} else if not_found_is_qvar {
let tyvar = named_free_var(Str::rc(other), self.level, Constraint::Uninited);
tmp_tv_cache.push_or_init_tyvar(&ident.name, &tyvar, self);
Ok(tyvar)
} else if let Some(decl_t) = opt_decl_t {
Ok(decl_t.typ().clone())
} else {
Err(TyCheckErrors::from(TyCheckError::no_type_error(
self.cfg.input.clone(),
@ -1375,6 +1374,7 @@ impl Context {
}
}
// FIXME: opt_decl_t must be disassembled for each polymorphic type
pub(crate) fn instantiate_typespec_full(
&self,
t_spec: &TypeSpec,

View file

@ -19,6 +19,7 @@ from _erg_set import Set
from _erg_contains_operator import contains_operator
from _erg_mutate_operator import mutate_operator
Record = tuple
class Never:
pass

View file

@ -7,3 +7,9 @@ higher2(f: ((g: Nat -> Nat) -> Nat)): Nat = f((x: Nat) -> x + 1)
f(g: Bool -> Nat): Nat = g(False)
print! higher2 f # OK
str_to_int_or_rec(_: {Str: Int or Record}) = None
str_to_int_or_rec { "a": 1 }
str_to_int_or_rec { "a": {.a = 1} }
str_to_int_or_rec { "a": {.a = 1}, "b": 1 }