mirror of
https://github.com/erg-lang/erg.git
synced 2025-07-07 13:15:21 +00:00
fix: sub-unification bug of self
This commit is contained in:
parent
29d270c0b3
commit
1a2924512b
5 changed files with 54 additions and 6 deletions
|
@ -859,7 +859,8 @@ impl Context {
|
|||
return Triple::Err(errs);
|
||||
}
|
||||
drop(list);
|
||||
let res = self.sub_unify(obj.ref_t(), self_t, obj, Some(&"self".into()));
|
||||
let res =
|
||||
self.self_unify(obj.ref_t(), self_t, &vi.t, obj, Some(&"self".into()));
|
||||
if DEBUG_MODE {
|
||||
res.unwrap();
|
||||
}
|
||||
|
@ -2150,7 +2151,13 @@ impl Context {
|
|||
let non_default_params = if is_method_call {
|
||||
let mut non_default_params = subr.non_default_params.iter();
|
||||
let self_pt = non_default_params.next().unwrap();
|
||||
if let Err(mut es) = self.sub_unify(obj.ref_t(), self_pt.typ(), obj, self_pt.name()) {
|
||||
if let Err(mut es) = self.self_unify(
|
||||
obj.ref_t(),
|
||||
self_pt.typ(),
|
||||
&Type::Subr(subr.clone()),
|
||||
obj,
|
||||
self_pt.name(),
|
||||
) {
|
||||
errs.append(&mut es);
|
||||
}
|
||||
passed_params.insert("self".into());
|
||||
|
|
|
@ -1037,7 +1037,13 @@ impl Context {
|
|||
let mut tmp_tv_cache = TyVarCache::new(self.level, self);
|
||||
let ty = self.instantiate_t_inner(*quant, &mut tmp_tv_cache, callee)?;
|
||||
if let Some(self_t) = ty.self_t() {
|
||||
self.sub_unify(callee.ref_t(), self_t, callee, Some(&Str::ever("self")))?;
|
||||
self.self_unify(
|
||||
callee.ref_t(),
|
||||
self_t,
|
||||
&ty,
|
||||
callee,
|
||||
Some(&Str::ever("self")),
|
||||
)?;
|
||||
}
|
||||
if DEBUG_MODE && ty.has_qvar() {
|
||||
panic!("{ty} has qvar")
|
||||
|
@ -1050,9 +1056,10 @@ impl Context {
|
|||
match &t {
|
||||
Type::Subr(subr) => {
|
||||
if let Some(self_t) = subr.self_t() {
|
||||
self.sub_unify(
|
||||
self.self_unify(
|
||||
callee.ref_t(),
|
||||
self_t,
|
||||
&t,
|
||||
callee,
|
||||
Some(&Str::ever("self")),
|
||||
)?;
|
||||
|
@ -1061,9 +1068,10 @@ impl Context {
|
|||
Type::And(tys, _) => {
|
||||
for ty in tys {
|
||||
if let Some(self_t) = ty.self_t() {
|
||||
self.sub_unify(
|
||||
self.self_unify(
|
||||
callee.ref_t(),
|
||||
self_t,
|
||||
ty,
|
||||
callee,
|
||||
Some(&Str::ever("self")),
|
||||
)?;
|
||||
|
|
|
@ -2267,6 +2267,33 @@ impl Context {
|
|||
unifier.sub_unify(maybe_sub, maybe_super)
|
||||
}
|
||||
|
||||
pub(crate) fn self_unify(
|
||||
&self,
|
||||
sub_self: &Type,
|
||||
super_self: &Type,
|
||||
subr: &Type,
|
||||
loc: &impl Locational,
|
||||
param_name: Option<&Str>,
|
||||
) -> TyCheckResult<()> {
|
||||
let unifier = Unifier::new(self, loc, None, false, param_name.cloned());
|
||||
unifier.sub_unify(sub_self, super_self)?;
|
||||
let super_self = match super_self {
|
||||
Type::Ref(inner) => inner,
|
||||
Type::RefMut { before, .. } => before,
|
||||
_ => super_self,
|
||||
};
|
||||
let sub_self = sub_self.derefine();
|
||||
if self.subtype_of(super_self, &sub_self) {
|
||||
if let Some(return_t) = subr.return_t() {
|
||||
if return_t.has_no_unbound_var() && !return_t.contains_type(&sub_self) {
|
||||
// callee.ref_t() == self_t
|
||||
let _ = unifier.sub_unify(super_self, &sub_self);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn sub_unify_with_coercion(
|
||||
&self,
|
||||
maybe_sub: &Type,
|
||||
|
|
|
@ -14,3 +14,9 @@ i_s.push! None # ERR
|
|||
|
||||
_: List!(Int, _) = !["a"] # ERR
|
||||
_: List!(Int, 1) = ![1, 2] # ERR
|
||||
|
||||
C! = Class(List!(List!(Int)))
|
||||
C!.
|
||||
append! ref! self =
|
||||
self::base.insert! 0, !["a"] # ERR
|
||||
self::base.insert! 0, [1] # ERR
|
||||
|
|
|
@ -766,7 +766,7 @@ fn exec_mut_err() -> Result<(), ()> {
|
|||
|
||||
#[test]
|
||||
fn exec_mut_list_err() -> Result<(), ()> {
|
||||
expect_compile_failure("tests/should_err/mut_list.er", 0, 5)
|
||||
expect_compile_failure("tests/should_err/mut_list.er", 0, 7)
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue