fix(typechecker): type assignment bug for bound methods

This commit is contained in:
Shunsuke Shibayama 2023-02-11 16:00:15 +09:00
parent b452503105
commit 26046d90e5
5 changed files with 34 additions and 1 deletions

View file

@ -458,6 +458,10 @@ impl Context {
}
match self.get_attr_from_nominal_t(obj, ident, input, namespace) {
Ok(vi) => {
if let Some(self_t) = vi.t.self_t() {
self.sub_unify(obj.ref_t(), self_t, obj.loc(), Some(&"self".into()))
.map_err(|mut e| e.remove(0))?;
}
return Ok(vi);
}
Err(e) if e.core.kind == ErrorKind::AttributeError => {}

View file

@ -360,6 +360,10 @@ impl SubrType {
})
}
pub fn is_method(&self) -> bool {
self.self_t().is_some()
}
pub fn non_var_params(&self) -> impl Iterator<Item = &ParamTy> + Clone {
if self.var_params.is_some() {
self.non_default_params.iter().chain([].iter())
@ -1268,6 +1272,16 @@ impl Type {
}
}
pub fn is_method(&self) -> bool {
match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_method(),
Self::Refinement(refine) => refine.t.is_method(),
Self::Subr(subr) => subr.is_method(),
Self::Quantified(quant) => quant.is_method(),
_ => false,
}
}
pub fn is_quantified(&self) -> bool {
match self {
Self::FreeVar(fv) if fv.is_linked() => fv.crack().is_quantified(),

View file

@ -720,7 +720,11 @@ impl TyParam {
pub fn qvars(&self) -> Set<(Str, Constraint)> {
match self {
Self::FreeVar(fv) if !fv.constraint_is_uninited() => {
set! { (fv.unbound_name().unwrap(), fv.constraint().unwrap()) }
if let (Some(name), Some(constraint)) = (fv.unbound_name(), fv.constraint()) {
set! { (name, constraint) }
} else {
set! {}
}
}
Self::FreeVar(fv) if fv.is_linked() => fv.forced_as_ref().linked().unwrap().qvars(),
Self::Type(t) => t.qvars(),

6
tests/should_err/move.er Normal file
View file

@ -0,0 +1,6 @@
a = ![]
a.sort! # WARN
# NOTE: For safety reasons this is assumed to be an error, but maybe this restriction can be relaxed
print! a # ERR

View file

@ -249,3 +249,8 @@ fn exec_var_args() -> Result<(), ()> {
fn exec_var_args_err() -> Result<(), ()> {
expect_failure("tests/should_err/var_args.er", 2)
}
#[test]
fn exec_move() -> Result<(), ()> {
expect_failure("tests/should_err/move.er", 1)
}