From bb0f4d20fc56df93e087f81b6fcf32e9af54f5bb Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 17 May 2024 17:20:18 +0900 Subject: [PATCH] chore: set recursion call limit to `sub_unify` --- crates/erg_compiler/context/unify.rs | 15 +++++++++++++++ crates/erg_compiler/error/tycheck.rs | 25 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/crates/erg_compiler/context/unify.rs b/crates/erg_compiler/context/unify.rs index 2fe83be3f..b37828b56 100644 --- a/crates/erg_compiler/context/unify.rs +++ b/crates/erg_compiler/context/unify.rs @@ -2,6 +2,7 @@ use std::iter::repeat; use std::mem; use std::option::Option; +use std::sync::atomic::{AtomicUsize, Ordering}; use erg_common::consts::DEBUG_MODE; use erg_common::fresh::FRESH_GEN; @@ -33,6 +34,7 @@ pub struct Unifier<'c, 'l, 'u, L: Locational> { loc: &'l L, undoable: Option<&'u UndoableLinkedList>, change_generalized: bool, + recursion_limit: AtomicUsize, param_name: Option, } @@ -49,6 +51,7 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> { loc, undoable, change_generalized, + recursion_limit: AtomicUsize::new(128), param_name, } } @@ -945,6 +948,18 @@ impl<'c, 'l, 'u, L: Locational> Unifier<'c, 'l, 'u, L> { /// ``` fn sub_unify(&self, maybe_sub: &Type, maybe_sup: &Type) -> TyCheckResult<()> { log!(info "trying {}sub_unify:\nmaybe_sub: {maybe_sub}\nmaybe_sup: {maybe_sup}", self.undoable.map_or("", |_| "undoable_")); + self.recursion_limit.fetch_sub(1, Ordering::SeqCst); + if self.recursion_limit.load(Ordering::SeqCst) == 0 { + log!(err "recursion limit exceeded: {maybe_sub} / {maybe_sup}"); + return Err(TyCheckError::recursion_limit( + self.ctx.cfg.input.clone(), + line!() as usize, + self.loc.loc(), + fn_name!(), + line!(), + ) + .into()); + } // In this case, there is no new information to be gained // この場合、特に新しく得られる情報はない if maybe_sub == &Type::Never || maybe_sup == &Type::Obj || maybe_sup.addr_eq(maybe_sub) { diff --git a/crates/erg_compiler/error/tycheck.rs b/crates/erg_compiler/error/tycheck.rs index 465a96b41..834428aa5 100644 --- a/crates/erg_compiler/error/tycheck.rs +++ b/crates/erg_compiler/error/tycheck.rs @@ -53,6 +53,31 @@ impl TyCheckError { ) } + pub fn recursion_limit( + input: Input, + errno: usize, + loc: Location, + fn_name: &str, + line: u32, + ) -> Self { + Self::new( + ErrorCore::new( + vec![SubMessage::only_loc(loc)], + switch_lang!( + "japanese" => format!("コンパイラ内部の再帰呼び出し回数が上限に達しました。これはErg compilerのバグです、開発者に報告して下さい ({URL})\n\n{fn_name}:{line}より発生"), + "simplified_chinese" => format!("编译器内部的递归调用次数已达到上限。这是Erg编译器的错误,请报告给{URL}\n\n原因来自: {fn_name}:{line}"), + "traditional_chinese" => format!("編譯器內部的遞歸調用次數已達到上限。這是Erg編譯器的錯誤,請報告給{URL}\n\n原因來自: {fn_name}:{line}"), + "english" => format!("the number of recursive calls in the compiler has reached the limit. This is a bug of the Erg compiler, please report it to {URL}\n\ncaused from: {fn_name}:{line}"), + ), + errno, + CompilerSystemError, + loc, + ), + input, + "".to_string(), + ) + } + pub fn no_type_spec_error( input: Input, errno: usize,