mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-03 05:54:33 +00:00
Raise the priority of traits in method search
This commit is contained in:
parent
59f6046916
commit
e89bb869bf
4 changed files with 47 additions and 37 deletions
|
@ -126,25 +126,20 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (trait_method, vi) in ctx.decls.iter() {
|
for (trait_method, vi) in ctx.decls.iter() {
|
||||||
if let Some(types) = self.method_to_types.get_mut(trait_method.inspect()) {
|
if let Some(types) = self.method_to_traits.get_mut(trait_method.inspect()) {
|
||||||
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||||
} else {
|
} else {
|
||||||
self.method_to_types.insert(
|
self.method_to_traits.insert(
|
||||||
trait_method.inspect().clone(),
|
trait_method.inspect().clone(),
|
||||||
vec![MethodType::new(t.clone(), vi.t.clone())],
|
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (class_method, vi) in ctx.locals.iter() {
|
for (class_method, vi) in ctx.locals.iter() {
|
||||||
if let Some(mut types) = self.method_to_types.remove(class_method.inspect()) {
|
if let Some(types) = self.method_to_classes.get_mut(class_method.inspect()) {
|
||||||
// doesn't register if it's declared as a trait
|
|
||||||
if self.is_class(&types.first().unwrap().definition_type) {
|
|
||||||
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||||
}
|
|
||||||
self.method_to_types
|
|
||||||
.insert(class_method.inspect().clone(), types);
|
|
||||||
} else {
|
} else {
|
||||||
self.method_to_types.insert(
|
self.method_to_classes.insert(
|
||||||
class_method.inspect().clone(),
|
class_method.inspect().clone(),
|
||||||
vec![MethodType::new(t.clone(), vi.t.clone())],
|
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||||
);
|
);
|
||||||
|
@ -182,25 +177,20 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (trait_method, vi) in ctx.decls.iter() {
|
for (trait_method, vi) in ctx.decls.iter() {
|
||||||
if let Some(traits) = self.method_to_types.get_mut(trait_method.inspect()) {
|
if let Some(traits) = self.method_to_traits.get_mut(trait_method.inspect()) {
|
||||||
traits.push(MethodType::new(t.clone(), vi.t.clone()));
|
traits.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||||
} else {
|
} else {
|
||||||
self.method_to_types.insert(
|
self.method_to_traits.insert(
|
||||||
trait_method.inspect().clone(),
|
trait_method.inspect().clone(),
|
||||||
vec![MethodType::new(t.clone(), vi.t.clone())],
|
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (class_method, vi) in ctx.locals.iter() {
|
for (class_method, vi) in ctx.locals.iter() {
|
||||||
if let Some(mut types) = self.method_to_types.remove(class_method.inspect()) {
|
if let Some(types) = self.method_to_classes.get_mut(class_method.inspect()) {
|
||||||
// doesn't register if it's declared as a trait
|
|
||||||
if self.is_class(&types.first().unwrap().definition_type) {
|
|
||||||
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||||
}
|
|
||||||
self.method_to_types
|
|
||||||
.insert(class_method.inspect().clone(), types);
|
|
||||||
} else {
|
} else {
|
||||||
self.method_to_types.insert(
|
self.method_to_classes.insert(
|
||||||
class_method.inspect().clone(),
|
class_method.inspect().clone(),
|
||||||
vec![MethodType::new(t.clone(), vi.t.clone())],
|
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||||
);
|
);
|
||||||
|
|
|
@ -1764,16 +1764,17 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_method_type_by_name(&self, name: &Identifier) -> SingleTyCheckResult<&MethodType> {
|
fn get_method_type_by_name(&self, name: &Identifier) -> SingleTyCheckResult<&MethodType> {
|
||||||
if let Some(candidates) = self.method_to_types.get(name.inspect()) {
|
// TODO: min_by
|
||||||
|
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;
|
||||||
if candidates
|
if candidates
|
||||||
.iter()
|
.iter()
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.all(|t| &t.method_type == first_method_type)
|
.all(|t| &t.method_type == first_method_type)
|
||||||
{
|
{
|
||||||
Ok(&candidates[0])
|
return Ok(&candidates[0]);
|
||||||
} else {
|
} else {
|
||||||
Err(TyCheckError::ambiguous_type_error(
|
return Err(TyCheckError::ambiguous_type_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
name,
|
name,
|
||||||
|
@ -1782,9 +1783,31 @@ impl Context {
|
||||||
.map(|t| t.definition_type.clone())
|
.map(|t| t.definition_type.clone())
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
} else if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) {
|
}
|
||||||
|
if let Some(candidates) = self.method_to_classes.get(name.inspect()) {
|
||||||
|
let first_method_type = &candidates.first().unwrap().method_type;
|
||||||
|
if candidates
|
||||||
|
.iter()
|
||||||
|
.skip(1)
|
||||||
|
.all(|t| &t.method_type == first_method_type)
|
||||||
|
{
|
||||||
|
return Ok(&candidates[0]);
|
||||||
|
} else {
|
||||||
|
return Err(TyCheckError::ambiguous_type_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
name,
|
||||||
|
&candidates
|
||||||
|
.iter()
|
||||||
|
.map(|t| t.definition_type.clone())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
self.caused_by(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) {
|
||||||
outer.get_method_type_by_name(name)
|
outer.get_method_type_by_name(name)
|
||||||
} else {
|
} else {
|
||||||
Err(TyCheckError::no_attr_error(
|
Err(TyCheckError::no_attr_error(
|
||||||
|
|
|
@ -347,7 +347,8 @@ pub struct Context {
|
||||||
pub(crate) methods_list: Vec<(ClassDefType, Context)>,
|
pub(crate) methods_list: Vec<(ClassDefType, Context)>,
|
||||||
// K: method name, V: types defines the method
|
// K: method name, V: types defines the method
|
||||||
// If it is declared in a trait, it takes precedence over the class.
|
// If it is declared in a trait, it takes precedence over the class.
|
||||||
pub(crate) method_to_types: Dict<Str, Vec<MethodType>>,
|
pub(crate) method_to_traits: Dict<Str, Vec<MethodType>>,
|
||||||
|
pub(crate) method_to_classes: Dict<Str, Vec<MethodType>>,
|
||||||
/// K: method name, V: impl patch
|
/// K: method name, V: impl patch
|
||||||
/// Provided methods can switch implementations on a scope-by-scope basis
|
/// Provided methods can switch implementations on a scope-by-scope basis
|
||||||
/// K: メソッド名, V: それを実装するパッチたち
|
/// K: メソッド名, V: それを実装するパッチたち
|
||||||
|
@ -485,7 +486,8 @@ impl Context {
|
||||||
super_traits: vec![],
|
super_traits: vec![],
|
||||||
methods_list: vec![],
|
methods_list: vec![],
|
||||||
const_param_defaults: Dict::default(),
|
const_param_defaults: Dict::default(),
|
||||||
method_to_types: Dict::default(),
|
method_to_traits: Dict::default(),
|
||||||
|
method_to_classes: Dict::default(),
|
||||||
method_impl_patches: Dict::default(),
|
method_impl_patches: Dict::default(),
|
||||||
trait_impls: Dict::default(),
|
trait_impls: Dict::default(),
|
||||||
params: params_,
|
params: params_,
|
||||||
|
|
|
@ -848,25 +848,20 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (trait_method, vi) in ctx.decls.iter() {
|
for (trait_method, vi) in ctx.decls.iter() {
|
||||||
if let Some(types) = self.method_to_types.get_mut(trait_method.inspect()) {
|
if let Some(types) = self.method_to_traits.get_mut(trait_method.inspect()) {
|
||||||
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||||
} else {
|
} else {
|
||||||
self.method_to_types.insert(
|
self.method_to_traits.insert(
|
||||||
trait_method.inspect().clone(),
|
trait_method.inspect().clone(),
|
||||||
vec![MethodType::new(t.clone(), vi.t.clone())],
|
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (class_method, vi) in ctx.locals.iter() {
|
for (class_method, vi) in ctx.locals.iter() {
|
||||||
if let Some(mut types) = self.method_to_types.remove(class_method.inspect()) {
|
if let Some(types) = self.method_to_classes.get_mut(class_method.inspect()) {
|
||||||
// doesn't register if it's declared as a trait
|
|
||||||
if self.is_class(&types.first().unwrap().definition_type) {
|
|
||||||
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||||
}
|
|
||||||
self.method_to_types
|
|
||||||
.insert(class_method.inspect().clone(), types);
|
|
||||||
} else {
|
} else {
|
||||||
self.method_to_types.insert(
|
self.method_to_classes.insert(
|
||||||
class_method.inspect().clone(),
|
class_method.inspect().clone(),
|
||||||
vec![MethodType::new(t.clone(), vi.t.clone())],
|
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue