diff --git a/compiler/erg_compiler/context/initialize/mod.rs b/compiler/erg_compiler/context/initialize/mod.rs index acfcd93d..e17e4f11 100644 --- a/compiler/erg_compiler/context/initialize/mod.rs +++ b/compiler/erg_compiler/context/initialize/mod.rs @@ -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())], ); diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index 01c0be71..f931585f 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -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::>(), 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::>(), + 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( diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index afd6c197..396d6a36 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -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>, + pub(crate) method_to_traits: Dict>, + pub(crate) method_to_classes: Dict>, /// 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_, diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 6d9620b5..9d9ff432 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -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())], );