diff --git a/compiler/erg_compiler/build_hir.rs b/compiler/erg_compiler/build_hir.rs index 0434f100..6a298e87 100644 --- a/compiler/erg_compiler/build_hir.rs +++ b/compiler/erg_compiler/build_hir.rs @@ -10,7 +10,6 @@ use crate::artifact::{CompleteArtifact, IncompleteArtifact}; use crate::context::{Context, ContextProvider}; use crate::effectcheck::SideEffectChecker; use crate::error::{CompileError, CompileErrors}; -use crate::hir::HIR; use crate::lower::ASTLowerer; use crate::mod_cache::SharedModuleCache; use crate::ownercheck::OwnershipChecker; @@ -58,16 +57,18 @@ impl Runnable for HIRBuilder { fn exec(&mut self) -> Result { let mut builder = ASTBuilder::new(self.cfg().copy()); let ast = builder.build(self.input().read())?; - let hir = self.check(ast, "exec").map_err(|arti| arti.errors)?; - println!("{hir}"); + let artifact = self.check(ast, "exec").map_err(|arti| arti.errors)?; + artifact.warns.fmt_all_stderr(); + println!("{}", artifact.hir); Ok(0) } fn eval(&mut self, src: String) -> Result { let mut builder = ASTBuilder::new(self.cfg().copy()); let ast = builder.build(src)?; - let hir = self.check(ast, "eval").map_err(|arti| arti.errors)?; - Ok(hir.to_string()) + let artifact = self.check(ast, "eval").map_err(|arti| arti.errors)?; + artifact.warns.fmt_all_stderr(); + Ok(artifact.hir.to_string()) } } @@ -98,19 +99,19 @@ impl HIRBuilder { } } - pub fn check(&mut self, ast: AST, mode: &str) -> Result { + pub fn check(&mut self, ast: AST, mode: &str) -> Result { let artifact = self.lowerer.lower(ast, mode)?; if self.cfg().verbose >= 2 { artifact.warns.fmt_all_stderr(); } let effect_checker = SideEffectChecker::new(self.cfg().clone()); let hir = effect_checker.check(artifact.hir).map_err(|(hir, errs)| { - IncompleteArtifact::new(Some(hir), errs, CompileErrors::empty()) + IncompleteArtifact::new(Some(hir), errs, artifact.warns.clone()) })?; let hir = self.ownership_checker.check(hir).map_err(|(hir, errs)| { - IncompleteArtifact::new(Some(hir), errs, CompileErrors::empty()) + IncompleteArtifact::new(Some(hir), errs, artifact.warns.clone()) })?; - Ok(hir) + Ok(CompleteArtifact::new(hir, artifact.warns)) } pub fn build( @@ -122,8 +123,7 @@ impl HIRBuilder { let ast = ast_builder.build(src).map_err(|errs| { IncompleteArtifact::new(None, CompileErrors::from(errs), CompileErrors::empty()) })?; - let hir = self.check(ast, mode)?; - Ok(CompleteArtifact::new(hir, CompileErrors::empty())) + self.check(ast, mode) } pub fn pop_mod_ctx(&mut self) -> Context { diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index 199e917e..fbfab343 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -18,7 +18,7 @@ use erg_parser::error::{ParserRunnerError, ParserRunnerErrors}; use crate::context::Context; use crate::hir::{Expr, Identifier, Signature}; -use crate::ty::{Predicate, Type}; +use crate::ty::{HasType, Predicate, Type}; pub fn ordinal_num(n: usize) -> String { match n.to_string().chars().last().unwrap() { @@ -109,7 +109,7 @@ pub fn readable_name(name: &str) -> &str { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct CompileError { pub core: Box, // ErrorCore is large, so box it pub input: Input, @@ -1458,6 +1458,33 @@ impl LowerError { ) } + pub fn unused_expr_warning(input: Input, errno: usize, expr: &Expr, caused_by: String) -> Self { + let desc = switch_lang!( + "japanese" => format!("式の評価結果(: {})が使われていません", expr.ref_t()), + "simplified_chinese" => format!("表达式评估结果(: {})未使用", expr.ref_t()), + "traditional_chinese" => format!("表達式評估結果(: {})未使用", expr.ref_t()), + "english" => format!("the evaluation result of the expression (: {}) is not used", expr.ref_t()), + ); + let hint = switch_lang!( + "japanese" => "値を使わない場合は、discard関数を使用してください", + "simplified_chinese" => "如果您不想使用该值,请使用discard函数", + "traditional_chinese" => "如果您不想使用該值,請使用discard函數", + "english" => "if you don't use the value, use discard function", + ) + .to_owned(); + Self::new( + ErrorCore::new( + vec![SubMessage::ambiguous_new(expr.loc(), vec![], Some(hint))], + desc, + errno, + UnusedWarning, + expr.loc(), + ), + input, + caused_by, + ) + } + pub fn duplicate_decl_error( input: Input, errno: usize, @@ -2234,7 +2261,7 @@ impl LowerError { } } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct CompileErrors(Vec); impl std::error::Error for CompileErrors {} diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index c334a595..bd13f8a9 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -31,7 +31,7 @@ use crate::context::{ ClassDefType, Context, ContextKind, ContextProvider, RegistrationMode, TypeRelationInstance, }; use crate::error::{ - CompileError, CompileErrors, LowerError, LowerErrors, LowerResult, LowerWarnings, + CompileError, CompileErrors, LowerError, LowerErrors, LowerResult, LowerWarning, LowerWarnings, SingleLowerResult, }; use crate::hir; @@ -179,26 +179,11 @@ impl ASTLowerer { /// OK: exec `None` fn use_check(&self, expr: &hir::Expr, mode: &str) -> SingleLowerResult<()> { if mode != "eval" && !expr.ref_t().is_nonelike() && !expr.is_type_asc() { - Err(LowerError::syntax_error( + Err(LowerWarning::unused_expr_warning( self.cfg.input.clone(), line!() as usize, - expr.loc(), + expr, String::from(&self.ctx.name[..]), - switch_lang!( - "japanese" => format!("式の評価結果(: {})が使われていません", expr.ref_t()), - "simplified_chinese" => format!("表达式评估结果(: {})未使用", expr.ref_t()), - "traditional_chinese" => format!("表達式評估結果(: {})未使用", expr.ref_t()), - "english" => format!("the evaluation result of the expression (: {}) is not used", expr.ref_t()), - ), - Some( - switch_lang!( - "japanese" => "値を使わない場合は、discard関数を使用してください", - "simplified_chinese" => "如果您不想使用该值,请使用discard函数", - "traditional_chinese" => "如果您不想使用該值,請使用discard函數", - "english" => "if you don't use the value, use discard function", - ) - .to_owned(), - ), )) } else { Ok(()) @@ -1939,8 +1924,8 @@ impl ASTLowerer { }; // TODO: recursive check for chunk in hir.module.iter() { - if let Err(err) = self.use_check(chunk, mode) { - self.errs.push(err); + if let Err(warn) = self.use_check(chunk, mode) { + self.warns.push(warn); } } if self.errs.is_empty() {