mirror of
https://github.com/erg-lang/erg.git
synced 2025-07-07 21:25:31 +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);
|
return Triple::Err(errs);
|
||||||
}
|
}
|
||||||
drop(list);
|
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 {
|
if DEBUG_MODE {
|
||||||
res.unwrap();
|
res.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -2150,7 +2151,13 @@ impl Context {
|
||||||
let non_default_params = if is_method_call {
|
let non_default_params = if is_method_call {
|
||||||
let mut non_default_params = subr.non_default_params.iter();
|
let mut non_default_params = subr.non_default_params.iter();
|
||||||
let self_pt = non_default_params.next().unwrap();
|
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);
|
errs.append(&mut es);
|
||||||
}
|
}
|
||||||
passed_params.insert("self".into());
|
passed_params.insert("self".into());
|
||||||
|
|
|
@ -1037,7 +1037,13 @@ impl Context {
|
||||||
let mut tmp_tv_cache = TyVarCache::new(self.level, self);
|
let mut tmp_tv_cache = TyVarCache::new(self.level, self);
|
||||||
let ty = self.instantiate_t_inner(*quant, &mut tmp_tv_cache, callee)?;
|
let ty = self.instantiate_t_inner(*quant, &mut tmp_tv_cache, callee)?;
|
||||||
if let Some(self_t) = ty.self_t() {
|
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() {
|
if DEBUG_MODE && ty.has_qvar() {
|
||||||
panic!("{ty} has qvar")
|
panic!("{ty} has qvar")
|
||||||
|
@ -1050,9 +1056,10 @@ impl Context {
|
||||||
match &t {
|
match &t {
|
||||||
Type::Subr(subr) => {
|
Type::Subr(subr) => {
|
||||||
if let Some(self_t) = subr.self_t() {
|
if let Some(self_t) = subr.self_t() {
|
||||||
self.sub_unify(
|
self.self_unify(
|
||||||
callee.ref_t(),
|
callee.ref_t(),
|
||||||
self_t,
|
self_t,
|
||||||
|
&t,
|
||||||
callee,
|
callee,
|
||||||
Some(&Str::ever("self")),
|
Some(&Str::ever("self")),
|
||||||
)?;
|
)?;
|
||||||
|
@ -1061,9 +1068,10 @@ impl Context {
|
||||||
Type::And(tys, _) => {
|
Type::And(tys, _) => {
|
||||||
for ty in tys {
|
for ty in tys {
|
||||||
if let Some(self_t) = ty.self_t() {
|
if let Some(self_t) = ty.self_t() {
|
||||||
self.sub_unify(
|
self.self_unify(
|
||||||
callee.ref_t(),
|
callee.ref_t(),
|
||||||
self_t,
|
self_t,
|
||||||
|
ty,
|
||||||
callee,
|
callee,
|
||||||
Some(&Str::ever("self")),
|
Some(&Str::ever("self")),
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -2267,6 +2267,33 @@ impl Context {
|
||||||
unifier.sub_unify(maybe_sub, maybe_super)
|
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(
|
pub(crate) fn sub_unify_with_coercion(
|
||||||
&self,
|
&self,
|
||||||
maybe_sub: &Type,
|
maybe_sub: &Type,
|
||||||
|
|
|
@ -14,3 +14,9 @@ i_s.push! None # ERR
|
||||||
|
|
||||||
_: List!(Int, _) = !["a"] # ERR
|
_: List!(Int, _) = !["a"] # ERR
|
||||||
_: List!(Int, 1) = ![1, 2] # 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]
|
#[test]
|
||||||
fn exec_mut_list_err() -> Result<(), ()> {
|
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]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue