mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
Fix lowerer crash bugs
This commit is contained in:
parent
12664a0e1c
commit
622e1fa350
4 changed files with 99 additions and 32 deletions
|
@ -495,9 +495,15 @@ impl Context {
|
|||
self.get_similar_attr_from_singular(obj, method_name.inspect()),
|
||||
));
|
||||
}
|
||||
if let Some(trait_) = self.rec_get_method_traits(method_name) {
|
||||
let (_, ctx) = self.get_nominal_type_ctx(trait_).unwrap();
|
||||
return ctx.rec_get_var_t(method_name, input, namespace);
|
||||
match self.rec_get_method_traits(method_name) {
|
||||
Ok(trait_) => {
|
||||
let (_, ctx) = self.get_nominal_type_ctx(trait_).unwrap();
|
||||
return ctx.rec_get_var_t(method_name, input, namespace);
|
||||
}
|
||||
Err(err) if err.core.kind == ErrorKind::TypeError => {
|
||||
return Err(err);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
// TODO: patch
|
||||
Err(TyCheckError::no_attr_error(
|
||||
|
@ -1561,17 +1567,32 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
fn rec_get_method_traits(&self, name: &Identifier) -> Option<&Type> {
|
||||
if let Some(t) = self.method_traits.get(name.inspect()) {
|
||||
if t.len() == 1 {
|
||||
Some(&t[0])
|
||||
fn rec_get_method_traits(&self, name: &Identifier) -> SingleTyCheckResult<&Type> {
|
||||
if let Some(candidates) = self.method_traits.get(name.inspect()) {
|
||||
let first_t = candidates.first().unwrap();
|
||||
if candidates.iter().skip(1).all(|t| t == first_t) {
|
||||
Ok(&candidates[0])
|
||||
} else {
|
||||
None
|
||||
Err(TyCheckError::ambiguous_type_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
name,
|
||||
candidates,
|
||||
self.caused_by(),
|
||||
))
|
||||
}
|
||||
} else if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) {
|
||||
outer.rec_get_method_traits(name)
|
||||
} else {
|
||||
None
|
||||
Err(TyCheckError::no_attr_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
name.loc(),
|
||||
self.caused_by(),
|
||||
&Type::Failure,
|
||||
name.inspect(),
|
||||
None,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -50,11 +50,8 @@ impl Context {
|
|||
return Some((name, vi));
|
||||
}
|
||||
if is_const {
|
||||
if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) {
|
||||
outer.registered_info(name, is_const)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
let outer = self.get_outer().or_else(|| self.get_builtins())?;
|
||||
outer.registered_info(name, is_const)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -460,18 +457,27 @@ impl Context {
|
|||
|
||||
// To allow forward references and recursive definitions
|
||||
pub(crate) fn preregister(&mut self, block: &ast::Block) -> TyCheckResult<()> {
|
||||
let mut total_errs = TyCheckErrors::empty();
|
||||
for expr in block.iter() {
|
||||
match expr {
|
||||
ast::Expr::Def(def) => {
|
||||
self.preregister_def(def)?;
|
||||
if let Err(errs) = self.preregister_def(def) {
|
||||
total_errs.extend(errs.into_iter());
|
||||
}
|
||||
}
|
||||
ast::Expr::ClassDef(class_def) => {
|
||||
self.preregister_def(&class_def.def)?;
|
||||
if let Err(errs) = self.preregister_def(&class_def.def) {
|
||||
total_errs.extend(errs.into_iter());
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
if total_errs.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(total_errs)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn preregister_def(&mut self, def: &ast::Def) -> TyCheckResult<()> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue