mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-02 21:44:34 +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() {
|
||||
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()));
|
||||
} else {
|
||||
self.method_to_types.insert(
|
||||
self.method_to_traits.insert(
|
||||
trait_method.inspect().clone(),
|
||||
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||
);
|
||||
}
|
||||
}
|
||||
for (class_method, vi) in ctx.locals.iter() {
|
||||
if let Some(mut types) = self.method_to_types.remove(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()));
|
||||
}
|
||||
self.method_to_types
|
||||
.insert(class_method.inspect().clone(), types);
|
||||
if let Some(types) = self.method_to_classes.get_mut(class_method.inspect()) {
|
||||
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||
} else {
|
||||
self.method_to_types.insert(
|
||||
self.method_to_classes.insert(
|
||||
class_method.inspect().clone(),
|
||||
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||
);
|
||||
|
@ -182,25 +177,20 @@ impl Context {
|
|||
}
|
||||
}
|
||||
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()));
|
||||
} else {
|
||||
self.method_to_types.insert(
|
||||
self.method_to_traits.insert(
|
||||
trait_method.inspect().clone(),
|
||||
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||
);
|
||||
}
|
||||
}
|
||||
for (class_method, vi) in ctx.locals.iter() {
|
||||
if let Some(mut types) = self.method_to_types.remove(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()));
|
||||
}
|
||||
self.method_to_types
|
||||
.insert(class_method.inspect().clone(), types);
|
||||
if let Some(types) = self.method_to_classes.get_mut(class_method.inspect()) {
|
||||
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||
} else {
|
||||
self.method_to_types.insert(
|
||||
self.method_to_classes.insert(
|
||||
class_method.inspect().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> {
|
||||
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;
|
||||
if candidates
|
||||
.iter()
|
||||
.skip(1)
|
||||
.all(|t| &t.method_type == first_method_type)
|
||||
{
|
||||
Ok(&candidates[0])
|
||||
return Ok(&candidates[0]);
|
||||
} else {
|
||||
Err(TyCheckError::ambiguous_type_error(
|
||||
return Err(TyCheckError::ambiguous_type_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
name,
|
||||
|
@ -1782,9 +1783,31 @@ impl Context {
|
|||
.map(|t| t.definition_type.clone())
|
||||
.collect::<Vec<_>>(),
|
||||
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)
|
||||
} else {
|
||||
Err(TyCheckError::no_attr_error(
|
||||
|
|
|
@ -347,7 +347,8 @@ pub struct Context {
|
|||
pub(crate) methods_list: Vec<(ClassDefType, Context)>,
|
||||
// K: method name, V: types defines the method
|
||||
// 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
|
||||
/// Provided methods can switch implementations on a scope-by-scope basis
|
||||
/// K: メソッド名, V: それを実装するパッチたち
|
||||
|
@ -485,7 +486,8 @@ impl Context {
|
|||
super_traits: vec![],
|
||||
methods_list: vec![],
|
||||
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(),
|
||||
trait_impls: Dict::default(),
|
||||
params: params_,
|
||||
|
|
|
@ -848,25 +848,20 @@ impl Context {
|
|||
}
|
||||
}
|
||||
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()));
|
||||
} else {
|
||||
self.method_to_types.insert(
|
||||
self.method_to_traits.insert(
|
||||
trait_method.inspect().clone(),
|
||||
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||
);
|
||||
}
|
||||
}
|
||||
for (class_method, vi) in ctx.locals.iter() {
|
||||
if let Some(mut types) = self.method_to_types.remove(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()));
|
||||
}
|
||||
self.method_to_types
|
||||
.insert(class_method.inspect().clone(), types);
|
||||
if let Some(types) = self.method_to_classes.get_mut(class_method.inspect()) {
|
||||
types.push(MethodType::new(t.clone(), vi.t.clone()));
|
||||
} else {
|
||||
self.method_to_types.insert(
|
||||
self.method_to_classes.insert(
|
||||
class_method.inspect().clone(),
|
||||
vec![MethodType::new(t.clone(), vi.t.clone())],
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue