mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 04:24:43 +00:00
fix: attribute inffering
This commit is contained in:
parent
40762bf8cf
commit
57588c78f7
2 changed files with 28 additions and 20 deletions
|
@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
|
||||||
use erg_common::config::{ErgConfig, Input};
|
use erg_common::config::{ErgConfig, Input};
|
||||||
use erg_common::dict;
|
use erg_common::dict;
|
||||||
use erg_common::env::{erg_py_external_lib_path, erg_pystd_path, erg_std_path};
|
use erg_common::env::{erg_py_external_lib_path, erg_pystd_path, erg_std_path};
|
||||||
use erg_common::error::{ErrorCore, ErrorKind, Location, SubMessage};
|
use erg_common::error::{ErrorCore, Location, SubMessage};
|
||||||
use erg_common::levenshtein;
|
use erg_common::levenshtein;
|
||||||
use erg_common::pathutil::add_postfix_foreach;
|
use erg_common::pathutil::add_postfix_foreach;
|
||||||
use erg_common::set::Set;
|
use erg_common::set::Set;
|
||||||
|
@ -545,6 +545,20 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
match self.get_attr_type_by_name(ident) {
|
||||||
|
Triple::Ok(method) => {
|
||||||
|
if let Err(mut errs) =
|
||||||
|
self.sub_unify(obj.ref_t(), &method.definition_type, obj, None)
|
||||||
|
{
|
||||||
|
return Triple::Err(errs.remove(0));
|
||||||
|
}
|
||||||
|
return Triple::Ok(method.method_type.clone());
|
||||||
|
}
|
||||||
|
Triple::Err(err) if !cfg!(feature = "py_compatible") => {
|
||||||
|
return Triple::Err(err);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
// get_attr_info(?T, aaa) == None
|
// get_attr_info(?T, aaa) == None
|
||||||
// => ?T(<: Structural({ .aaa = ?U }))
|
// => ?T(<: Structural({ .aaa = ?U }))
|
||||||
if self.in_subr() && cfg!(feature = "py_compatible") {
|
if self.in_subr() && cfg!(feature = "py_compatible") {
|
||||||
|
@ -838,14 +852,14 @@ impl Context {
|
||||||
self.get_similar_attr_from_singular(obj, attr_name.inspect()),
|
self.get_similar_attr_from_singular(obj, attr_name.inspect()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
match self.get_method_type_by_name(attr_name) {
|
match self.get_attr_type_by_name(attr_name) {
|
||||||
Ok(method) => {
|
Triple::Ok(method) => {
|
||||||
self.sub_unify(obj.ref_t(), &method.definition_type, obj, None)
|
self.sub_unify(obj.ref_t(), &method.definition_type, obj, None)
|
||||||
// HACK: change this func's return type to TyCheckResult<Type>
|
// HACK: change this func's return type to TyCheckResult<Type>
|
||||||
.map_err(|mut errs| errs.remove(0))?;
|
.map_err(|mut errs| errs.remove(0))?;
|
||||||
return Ok(method.method_type.clone());
|
return Ok(method.method_type.clone());
|
||||||
}
|
}
|
||||||
Err(err) if err.core.kind == ErrorKind::TypeError => {
|
Triple::Err(err) => {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -2455,7 +2469,9 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_method_type_by_name(&self, name: &Identifier) -> SingleTyCheckResult<&MethodInfo> {
|
/// Infer the receiver type from the attribute name.
|
||||||
|
/// Returns an error if multiple candidates are found. If nothing is found, returns None.
|
||||||
|
fn get_attr_type_by_name(&self, name: &Identifier) -> Triple<&MethodInfo, TyCheckError> {
|
||||||
// TODO: min_by
|
// TODO: min_by
|
||||||
if let Some(candidates) = self.method_to_traits.get(name.inspect()) {
|
if let Some(candidates) = self.method_to_traits.get(name.inspect()) {
|
||||||
let first_method_type = &candidates.first().unwrap().method_type;
|
let first_method_type = &candidates.first().unwrap().method_type;
|
||||||
|
@ -2464,9 +2480,9 @@ impl Context {
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.all(|t| &t.method_type == first_method_type)
|
.all(|t| &t.method_type == first_method_type)
|
||||||
{
|
{
|
||||||
return Ok(&candidates[0]);
|
return Triple::Ok(&candidates[0]);
|
||||||
} else {
|
} else {
|
||||||
return Err(TyCheckError::ambiguous_type_error(
|
return Triple::Err(TyCheckError::ambiguous_type_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
name,
|
name,
|
||||||
|
@ -2485,9 +2501,9 @@ impl Context {
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.all(|t| &t.method_type == first_method_type)
|
.all(|t| &t.method_type == first_method_type)
|
||||||
{
|
{
|
||||||
return Ok(&candidates[0]);
|
return Triple::Ok(&candidates[0]);
|
||||||
} else {
|
} else {
|
||||||
return Err(TyCheckError::ambiguous_type_error(
|
return Triple::Err(TyCheckError::ambiguous_type_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
name,
|
name,
|
||||||
|
@ -2500,17 +2516,9 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) {
|
if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) {
|
||||||
outer.get_method_type_by_name(name)
|
outer.get_attr_type_by_name(name)
|
||||||
} else {
|
} else {
|
||||||
Err(TyCheckError::no_attr_error(
|
Triple::None
|
||||||
self.cfg.input.clone(),
|
|
||||||
line!() as usize,
|
|
||||||
name.loc(),
|
|
||||||
self.caused_by(),
|
|
||||||
&Type::Failure,
|
|
||||||
name.inspect(),
|
|
||||||
None,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.dis!: (x: Code or ClassType or TraitType or Proc or Str or Bytes or NoneType := NoneType) => NoneType
|
.dis!: (x: Code or ClassType or TraitType or GenericCallable or Str or Bytes or NoneType := NoneType) => NoneType
|
||||||
.code_info: (x: Code or ClassType or TraitType or GenericCallable or Str or Bytes) -> Str
|
.code_info: (x: Code or ClassType or TraitType or GenericCallable or Str or Bytes) -> Str
|
||||||
.show_code!: (x: Code or ClassType or TraitType or GenericCallable or Str or Bytes) => NoneType
|
.show_code!: (x: Code or ClassType or TraitType or GenericCallable or Str or Bytes) => NoneType
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue