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()),
|
self.get_similar_attr_from_singular(obj, method_name.inspect()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let Some(trait_) = self.rec_get_method_traits(method_name) {
|
match self.rec_get_method_traits(method_name) {
|
||||||
let (_, ctx) = self.get_nominal_type_ctx(trait_).unwrap();
|
Ok(trait_) => {
|
||||||
return ctx.rec_get_var_t(method_name, input, namespace);
|
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
|
// TODO: patch
|
||||||
Err(TyCheckError::no_attr_error(
|
Err(TyCheckError::no_attr_error(
|
||||||
|
@ -1561,17 +1567,32 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rec_get_method_traits(&self, name: &Identifier) -> Option<&Type> {
|
fn rec_get_method_traits(&self, name: &Identifier) -> SingleTyCheckResult<&Type> {
|
||||||
if let Some(t) = self.method_traits.get(name.inspect()) {
|
if let Some(candidates) = self.method_traits.get(name.inspect()) {
|
||||||
if t.len() == 1 {
|
let first_t = candidates.first().unwrap();
|
||||||
Some(&t[0])
|
if candidates.iter().skip(1).all(|t| t == first_t) {
|
||||||
|
Ok(&candidates[0])
|
||||||
} else {
|
} 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()) {
|
} else if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) {
|
||||||
outer.rec_get_method_traits(name)
|
outer.rec_get_method_traits(name)
|
||||||
} else {
|
} 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));
|
return Some((name, vi));
|
||||||
}
|
}
|
||||||
if is_const {
|
if is_const {
|
||||||
if let Some(outer) = self.get_outer().or_else(|| self.get_builtins()) {
|
let outer = self.get_outer().or_else(|| self.get_builtins())?;
|
||||||
outer.registered_info(name, is_const)
|
outer.registered_info(name, is_const)
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -460,18 +457,27 @@ impl Context {
|
||||||
|
|
||||||
// To allow forward references and recursive definitions
|
// To allow forward references and recursive definitions
|
||||||
pub(crate) fn preregister(&mut self, block: &ast::Block) -> TyCheckResult<()> {
|
pub(crate) fn preregister(&mut self, block: &ast::Block) -> TyCheckResult<()> {
|
||||||
|
let mut total_errs = TyCheckErrors::empty();
|
||||||
for expr in block.iter() {
|
for expr in block.iter() {
|
||||||
match expr {
|
match expr {
|
||||||
ast::Expr::Def(def) => {
|
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) => {
|
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<()> {
|
pub(crate) fn preregister_def(&mut self, def: &ast::Def) -> TyCheckResult<()> {
|
||||||
|
|
|
@ -920,6 +920,38 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
||||||
caused_by,
|
caused_by,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ambiguous_type_error(
|
||||||
|
input: Input,
|
||||||
|
errno: usize,
|
||||||
|
expr: &(impl Locational + Display),
|
||||||
|
candidates: &[Type],
|
||||||
|
caused_by: AtomicStr,
|
||||||
|
) -> Self {
|
||||||
|
Self::new(
|
||||||
|
ErrorCore::new(
|
||||||
|
errno,
|
||||||
|
TypeError,
|
||||||
|
expr.loc(),
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("{expr}の型を一意に決定できませんでした\n候補: {}", fmt_vec(candidates)),
|
||||||
|
"simplified_chinese" => format!("无法确定{expr}的类型\n候选:{}", fmt_vec(candidates)),
|
||||||
|
"traditional_chinese" => format!("無法確定{expr}的類型\n候選:{}", fmt_vec(candidates)),
|
||||||
|
"english" => format!("cannot determine the type of {expr}\ncandidates: {}", fmt_vec(candidates)),
|
||||||
|
),
|
||||||
|
Some(
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => "多相関数の場合は`f|T := Int|`, 型属性の場合は`T|T <: Trait|.X`などのようにして型を指定してください",
|
||||||
|
"simplified_chinese" => "如果是多态函数,请使用`f|T := Int|`,如果是类型属性,请使用`T|T <: Trait|.X`等方式指定类型",
|
||||||
|
"traditional_chinese" => "如果是多型函數,請使用`f|T := Int|`,如果是類型屬性,請使用`T|T <: Trait|.X`等方式指定類型",
|
||||||
|
"english" => "if it is a polymorphic function, use `f|T := Int|`, or if it is a type attribute, use `T|T <: Trait|.X` etc. to specify the type",
|
||||||
|
).into(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
input,
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TyCheckErrors = CompileErrors;
|
pub type TyCheckErrors = CompileErrors;
|
||||||
|
|
|
@ -508,16 +508,12 @@ impl ASTLowerer {
|
||||||
ContextKind::Func
|
ContextKind::Func
|
||||||
};
|
};
|
||||||
self.ctx.grow(&name, kind, Private)?;
|
self.ctx.grow(&name, kind, Private)?;
|
||||||
self.ctx
|
if let Err(errs) = self.ctx.assign_params(&lambda.sig.params, None) {
|
||||||
.assign_params(&lambda.sig.params, None)
|
self.errs.extend(errs.into_iter());
|
||||||
.map_err(|e| {
|
}
|
||||||
self.pop_append_errs();
|
if let Err(errs) = self.ctx.preregister(&lambda.body) {
|
||||||
e
|
self.errs.extend(errs.into_iter());
|
||||||
})?;
|
}
|
||||||
self.ctx.preregister(&lambda.body).map_err(|e| {
|
|
||||||
self.pop_append_errs();
|
|
||||||
e
|
|
||||||
})?;
|
|
||||||
let body = self.lower_block(lambda.body).map_err(|e| {
|
let body = self.lower_block(lambda.body).map_err(|e| {
|
||||||
self.pop_append_errs();
|
self.pop_append_errs();
|
||||||
e
|
e
|
||||||
|
@ -606,8 +602,13 @@ impl ASTLowerer {
|
||||||
body: ast::DefBody,
|
body: ast::DefBody,
|
||||||
) -> LowerResult<hir::Def> {
|
) -> LowerResult<hir::Def> {
|
||||||
log!(info "entered {}({sig})", fn_name!());
|
log!(info "entered {}({sig})", fn_name!());
|
||||||
self.ctx.preregister(&body.block)?;
|
if let Err(errs) = self.ctx.preregister(&body.block) {
|
||||||
let block = self.lower_block(body.block)?;
|
self.errs.extend(errs.into_iter());
|
||||||
|
}
|
||||||
|
let block = self.lower_block(body.block).map_err(|e| {
|
||||||
|
self.pop_append_errs();
|
||||||
|
e
|
||||||
|
})?;
|
||||||
let found_body_t = block.ref_t();
|
let found_body_t = block.ref_t();
|
||||||
let opt_expect_body_t = self
|
let opt_expect_body_t = self
|
||||||
.ctx
|
.ctx
|
||||||
|
@ -660,9 +661,16 @@ impl ASTLowerer {
|
||||||
.t
|
.t
|
||||||
.clone();
|
.clone();
|
||||||
let t = enum_unwrap!(t, Type::Subr);
|
let t = enum_unwrap!(t, Type::Subr);
|
||||||
self.ctx.assign_params(&sig.params, Some(t.clone()))?;
|
if let Err(errs) = self.ctx.assign_params(&sig.params, Some(t.clone())) {
|
||||||
self.ctx.preregister(&body.block)?;
|
self.errs.extend(errs.into_iter());
|
||||||
let block = self.lower_block(body.block)?;
|
}
|
||||||
|
if let Err(errs) = self.ctx.preregister(&body.block) {
|
||||||
|
self.errs.extend(errs.into_iter());
|
||||||
|
}
|
||||||
|
let block = self.lower_block(body.block).map_err(|e| {
|
||||||
|
self.pop_append_errs();
|
||||||
|
e
|
||||||
|
})?;
|
||||||
let found_body_t = block.ref_t();
|
let found_body_t = block.ref_t();
|
||||||
let expect_body_t = t.return_t.as_ref();
|
let expect_body_t = t.return_t.as_ref();
|
||||||
if !sig.is_const() {
|
if !sig.is_const() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue