From fe1b0fab70678de947db25c2a5cbb65e13eb4617 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Wed, 14 Sep 2022 12:11:06 +0900 Subject: [PATCH] Add `AtomicStr` --- compiler/erg_common/astr.rs | 166 +++++++++++++++++++++++ compiler/erg_common/error.rs | 10 +- compiler/erg_common/lib.rs | 1 + compiler/erg_compiler/codegen.rs | 5 +- compiler/erg_compiler/context/hint.rs | 10 +- compiler/erg_compiler/context/inquire.rs | 16 +-- compiler/erg_compiler/context/mod.rs | 5 +- compiler/erg_compiler/error.rs | 102 ++++++++------ compiler/erg_compiler/lower.rs | 67 ++++----- compiler/erg_parser/error.rs | 10 +- compiler/erg_type/deserialize.rs | 13 +- 11 files changed, 300 insertions(+), 105 deletions(-) create mode 100644 compiler/erg_common/astr.rs diff --git a/compiler/erg_common/astr.rs b/compiler/erg_common/astr.rs new file mode 100644 index 00000000..239b0430 --- /dev/null +++ b/compiler/erg_common/astr.rs @@ -0,0 +1,166 @@ +use std::borrow::Borrow; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::ops::{Add, Deref}; + +use crate::Str; + +pub type ArcStr = std::sync::Arc; + +/// Used to hold an immutable string. +/// +/// It can construct as a const (by AtomicStr::ever). +#[derive(Debug, Clone, Eq)] +pub enum AtomicStr { + Arc(ArcStr), + Static(&'static str), +} + +// unsafe impl Sync for AtomicStr {} + +impl PartialEq for AtomicStr { + #[inline] + fn eq(&self, other: &AtomicStr) -> bool { + self[..] == other[..] + } +} + +impl Add<&str> for AtomicStr { + type Output = AtomicStr; + #[inline] + fn add(self, other: &str) -> AtomicStr { + AtomicStr::from(&format!("{self}{other}")) + } +} + +impl Hash for AtomicStr { + fn hash(&self, state: &mut H) { + match self { + AtomicStr::Arc(s) => (s[..]).hash(state), + AtomicStr::Static(s) => s.hash(state), + } + } +} + +impl fmt::Display for AtomicStr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + AtomicStr::Arc(s) => write!(f, "{s}"), + AtomicStr::Static(s) => write!(f, "{s}"), + } + } +} + +// &'static str -> &strになってしまわないように +// あえて`impl> From for AtomicStr { ... }`はしない +impl From<&'static str> for AtomicStr { + #[inline] + fn from(s: &'static str) -> Self { + AtomicStr::ever(s) + } +} + +impl From<&String> for AtomicStr { + #[inline] + fn from(s: &String) -> Self { + AtomicStr::Arc((s[..]).into()) + } +} + +impl From for AtomicStr { + #[inline] + fn from(s: String) -> Self { + AtomicStr::Arc((s[..]).into()) + } +} + +impl From<&ArcStr> for AtomicStr { + #[inline] + fn from(s: &ArcStr) -> Self { + AtomicStr::Arc(s.clone()) + } +} + +impl From for AtomicStr { + #[inline] + fn from(s: ArcStr) -> Self { + AtomicStr::Arc(s) + } +} + +impl From<&AtomicStr> for AtomicStr { + #[inline] + fn from(s: &AtomicStr) -> Self { + match s { + AtomicStr::Arc(s) => AtomicStr::Arc(s.clone()), + AtomicStr::Static(s) => AtomicStr::Static(s), + } + } +} + +impl From for AtomicStr { + #[inline] + fn from(s: Str) -> Self { + match s { + Str::Rc(s) => AtomicStr::Arc((&s[..]).into()), + Str::Static(s) => AtomicStr::Static(s), + } + } +} + +impl From<&Str> for AtomicStr { + #[inline] + fn from(s: &Str) -> Self { + match s { + Str::Rc(s) => AtomicStr::Arc((&s[..]).into()), + Str::Static(s) => AtomicStr::Static(s), + } + } +} + +impl Deref for AtomicStr { + type Target = str; + fn deref(&self) -> &Self::Target { + self.borrow() + } +} + +impl Borrow for AtomicStr { + #[inline] + fn borrow(&self) -> &str { + match self { + AtomicStr::Arc(s) => s.borrow(), + AtomicStr::Static(s) => s, + } + } +} + +impl AsRef for AtomicStr { + fn as_ref(&self) -> &str { + self.borrow() + } +} + +impl AtomicStr { + pub const fn ever(s: &'static str) -> Self { + AtomicStr::Static(s) + } + + pub fn arc(s: &str) -> Self { + AtomicStr::Arc(s.into()) + } + + pub fn into_rc(self) -> ArcStr { + match self { + AtomicStr::Arc(s) => s, + AtomicStr::Static(s) => ArcStr::from(s), + } + } + + pub fn is_uppercase(&self) -> bool { + self.chars() + .next() + .map(|c| c.is_uppercase()) + .unwrap_or(false) + } +} diff --git a/compiler/erg_common/error.rs b/compiler/erg_common/error.rs index ad832bee..67bb4257 100644 --- a/compiler/erg_common/error.rs +++ b/compiler/erg_common/error.rs @@ -6,10 +6,10 @@ use std::fmt; use std::fmt::Write as _; use std::io::{stderr, BufWriter, Write as _}; +use crate::astr::AtomicStr; use crate::color::*; use crate::config::Input; use crate::traits::{Locational, Stream}; -use crate::Str; use crate::{fmt_option, impl_display_from_debug, switch_lang}; /// ErrorKindと言っているが、ErrorだけでなくWarning, Exceptionも含まれる @@ -306,17 +306,17 @@ pub struct ErrorCore { pub errno: usize, pub kind: ErrorKind, pub loc: Location, - pub desc: Str, - pub hint: Option, + pub desc: AtomicStr, + pub hint: Option, } impl ErrorCore { - pub fn new>( + pub fn new>( errno: usize, kind: ErrorKind, loc: Location, desc: S, - hint: Option, + hint: Option, ) -> Self { Self { errno, diff --git a/compiler/erg_common/lib.rs b/compiler/erg_common/lib.rs index ed50f82f..9e6520c1 100644 --- a/compiler/erg_common/lib.rs +++ b/compiler/erg_common/lib.rs @@ -1,6 +1,7 @@ //! provides utilities for parser, compiler, and vm crate. use std::fmt; +pub mod astr; pub mod cache; pub mod color; pub mod config; diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index 6567e05f..53825d3e 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -4,6 +4,7 @@ use std::fmt; use std::process; +use erg_common::astr::AtomicStr; use erg_common::cache::CacheSet; use erg_common::config::{ErgConfig, Input}; use erg_common::error::{Location, MultiErrorDisplay}; @@ -1220,7 +1221,7 @@ impl CodeGenerator { self.cfg.input.clone(), unary.op.loc(), "", - unary.op.content.clone(), + AtomicStr::from(unary.op.content), )); NOT_IMPLEMENTED } @@ -1267,7 +1268,7 @@ impl CodeGenerator { self.cfg.input.clone(), bin.op.loc(), "", - bin.op.content.clone(), + AtomicStr::from(bin.op.content), )); NOT_IMPLEMENTED } diff --git a/compiler/erg_compiler/context/hint.rs b/compiler/erg_compiler/context/hint.rs index 38999882..1bdb0e71 100644 --- a/compiler/erg_compiler/context/hint.rs +++ b/compiler/erg_compiler/context/hint.rs @@ -1,11 +1,15 @@ -use erg_common::Str; +use erg_common::astr::AtomicStr; use erg_type::Type; use crate::context::Context; impl Context { - pub(crate) fn get_type_mismatch_hint(&self, expected: &Type, found: &Type) -> Option { + pub(crate) fn get_type_mismatch_hint( + &self, + expected: &Type, + found: &Type, + ) -> Option { let expected = if let Type::FreeVar(fv) = expected { if fv.is_linked() { fv.crack().clone() @@ -17,7 +21,7 @@ impl Context { expected.clone() }; match (&expected.name()[..], &found.name()[..]) { - ("Eq", "Float") => Some(Str::ever("Float has no equivalence relation defined. you should use `l - r <= Float.EPSILON` instead of `l == r`.")), + ("Eq", "Float") => Some(AtomicStr::ever("Float has no equivalence relation defined. you should use `l - r <= Float.EPSILON` instead of `l == r`.")), _ => None, } } diff --git a/compiler/erg_compiler/context/inquire.rs b/compiler/erg_compiler/context/inquire.rs index eab76aa3..c8530eb6 100644 --- a/compiler/erg_compiler/context/inquire.rs +++ b/compiler/erg_compiler/context/inquire.rs @@ -100,7 +100,7 @@ impl Context { Err(TyCheckError::no_var_error( line!() as usize, obj.loc(), - namespace.clone(), + namespace.into(), ident.inspect(), self.get_similar_name(ident.inspect()), )) @@ -213,7 +213,7 @@ impl Context { Err(TyCheckError::no_var_error( line!() as usize, ident.loc(), - namespace.clone(), + namespace.into(), ident.inspect(), self.get_similar_name(ident.inspect()), )) @@ -269,7 +269,7 @@ impl Context { Err(TyCheckError::no_attr_error( line!() as usize, name.loc(), - namespace.clone(), + namespace.into(), &self_t, name.inspect(), self.get_similar_attr(&self_t, name.inspect()), @@ -308,7 +308,7 @@ impl Context { Err(TyCheckError::no_attr_error( line!() as usize, ident.loc(), - namespace.clone(), + namespace.into(), &t, ident.inspect(), self.get_similar_attr(&t, ident.inspect()), @@ -393,7 +393,7 @@ impl Context { return Err(TyCheckError::singular_no_attr_error( line!() as usize, method_name.loc(), - namespace.clone(), + namespace.into(), obj.__name__().unwrap_or("?"), obj.ref_t(), method_name.inspect(), @@ -404,7 +404,7 @@ impl Context { Err(TyCheckError::no_attr_error( line!() as usize, method_name.loc(), - namespace.clone(), + namespace.into(), obj.ref_t(), method_name.inspect(), self.get_similar_attr(obj.ref_t(), method_name.inspect()), @@ -970,7 +970,7 @@ impl Context { Err(TyCheckError::no_var_error( line!() as usize, name.loc(), - namespace.clone(), + namespace.into(), name.inspect(), self.get_similar_name(name.inspect()), )) @@ -999,7 +999,7 @@ impl Context { Err(TyCheckError::no_attr_error( line!() as usize, name.loc(), - namespace.clone(), + namespace.into(), self_t, name.inspect(), self.get_similar_attr(self_t, name.inspect()), diff --git a/compiler/erg_compiler/context/mod.rs b/compiler/erg_compiler/context/mod.rs index fea2fb12..155acdd9 100644 --- a/compiler/erg_compiler/context/mod.rs +++ b/compiler/erg_compiler/context/mod.rs @@ -17,6 +17,7 @@ use std::fmt; use std::mem; use std::option::Option; // conflicting to Type::Option +use erg_common::astr::AtomicStr; use erg_common::dict::Dict; use erg_common::error::Location; use erg_common::impl_display_from_debug; @@ -476,8 +477,8 @@ impl Context { } #[inline] - pub fn caused_by(&self) -> Str { - self.name.clone() + pub fn caused_by(&self) -> AtomicStr { + AtomicStr::arc(&self.name[..]) } pub(crate) fn grow( diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index d44290c5..f3c210ad 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -1,6 +1,7 @@ use std::fmt::Display; use std::ops::Add; +use erg_common::astr::AtomicStr; use erg_common::color::{GREEN, RED, RESET, YELLOW}; use erg_common::config::Input; use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay}; @@ -96,7 +97,7 @@ pub fn readable_name(name: &str) -> &str { pub struct CompileError { pub core: ErrorCore, pub input: Input, - pub caused_by: Str, + pub caused_by: AtomicStr, } impl From for CompileError { @@ -125,7 +126,7 @@ impl ErrorDisplay for CompileError { } impl CompileError { - pub const fn new(core: ErrorCore, input: Input, caused_by: Str) -> Self { + pub const fn new(core: ErrorCore, input: Input, caused_by: AtomicStr) -> Self { Self { core, input, @@ -191,7 +192,7 @@ impl CompileError { ) } - pub fn feature_error(input: Input, loc: Location, name: &str, caused_by: Str) -> Self { + pub fn feature_error(input: Input, loc: Location, name: &str, caused_by: AtomicStr) -> Self { Self::new( ErrorCore::new( 0, @@ -233,7 +234,7 @@ impl CompileError { #[derive(Debug)] pub struct TyCheckError { pub core: ErrorCore, - pub caused_by: Str, + pub caused_by: AtomicStr, } impl ErrorDisplay for TyCheckError { @@ -252,7 +253,7 @@ impl ErrorDisplay for TyCheckError { } impl TyCheckError { - pub const fn new(core: ErrorCore, caused_by: Str) -> Self { + pub const fn new(core: ErrorCore, caused_by: AtomicStr) -> Self { Self { core, caused_by } } @@ -282,7 +283,7 @@ impl TyCheckError { ) } - pub fn feature_error(errno: usize, loc: Location, name: &str, caused_by: Str) -> Self { + pub fn feature_error(errno: usize, loc: Location, name: &str, caused_by: AtomicStr) -> Self { Self::new( ErrorCore::new( errno, @@ -300,12 +301,12 @@ impl TyCheckError { ) } - pub fn syntax_error>( + pub fn syntax_error>( errno: usize, loc: Location, - caused_by: Str, + caused_by: AtomicStr, desc: S, - hint: Option, + hint: Option, ) -> Self { Self::new( ErrorCore::new(errno, SyntaxError, loc, desc, hint), @@ -313,7 +314,12 @@ impl TyCheckError { ) } - pub fn duplicate_decl_error(errno: usize, loc: Location, caused_by: Str, name: &str) -> Self { + pub fn duplicate_decl_error( + errno: usize, + loc: Location, + caused_by: AtomicStr, + name: &str, + ) -> Self { let name = readable_name(name); Self::new( ErrorCore::new( @@ -326,7 +332,7 @@ impl TyCheckError { "traditional_chinese" => format!("{name}已聲明"), "english" => format!("{name} is already declared"), ), - Option::::None, + Option::::None, ), caused_by, ) @@ -335,7 +341,7 @@ impl TyCheckError { pub fn duplicate_definition_error( errno: usize, loc: Location, - caused_by: Str, + caused_by: AtomicStr, name: &str, ) -> Self { let name = readable_name(name); @@ -350,7 +356,7 @@ impl TyCheckError { "traditional_chinese" => format!("{name}已定義"), "english" => format!("{name} is already defined"), ), - Option::::None, + Option::::None, ), caused_by, ) @@ -359,7 +365,7 @@ impl TyCheckError { pub fn violate_decl_error( errno: usize, loc: Location, - caused_by: Str, + caused_by: AtomicStr, name: &str, spec_t: &Type, found_t: &Type, @@ -376,13 +382,18 @@ impl TyCheckError { "traditional_chinese" => format!("{name}被聲明為{GREEN}{spec_t}{RESET},但分配了一個{RED}{found_t}{RESET}對象"), "english" => format!("{name} was declared as {GREEN}{spec_t}{RESET}, but an {RED}{found_t}{RESET} object is assigned"), ), - Option::::None, + Option::::None, ), caused_by, ) } - pub fn no_type_spec_error(errno: usize, loc: Location, caused_by: Str, name: &str) -> Self { + pub fn no_type_spec_error( + errno: usize, + loc: Location, + caused_by: AtomicStr, + name: &str, + ) -> Self { let name = readable_name(name); Self::new( ErrorCore::new( @@ -404,7 +415,7 @@ impl TyCheckError { pub fn no_var_error( errno: usize, loc: Location, - caused_by: Str, + caused_by: AtomicStr, name: &str, similar_name: Option<&Str>, ) -> Self { @@ -439,7 +450,7 @@ impl TyCheckError { pub fn no_attr_error( errno: usize, loc: Location, - caused_by: Str, + caused_by: AtomicStr, obj_t: &Type, name: &str, similar_name: Option<&Str>, @@ -474,7 +485,7 @@ impl TyCheckError { pub fn singular_no_attr_error( errno: usize, loc: Location, - caused_by: Str, + caused_by: AtomicStr, obj_name: &str, obj_t: &Type, name: &str, @@ -511,7 +522,7 @@ impl TyCheckError { errno: usize, callee: &C, param_ts: impl Iterator, - caused_by: Str, + caused_by: AtomicStr, ) -> Self { let param_ts = fmt_iter(param_ts); Self::new( @@ -539,12 +550,12 @@ impl TyCheckError { pub fn type_mismatch_error( errno: usize, loc: Location, - caused_by: Str, + caused_by: AtomicStr, name: &str, expect: &Type, found: &Type, candidates: Option>, - hint: Option, + hint: Option, ) -> Self { Self::new( ErrorCore::new( @@ -566,7 +577,7 @@ impl TyCheckError { pub fn return_type_error( errno: usize, loc: Location, - caused_by: Str, + caused_by: AtomicStr, name: &str, expect: &Type, found: &Type, @@ -591,7 +602,7 @@ impl TyCheckError { pub fn uninitialized_error( errno: usize, loc: Location, - caused_by: Str, + caused_by: AtomicStr, name: &str, t: &Type, ) -> Self { @@ -615,7 +626,7 @@ impl TyCheckError { pub fn argument_error( errno: usize, loc: Location, - caused_by: Str, + caused_by: AtomicStr, expect: usize, found: usize, ) -> Self { @@ -636,7 +647,7 @@ impl TyCheckError { ) } - pub fn match_error(errno: usize, loc: Location, caused_by: Str, expr_t: &Type) -> Self { + pub fn match_error(errno: usize, loc: Location, caused_by: AtomicStr, expr_t: &Type) -> Self { Self::new( ErrorCore::new( errno, @@ -654,7 +665,7 @@ impl TyCheckError { ) } - pub fn infer_error(errno: usize, loc: Location, caused_by: Str, expr: &str) -> Self { + pub fn infer_error(errno: usize, loc: Location, caused_by: AtomicStr, expr: &str) -> Self { Self::new( ErrorCore::new( errno, @@ -680,7 +691,7 @@ impl TyCheckError { Self::new(ErrorCore::unreachable(fn_name, line), "".into()) } - pub fn reassign_error(errno: usize, loc: Location, caused_by: Str, name: &str) -> Self { + pub fn reassign_error(errno: usize, loc: Location, caused_by: AtomicStr, name: &str) -> Self { let name = readable_name(name); Self::new( ErrorCore::new( @@ -703,7 +714,7 @@ impl TyCheckError { errno: usize, loc: Location, callee_name: &str, - caused_by: Str, + caused_by: AtomicStr, params_len: usize, pos_args_len: usize, kw_args_len: usize, @@ -750,7 +761,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" errno: usize, loc: Location, callee_name: &str, - caused_by: Str, + caused_by: AtomicStr, missing_len: usize, missing_params: Vec, ) -> Self { @@ -776,7 +787,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" errno: usize, loc: Location, callee_name: &str, - caused_by: Str, + caused_by: AtomicStr, arg_name: &str, ) -> Self { let name = readable_name(callee_name); @@ -801,7 +812,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" errno: usize, loc: Location, callee_name: &str, - caused_by: Str, + caused_by: AtomicStr, param_name: &str, ) -> Self { let name = readable_name(callee_name); @@ -822,7 +833,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" ) } - pub fn unused_warning(errno: usize, loc: Location, name: &str, caused_by: Str) -> Self { + pub fn unused_warning(errno: usize, loc: Location, name: &str, caused_by: AtomicStr) -> Self { let name = readable_name(name); Self::new( ErrorCore::new( @@ -847,7 +858,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" rhs_t: &Type, lhs_loc: Option, rhs_loc: Option, - caused_by: Str, + caused_by: AtomicStr, ) -> Self { let loc = match (lhs_loc, rhs_loc) { (Some(l), Some(r)) => Location::pair(l, r), @@ -878,7 +889,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" rhs_t: &Type, lhs_loc: Option, rhs_loc: Option, - caused_by: Str, + caused_by: AtomicStr, ) -> Self { let loc = match (lhs_loc, rhs_loc) { (Some(l), Some(r)) => Location::pair(l, r), @@ -909,7 +920,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" sup_t: &Type, sub_loc: Option, sup_loc: Option, - caused_by: Str, + caused_by: AtomicStr, ) -> Self { let loc = match (sub_loc, sup_loc) { (Some(l), Some(r)) => Location::pair(l, r), @@ -938,7 +949,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" errno: usize, lhs: &Predicate, rhs: &Predicate, - caused_by: Str, + caused_by: AtomicStr, ) -> Self { Self::new( ErrorCore::new( @@ -957,7 +968,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" ) } - pub fn has_effect>(errno: usize, expr: &Expr, caused_by: S) -> Self { + pub fn has_effect>(errno: usize, expr: &Expr, caused_by: S) -> Self { Self::new( ErrorCore::new( errno, @@ -975,7 +986,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" ) } - pub fn move_error>( + pub fn move_error>( errno: usize, name: &str, name_loc: Location, @@ -1014,7 +1025,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" pub fn visibility_error( errno: usize, loc: Location, - caused_by: Str, + caused_by: AtomicStr, name: &str, vis: Visibility, ) -> Self { @@ -1051,7 +1062,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" ) } - pub fn not_const_expr(errno: usize, loc: Location, caused_by: Str) -> Self { + pub fn not_const_expr(errno: usize, loc: Location, caused_by: AtomicStr) -> Self { Self::new( ErrorCore::new( errno, @@ -1069,7 +1080,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}" ) } - pub fn override_error>( + pub fn override_error>( errno: usize, name: &str, name_loc: Location, @@ -1106,7 +1117,12 @@ passed keyword args: {RED}{kw_args_len}{RESET}" ) } - pub fn inheritance_error(errno: usize, class: String, loc: Location, caused_by: Str) -> Self { + pub fn inheritance_error( + errno: usize, + class: String, + loc: Location, + caused_by: AtomicStr, + ) -> Self { Self::new( ErrorCore::new( errno, diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index d3bdf656..f183a91c 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -1,6 +1,7 @@ //! implements `ASTLowerer`. //! //! ASTLowerer(ASTからHIRへの変換器)を実装 +use erg_common::astr::AtomicStr; use erg_common::config::{ErgConfig, Input}; use erg_common::error::{Location, MultiErrorDisplay}; use erg_common::traits::{Locational, Runnable, Stream}; @@ -17,7 +18,7 @@ use erg_parser::Parser; use erg_type::constructors::{array, array_mut, free_var, func, mono, poly, proc, quant}; use erg_type::free::Constraint; use erg_type::typaram::TyParam; -use erg_type::value::{TypeObj, ValueObj}; +use erg_type::value::{GenTypeObj, TypeObj, ValueObj}; use erg_type::{HasType, ParamTy, Type}; use crate::context::{ClassDefType, Context, ContextKind, RegistrationMode}; @@ -30,34 +31,6 @@ use crate::link::Linker; use crate::varinfo::VarKind; use Visibility::*; -/// HACK: Cannot be methodized this because a reference has been taken immediately before. -macro_rules! check_inheritable { - ($self: ident, $type_obj: expr, $sup_class: expr, $sub_sig: expr) => { - match $type_obj.require_or_sup.as_ref() { - TypeObj::Generated(gen) => { - if let Some(impls) = gen.impls.as_ref() { - if !impls.contains_intersec(&mono("InheritableType")) { - $self.errs.push(LowerError::inheritance_error( - line!() as usize, - $sup_class.to_string(), - $sup_class.loc(), - $sub_sig.ident().inspect().clone(), - )); - } - } else { - $self.errs.push(LowerError::inheritance_error( - line!() as usize, - $sup_class.to_string(), - $sup_class.loc(), - $sub_sig.ident().inspect().clone(), - )); - } - } - _ => {} - } - }; -} - pub struct ASTLowererRunner { cfg: ErgConfig, lowerer: ASTLowerer, @@ -186,7 +159,7 @@ impl ASTLowerer { Err(LowerError::syntax_error( 0, expr.loc(), - self.ctx.name.clone(), + AtomicStr::arc(&self.ctx.name[..]), switch_lang!( "japanese" => format!("式の評価結果(: {})が使われていません", expr.ref_t()), "simplified_chinese" => format!("表达式评估结果(: {})未使用", expr.ref_t()), @@ -237,7 +210,7 @@ impl ASTLowerer { return Err(LowerError::syntax_error( line!() as usize, elem.loc(), - self.ctx.name.clone(), + AtomicStr::arc(&self.ctx.name[..]), switch_lang!( "japanese" => "配列の要素は全て同じ型である必要があります", "simplified_chinese" => "数组元素必须全部是相同类型", @@ -750,7 +723,7 @@ impl ASTLowerer { self.errs.push(LowerError::duplicate_definition_error( line!() as usize, newly_defined_name.loc(), - methods.name.clone(), + methods.name.clone().into(), newly_defined_name.inspect(), )); } else { @@ -782,7 +755,7 @@ impl ASTLowerer { .args .get_left_or_key("Super") .unwrap(); - check_inheritable!(self, type_obj, sup_type, &hir_def.sig); + Self::check_inheritable(&mut self.errs, type_obj, sup_type, &hir_def.sig); // vi.t.non_default_params().unwrap()[0].typ().clone() let (__new__, need_to_gen_new) = if let (Some(dunder_new_vi), Some(new_vi)) = ( ctx.get_current_scope_var("__new__"), @@ -804,6 +777,34 @@ impl ASTLowerer { )) } + /// HACK: Cannot be methodized this because `&self` has been taken immediately before. + fn check_inheritable( + errs: &mut LowerErrors, + type_obj: &GenTypeObj, + sup_class: &hir::Expr, + sub_sig: &hir::Signature, + ) { + if let TypeObj::Generated(gen) = type_obj.require_or_sup.as_ref() { + if let Some(impls) = gen.impls.as_ref() { + if !impls.contains_intersec(&mono("InheritableType")) { + errs.push(LowerError::inheritance_error( + line!() as usize, + sup_class.to_string(), + sup_class.loc(), + sub_sig.ident().inspect().into(), + )); + } + } else { + errs.push(LowerError::inheritance_error( + line!() as usize, + sup_class.to_string(), + sup_class.loc(), + sub_sig.ident().inspect().into(), + )); + } + } + } + fn check_override(&mut self, class: &Type, ctx: &Context) { if let Some(sups) = self.ctx.get_nominal_super_type_ctxs(class) { for (sup_t, sup) in sups.skip(1) { diff --git a/compiler/erg_parser/error.rs b/compiler/erg_parser/error.rs index d4345879..bd1b207e 100644 --- a/compiler/erg_parser/error.rs +++ b/compiler/erg_parser/error.rs @@ -1,10 +1,10 @@ //! defines `ParseError` and others. //! //! パーサーが出すエラーを定義 +use erg_common::astr::AtomicStr; use erg_common::config::Input; use erg_common::error::{ErrorCore, ErrorDisplay, ErrorKind::*, Location, MultiErrorDisplay}; use erg_common::traits::Stream; -use erg_common::Str; use erg_common::{impl_stream_for_wrapper, switch_lang}; #[derive(Debug)] @@ -65,20 +65,20 @@ impl LexError { )) } - pub fn syntax_error>( + pub fn syntax_error>( errno: usize, loc: Location, desc: S, - hint: Option, + hint: Option, ) -> Self { Self::new(ErrorCore::new(errno, SyntaxError, loc, desc, hint)) } - pub fn syntax_warning>( + pub fn syntax_warning>( errno: usize, loc: Location, desc: S, - hint: Option, + hint: Option, ) -> Self { Self::new(ErrorCore::new(errno, SyntaxWarning, loc, desc, hint)) } diff --git a/compiler/erg_type/deserialize.rs b/compiler/erg_type/deserialize.rs index aca1df1a..1b47d006 100644 --- a/compiler/erg_type/deserialize.rs +++ b/compiler/erg_type/deserialize.rs @@ -2,6 +2,7 @@ use std::process; use std::string::FromUtf8Error; +use erg_common::astr::AtomicStr; use erg_common::cache::CacheSet; use erg_common::config::{ErgConfig, Input}; use erg_common::error::{ErrorCore, ErrorKind, Location}; @@ -18,8 +19,8 @@ use crate::{HasType, Type}; #[derive(Debug)] pub struct DeserializeError { pub errno: usize, - pub caused_by: Str, - pub desc: Str, + pub caused_by: AtomicStr, + pub desc: AtomicStr, } impl From for DeserializeError { @@ -41,13 +42,17 @@ impl From for ErrorCore { ErrorKind::ImportError, Location::Unknown, err.desc, - Option::::None, + Option::::None, ) } } impl DeserializeError { - pub fn new, T: Into>(errno: usize, caused_by: S, desc: T) -> Self { + pub fn new, T: Into>( + errno: usize, + caused_by: S, + desc: T, + ) -> Self { Self { errno, caused_by: caused_by.into(),