diff --git a/crates/erg_compiler/context/inquire.rs b/crates/erg_compiler/context/inquire.rs index 6e1f93bf..163b6d43 100644 --- a/crates/erg_compiler/context/inquire.rs +++ b/crates/erg_compiler/context/inquire.rs @@ -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 => {} diff --git a/crates/erg_compiler/ty/mod.rs b/crates/erg_compiler/ty/mod.rs index 1d428262..cb525ec7 100644 --- a/crates/erg_compiler/ty/mod.rs +++ b/crates/erg_compiler/ty/mod.rs @@ -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 + 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(), diff --git a/crates/erg_compiler/ty/typaram.rs b/crates/erg_compiler/ty/typaram.rs index a668375f..7ba2a141 100644 --- a/crates/erg_compiler/ty/typaram.rs +++ b/crates/erg_compiler/ty/typaram.rs @@ -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(), diff --git a/tests/should_err/move.er b/tests/should_err/move.er new file mode 100644 index 00000000..c98240ca --- /dev/null +++ b/tests/should_err/move.er @@ -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 diff --git a/tests/test.rs b/tests/test.rs index 941e5310..1f19d065 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -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) +}