feat: let Shared: Send + Sync

This commit is contained in:
Shunsuke Shibayama 2023-05-27 20:41:28 +09:00
parent 4d9800716b
commit 0e42ab03ca
18 changed files with 197 additions and 174 deletions

9
Cargo.lock generated
View file

@ -117,10 +117,13 @@ dependencies = [
name = "erg_common"
version = "0.6.13"
dependencies = [
"backtrace",
"backtrace-on-stack-overflow",
"crossterm",
"hermit-abi",
"libc",
"once_cell",
"parking_lot",
"winapi",
]
@ -276,6 +279,12 @@ dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "parking_lot"
version = "0.12.1"

View file

@ -4,11 +4,11 @@ use serde_json::Value;
use erg_common::config::{ErgConfig, Input};
use erg_common::dict::Dict;
use erg_common::env::erg_pystd_path;
use erg_common::env::ERG_PYSTD_PATH;
use erg_common::impl_u8_enum;
use erg_common::python_util::BUILTIN_PYTHON_MODS;
use erg_common::set::Set;
use erg_common::shared::AtomicShared;
use erg_common::shared::Shared;
use erg_common::traits::Locational;
use erg_compiler::artifact::{BuildRunnable, Buildable};
@ -174,7 +174,7 @@ impl<'b> CompletionOrderSetter<'b> {
}
}
type Cache = AtomicShared<Dict<String, Vec<CompletionItem>>>;
type Cache = Shared<Dict<String, Vec<CompletionItem>>>;
#[derive(Debug)]
pub struct CompletionCache {
@ -296,7 +296,7 @@ fn load_modules(cfg: ErgConfig, cache: Cache) {
if cache.get("<module>").is_none() {
cache.insert("<module>".into(), module_completions());
}
let std_path = erg_pystd_path().display().to_string().replace('\\', "/");
let std_path = ERG_PYSTD_PATH.display().to_string().replace('\\', "/");
for (path, entry) in shared.py_mod_cache.iter() {
let dir = entry.module.context.local_dir();
let mod_name = path.display().to_string().replace('\\', "/");
@ -316,7 +316,7 @@ fn load_modules(cfg: ErgConfig, cache: Cache) {
impl CompletionCache {
pub fn new(cfg: ErgConfig) -> Self {
let cache = AtomicShared::new(Dict::default());
let cache = Shared::new(Dict::default());
let clone = cache.clone();
std::thread::spawn(move || {
crate::_log!("load_modules");

View file

@ -12,7 +12,7 @@ use lsp_types::{
};
use erg_common::dict::Dict;
use erg_common::shared::AtomicShared;
use erg_common::shared::Shared;
use erg_common::traits::DequeStream;
use erg_compiler::erg_parser::lex::Lexer;
use erg_compiler::erg_parser::token::{Token, TokenStream};
@ -50,13 +50,13 @@ impl FileCacheEntry {
/// This struct can save changes in real-time & incrementally.
#[derive(Debug, Clone)]
pub struct FileCache {
pub files: AtomicShared<Dict<NormalizedUrl, FileCacheEntry>>,
pub files: Shared<Dict<NormalizedUrl, FileCacheEntry>>,
}
impl FileCache {
pub fn new() -> Self {
Self {
files: AtomicShared::new(Dict::new()),
files: Shared::new(Dict::new()),
}
}

View file

@ -14,7 +14,7 @@ use serde_json::Value;
use erg_common::config::ErgConfig;
use erg_common::dict::Dict;
use erg_common::env::erg_path;
use erg_common::env::ERG_PATH;
use erg_common::normalize_path;
use erg_compiler::artifact::{BuildRunnable, IncompleteArtifact};
@ -224,7 +224,7 @@ impl<Checker: BuildRunnable> Server<Checker> {
comp_cache: CompletionCache::new(cfg.copy()),
cfg,
home: normalize_path(std::env::current_dir().unwrap_or_default()),
erg_path: erg_path(), // already normalized
erg_path: ERG_PATH.clone(), // already normalized
client_capas: ClientCapabilities::default(),
disabled_features: vec![],
opt_features: vec![],

View file

@ -33,7 +33,10 @@ version = "0.3"
features = ["consoleapi"]
[dependencies]
backtrace = "0.3"
once_cell = "1.17"
crossterm = { optional = true, version = "0.25.0" }
parking_lot = "0.12"
[lib]
path = "lib.rs"

View file

@ -1,15 +1,15 @@
use std::borrow::{Borrow, ToOwned};
use std::cell::RefCell;
use std::hash::Hash;
use std::sync::Arc;
use std::thread::LocalKey;
use crate::dict::Dict;
use crate::set::Set;
use crate::shared::Shared;
use crate::{ArcArray, Str};
#[derive(Debug)]
pub struct CacheSet<T: ?Sized>(RefCell<Set<Arc<T>>>);
pub struct CacheSet<T: ?Sized>(Shared<Set<Arc<T>>>);
impl<T: ?Sized> Default for CacheSet<T> {
fn default() -> Self {
@ -19,7 +19,7 @@ impl<T: ?Sized> Default for CacheSet<T> {
impl<T: ?Sized> CacheSet<T> {
pub fn new() -> Self {
Self(RefCell::new(Set::new()))
Self(Shared::new(Set::new()))
}
}
@ -72,6 +72,6 @@ impl<T: Hash + Eq> CacheSet<T> {
}
}
pub struct CacheDict<K, V: ?Sized>(RefCell<Dict<K, Arc<V>>>);
pub struct CacheDict<K, V: ?Sized>(Shared<Dict<K, Arc<V>>>);
pub struct GlobalCacheDict<K: 'static, V: ?Sized + 'static>(LocalKey<RefCell<CacheDict<K, V>>>);
pub struct GlobalCacheDict<K: 'static, V: ?Sized + 'static>(LocalKey<Shared<CacheDict<K, V>>>);

View file

@ -11,7 +11,7 @@ use std::process;
use std::str::FromStr;
use crate::consts::ERG_MODE;
use crate::env::{erg_py_external_lib_path, erg_pystd_path, erg_std_path, python_site_packages};
use crate::env::{ERG_EXTERNAL_LIB_PATH, ERG_PYSTD_PATH, ERG_STD_PATH, PYTHON_SITE_PACKAGES};
use crate::help_messages::{command_message, mode_message, OPTIONS};
use crate::levenshtein::get_similar_name;
use crate::pathutil::add_postfix_foreach;
@ -581,12 +581,12 @@ impl Input {
pub fn resolve_real_path(&self, path: &Path) -> Option<PathBuf> {
if let Ok(path) = self.resolve_local(path) {
Some(path)
} else if let Ok(path) = erg_std_path()
} else if let Ok(path) = ERG_STD_PATH
.join(format!("{}.er", path.display()))
.canonicalize()
{
Some(normalize_path(path))
} else if let Ok(path) = erg_std_path()
} else if let Ok(path) = ERG_STD_PATH
.join(format!("{}", path.display()))
.join("__init__.er")
.canonicalize()
@ -612,13 +612,12 @@ impl Input {
if let Ok(path) = self.resolve_local_decl(path) {
Some(path)
} else {
let py_roots = [erg_pystd_path, erg_py_external_lib_path];
for root in py_roots {
if let Some(path) = Self::resolve_std_decl_path(root(), path) {
for root in [ERG_PYSTD_PATH.clone(), ERG_EXTERNAL_LIB_PATH.clone()] {
if let Some(path) = Self::resolve_std_decl_path(root, path) {
return Some(path);
}
}
for site_packages in python_site_packages() {
for site_packages in PYTHON_SITE_PACKAGES.clone() {
if let Some(path) = Self::resolve_site_pkgs_decl_path(site_packages, path) {
return Some(path);
}

View file

@ -1,6 +1,8 @@
use std::env::var;
use std::path::{Path, PathBuf};
use once_cell::sync::Lazy;
use crate::normalize_path;
use crate::python_util::get_sys_path;
use crate::style::colors::*;
@ -66,43 +68,19 @@ fn _python_site_packages() -> impl Iterator<Item = PathBuf> {
})
}
thread_local! {
pub static ERG_PATH: PathBuf = normalize_path(_erg_path());
pub static ERG_STD_PATH: PathBuf = normalize_path(_erg_std_path());
pub static ERG_STD_DECL_PATH: PathBuf = normalize_path(_erg_std_decl_path());
pub static ERG_PYSTD_PATH: PathBuf = normalize_path(_erg_pystd_path());
pub static ERG_EXTERNAL_LIB_PATH: PathBuf = normalize_path(_erg_external_lib_path());
pub static PYTHON_SITE_PACKAGES: Vec<PathBuf> = _python_site_packages().collect();
}
pub fn erg_path() -> PathBuf {
ERG_PATH.with(|s| s.clone())
}
pub fn erg_std_path() -> PathBuf {
ERG_STD_PATH.with(|s| s.clone())
}
pub fn erg_std_decl_path() -> PathBuf {
ERG_STD_DECL_PATH.with(|s| s.clone())
}
pub fn erg_pystd_path() -> PathBuf {
ERG_PYSTD_PATH.with(|s| s.clone())
}
pub fn erg_py_external_lib_path() -> PathBuf {
ERG_EXTERNAL_LIB_PATH.with(|s| s.clone())
}
pub fn python_site_packages() -> Vec<PathBuf> {
PYTHON_SITE_PACKAGES.with(|s| s.clone())
}
pub static ERG_PATH: Lazy<PathBuf> = Lazy::new(|| normalize_path(_erg_path()));
pub static ERG_STD_PATH: Lazy<PathBuf> = Lazy::new(|| normalize_path(_erg_std_path()));
pub static ERG_STD_DECL_PATH: Lazy<PathBuf> = Lazy::new(|| normalize_path(_erg_std_decl_path()));
pub static ERG_PYSTD_PATH: Lazy<PathBuf> = Lazy::new(|| normalize_path(_erg_pystd_path()));
pub static ERG_EXTERNAL_LIB_PATH: Lazy<PathBuf> =
Lazy::new(|| normalize_path(_erg_external_lib_path()));
pub static PYTHON_SITE_PACKAGES: Lazy<Vec<PathBuf>> =
Lazy::new(|| _python_site_packages().collect());
pub fn is_std_decl_path(path: &Path) -> bool {
path.starts_with(erg_pystd_path())
|| path.starts_with(erg_std_decl_path())
|| path.starts_with(erg_py_external_lib_path())
path.starts_with(ERG_PYSTD_PATH.as_path())
|| path.starts_with(ERG_STD_DECL_PATH.as_path())
|| path.starts_with(ERG_EXTERNAL_LIB_PATH.as_path())
}
pub fn is_pystd_main_module(path: &Path) -> bool {
@ -113,6 +91,6 @@ pub fn is_pystd_main_module(path: &Path) -> bool {
} else {
path.pop();
}
let pystd_path = erg_pystd_path();
path == pystd_path
// let pystd_path = erg_pystd_path();
path == ERG_PYSTD_PATH.as_path()
}

View file

@ -1,21 +1,17 @@
use crate::shared::Shared;
thread_local! {
static VAR_ID: Shared<usize> = Shared::new(0);
}
use once_cell::sync::Lazy;
pub static VAR_ID: Lazy<Shared<usize>> = Lazy::new(|| Shared::new(0));
pub fn fresh_varname() -> String {
VAR_ID.with(|id| {
*id.borrow_mut() += 1;
let i = *id.borrow();
*VAR_ID.borrow_mut() += 1;
let i = *VAR_ID.borrow();
format!("%v{i}")
})
}
pub fn fresh_param_name() -> String {
VAR_ID.with(|id| {
*id.borrow_mut() += 1;
let i = *id.borrow();
*VAR_ID.borrow_mut() += 1;
let i = *VAR_ID.borrow();
format!("%p{i}")
})
}

View file

@ -1,10 +1,13 @@
use std::cell::{Ref, RefCell, RefMut};
// use std::cell::{Ref, RefCell, RefMut};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::rc::Rc;
use std::sync::{Arc, Mutex, MutexGuard};
// use std::rc::Rc;
pub use parking_lot::{
MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard,
};
use std::sync::Arc;
#[derive(Debug)]
/*#[derive(Debug)]
pub struct Shared<T: ?Sized>(Rc<RefCell<T>>);
impl<T: PartialEq> PartialEq for Shared<T> {
@ -108,14 +111,14 @@ impl<T: Clone> Shared<T> {
pub fn clone_inner(&self) -> T {
self.borrow().clone()
}
}
}*/
#[derive(Debug)]
pub struct AtomicShared<T: ?Sized>(Arc<Mutex<T>>);
pub struct Shared<T: ?Sized>(Arc<RwLock<T>>);
impl<T: PartialEq> PartialEq for AtomicShared<T>
impl<T: PartialEq> PartialEq for Shared<T>
where
Mutex<T>: PartialEq,
RwLock<T>: PartialEq,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
@ -123,35 +126,35 @@ where
}
}
impl<T: ?Sized> Clone for AtomicShared<T> {
fn clone(&self) -> AtomicShared<T> {
impl<T: ?Sized> Clone for Shared<T> {
fn clone(&self) -> Shared<T> {
Self(Arc::clone(&self.0))
}
}
impl<T: Eq> Eq for AtomicShared<T> where Mutex<T>: Eq {}
impl<T: Eq> Eq for Shared<T> where RwLock<T>: Eq {}
impl<T: Hash> Hash for AtomicShared<T> {
impl<T: Hash> Hash for Shared<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.borrow_mut().hash(state);
}
}
impl<T: Default> Default for AtomicShared<T> {
impl<T: Default> Default for Shared<T> {
fn default() -> Self {
Self::new(Default::default())
}
}
impl<T: fmt::Display> fmt::Display for AtomicShared<T> {
impl<T: fmt::Display> fmt::Display for Shared<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.borrow_mut())
}
}
impl<T> AtomicShared<T> {
impl<T> Shared<T> {
pub fn new(t: T) -> Self {
Self(Arc::new(Mutex::new(t)))
Self(Arc::new(RwLock::new(t)))
}
#[inline]
@ -160,27 +163,56 @@ impl<T> AtomicShared<T> {
Ok(mutex) => mutex,
Err(_rc) => panic!("unwrapping failed"),
};
Mutex::into_inner(mutex).unwrap()
RwLock::into_inner(mutex)
}
}
impl<T: ?Sized> AtomicShared<T> {
impl<T: ?Sized> Shared<T> {
#[inline]
pub fn copy(&self) -> Self {
Self(self.0.clone())
}
#[inline]
pub fn borrow_mut(&self) -> MutexGuard<'_, T> {
self.0.lock().unwrap()
pub fn borrow(&self) -> RwLockReadGuard<'_, T> {
println!("borrowing {}", std::any::type_name::<T>());
let res = self.0.read();
println!("borrowed successfully");
res
}
#[inline]
pub fn borrow_mut(&self) -> RwLockWriteGuard<'_, T> {
println!("borrowing mut {}", std::any::type_name::<T>());
let res = self.0.write();
println!("borrowed mut successfully");
res
}
pub fn get_mut(&mut self) -> Option<&mut T> {
Arc::get_mut(&mut self.0).map(|mutex| mutex.get_mut().unwrap())
Arc::get_mut(&mut self.0).map(|mutex| mutex.get_mut())
}
pub fn as_ptr(&self) -> *mut T {
Arc::as_ptr(&self.0) as *mut T
}
pub fn can_borrow(&self) -> bool {
self.0.try_read().is_some()
}
pub fn can_borrow_mut(&self) -> bool {
self.0.try_write().is_some()
}
/// # Safety
/// don't call this except you need to handle cyclic references.
pub unsafe fn force_unlock_write(&self) {
self.0.force_unlock_write();
}
}
impl<T: Clone> AtomicShared<T> {
impl<T: Clone> Shared<T> {
#[inline]
pub fn clone_inner(&self) -> T {
self.borrow_mut().clone()

View file

@ -1,5 +1,5 @@
use std::cell::RefCell;
use std::thread::LocalKey;
// use std::cell::RefCell;
// use std::thread::LocalKey;
#[cfg(not(feature = "full-repl"))]
use std::io::{stdin, BufRead, BufReader};
@ -261,57 +261,52 @@ impl StdinReader {
}
}
thread_local! {
static READER: RefCell<StdinReader> = RefCell::new(StdinReader{
static READER: crate::shared::RwLock<StdinReader> = crate::shared::RwLock::new(StdinReader {
block_begin: 1,
lineno: 1,
buf: vec![],
#[cfg(feature = "full-repl")]
history_input_position: 1,
indent: 1
indent: 1,
});
}
#[derive(Debug)]
pub struct GlobalStdin(LocalKey<RefCell<StdinReader>>);
pub struct GlobalStdin(&'static crate::shared::RwLock<StdinReader>);
pub static GLOBAL_STDIN: GlobalStdin = GlobalStdin(READER);
pub static GLOBAL_STDIN: GlobalStdin = GlobalStdin(&READER);
impl GlobalStdin {
pub fn read(&'static self) -> String {
self.0.with(|s| s.borrow_mut().read())
self.0.write().read()
}
pub fn reread(&'static self) -> String {
self.0.with(|s| s.borrow().reread())
self.0.read().reread()
}
pub fn reread_lines(&'static self, ln_begin: usize, ln_end: usize) -> Vec<String> {
self.0
.with(|s| s.borrow_mut().reread_lines(ln_begin, ln_end))
self.0.read().reread_lines(ln_begin, ln_end)
}
pub fn lineno(&'static self) -> usize {
self.0.with(|s| s.borrow().lineno)
self.0.read().lineno
}
pub fn block_begin(&'static self) -> usize {
self.0.with(|s| s.borrow().block_begin)
self.0.read().block_begin
}
pub fn set_block_begin(&'static self, n: usize) {
self.0.with(|s| s.borrow_mut().block_begin = n);
self.0.write().block_begin = n;
}
pub fn set_indent(&'static self, n: usize) {
self.0.with(|s| s.borrow_mut().indent = n as u16);
self.0.write().indent = n as u16;
}
pub fn insert_whitespace(&'static self, whitespace: &str) {
self.0.with(|s| {
if let Some(line) = s.borrow_mut().last_line() {
if let Some(line) = self.0.write().last_line() {
line.insert_str(0, whitespace);
}
})
}
}

View file

@ -8,7 +8,7 @@ use crate::ty::codeobj::{CodeObj, CodeObjFlags, MakeFunctionFlags};
use crate::ty::value::GenTypeObj;
use erg_common::cache::CacheSet;
use erg_common::config::{ErgConfig, Input};
use erg_common::env::erg_std_path;
use erg_common::env::ERG_STD_PATH;
use erg_common::error::{ErrorDisplay, Location};
use erg_common::opcode::{CommonOpcode, CompareOp};
use erg_common::opcode308::Opcode308;
@ -3120,7 +3120,7 @@ impl PyCodeGenerator {
);
self.emit_load_name_instr(Identifier::private("#path"));
self.emit_load_method_instr(Identifier::public("append"));
self.emit_load_const(erg_std_path().to_str().unwrap());
self.emit_load_const(ERG_STD_PATH.to_str().unwrap());
self.emit_call_instr(1, Method);
self.stack_dec();
self.emit_pop_top();

View file

@ -15,6 +15,7 @@ use std::path::PathBuf;
use erg_common::config::ErgConfig;
use erg_common::consts::{DEBUG_MODE, ERG_MODE, PYTHON_MODE};
use erg_common::dict;
use erg_common::env::{ERG_PYSTD_PATH, ERG_STD_DECL_PATH};
use erg_common::error::Location;
use erg_common::fresh::fresh_varname;
#[allow(unused_imports)]
@ -513,11 +514,11 @@ const KW_OFFSET: &str = "offset";
const KW_WHENCE: &str = "whence";
pub fn builtins_path() -> PathBuf {
erg_common::env::erg_pystd_path().join("builtins.d.er")
ERG_PYSTD_PATH.join("builtins.d.er")
}
pub fn std_decl_path() -> PathBuf {
erg_common::env::erg_std_decl_path()
ERG_STD_DECL_PATH.clone()
}
impl Context {
@ -772,7 +773,8 @@ impl Context {
);
self.consts.insert(name.clone(), val);
for impl_trait in ctx.super_traits.iter() {
if let Some(impls) = self.trait_impls().get_mut(&impl_trait.qual_name()) {
if self.trait_impls().get(&impl_trait.qual_name()).is_some() {
let mut impls = self.trait_impls().get_mut(&impl_trait.qual_name());
impls.insert(TraitImpl::new(t.clone(), impl_trait.clone()));
} else {
self.trait_impls().register(
@ -848,7 +850,8 @@ impl Context {
}
self.consts.insert(name.clone(), val);
for impl_trait in ctx.super_traits.iter() {
if let Some(impls) = self.trait_impls().get_mut(&impl_trait.qual_name()) {
if self.trait_impls().get(&impl_trait.qual_name()).is_some() {
let mut impls = self.trait_impls().get_mut(&impl_trait.qual_name());
impls.insert(TraitImpl::new(t.clone(), impl_trait.clone()));
} else {
self.trait_impls().register(
@ -912,7 +915,12 @@ impl Context {
}
}
if let ContextKind::GluePatch(tr_impl) = &ctx.kind {
if let Some(impls) = self.trait_impls().get_mut(&tr_impl.sup_trait.qual_name()) {
if self
.trait_impls()
.get(&tr_impl.sup_trait.qual_name())
.is_some()
{
let mut impls = self.trait_impls().get_mut(&tr_impl.sup_trait.qual_name());
impls.insert(tr_impl.clone());
} else {
self.trait_impls()

View file

@ -1653,7 +1653,8 @@ impl Context {
self.decls.insert(name.clone(), vi);
self.consts.insert(name.clone(), val);
for impl_trait in ctx.super_traits.iter() {
if let Some(impls) = self.trait_impls().get_mut(&impl_trait.qual_name()) {
if self.trait_impls().get(&impl_trait.qual_name()).is_some() {
let mut impls = self.trait_impls().get_mut(&impl_trait.qual_name());
impls.insert(TraitImpl::new(t.clone(), impl_trait.clone()));
} else {
self.trait_impls().register(
@ -1733,7 +1734,8 @@ impl Context {
self.consts
.insert(name.clone(), ValueObj::Type(TypeObj::Generated(gen)));
for impl_trait in ctx.super_traits.iter() {
if let Some(impls) = self.trait_impls().get_mut(&impl_trait.qual_name()) {
if self.trait_impls().get(&impl_trait.qual_name()).is_some() {
let mut impls = self.trait_impls().get_mut(&impl_trait.qual_name());
impls.insert(TraitImpl::new(t.clone(), impl_trait.clone()));
} else {
self.trait_impls().register(

View file

@ -1892,12 +1892,18 @@ impl ASTLowerer {
trait_loc: &impl Locational,
) -> LowerResult<()> {
// TODO: polymorphic trait
if let Some(impls) = self
if self
.module
.context
.trait_impls()
.get_mut(&trait_.qual_name())
.get(&trait_.qual_name())
.is_some()
{
let mut impls = self
.module
.context
.trait_impls()
.get_mut(&trait_.qual_name());
impls.insert(TraitImpl::new(class.clone(), trait_.clone()));
} else {
self.module.context.trait_impls().register(

View file

@ -2,7 +2,7 @@ use std::borrow::Borrow;
use std::fmt;
use std::hash::Hash;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use erg_common::config::ErgConfig;
use erg_common::dict::Dict;
@ -32,7 +32,7 @@ impl ModId {
pub struct ModuleEntry {
pub id: ModId, // builtin == 0, __main__ == 1
pub hir: Option<HIR>,
pub module: Rc<ModuleContext>,
pub module: Arc<ModuleContext>,
}
impl fmt::Display for ModuleEntry {
@ -50,7 +50,7 @@ impl ModuleEntry {
Self {
id,
hir,
module: Rc::new(ctx),
module: Arc::new(ctx),
}
}
@ -58,7 +58,7 @@ impl ModuleEntry {
Self {
id: ModId::builtin(),
hir: None,
module: Rc::new(ctx),
module: Arc::new(ctx),
}
}
@ -189,7 +189,7 @@ impl SharedModuleCache {
ref_.get_mut(path)
}
pub fn get_ctx<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<Rc<ModuleContext>>
pub fn get_ctx<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<Arc<ModuleContext>>
where
PathBuf: Borrow<Q>,
{
@ -236,7 +236,7 @@ impl SharedModuleCache {
for path in self.keys() {
self.remove(&path);
}
self.register(builtin_path, None, Rc::try_unwrap(builtin.module).unwrap());
self.register(builtin_path, None, Arc::try_unwrap(builtin.module).unwrap());
}
pub fn rename_path(&self, path: &PathBuf, new: PathBuf) {

View file

@ -4,7 +4,7 @@ use std::hash::Hash;
use erg_common::dict::Dict;
use erg_common::set::Set;
use erg_common::shared::Shared;
use erg_common::shared::{MappedRwLockWriteGuard, RwLockWriteGuard, Shared};
use erg_common::Str;
use crate::context::TraitImpl;
@ -84,12 +84,13 @@ impl SharedTraitImpls {
ref_.get(path)
}
pub fn get_mut<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> Option<&mut Set<TraitImpl>>
pub fn get_mut<Q: Eq + Hash + ?Sized>(&self, path: &Q) -> MappedRwLockWriteGuard<Set<TraitImpl>>
where
Str: Borrow<Q>,
{
let ref_ = unsafe { self.0.as_ptr().as_mut().unwrap() };
ref_.get_mut(path)
// let ref_ = unsafe { self.0.as_ptr().as_mut().unwrap() };
// ref_.get_mut(path)
RwLockWriteGuard::map(self.0.borrow_mut(), |tis| tis.get_mut(path).unwrap())
}
pub fn register(&self, name: Str, impls: Set<TraitImpl>) {

View file

@ -1,8 +1,9 @@
use std::cell::{Ref, RefMut};
// use std::cell::{Ref, RefMut};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem;
use erg_common::fresh::VAR_ID;
use erg_common::shared::Shared;
use erg_common::traits::{LimitedDisplay, StructuralEq};
use erg_common::Str;
@ -17,10 +18,6 @@ pub type Id = usize;
/// HACK: see doc/compiler/inference.md for details
pub const GENERIC_LEVEL: usize = usize::MAX;
thread_local! {
static UNBOUND_ID: Shared<usize> = Shared::new(0);
}
pub trait HasLevel {
fn level(&self) -> Option<Level>;
fn set_level(&self, lev: Level);
@ -429,14 +426,12 @@ impl<T> FreeKind<T> {
}
pub fn new_unbound(lev: Level, constraint: Constraint) -> Self {
UNBOUND_ID.with(|id| {
*id.borrow_mut() += 1;
*VAR_ID.borrow_mut() += 1;
Self::Unbound {
id: *id.borrow(),
id: *VAR_ID.borrow(),
lev,
constraint,
}
})
}
pub const fn named_unbound(name: Str, lev: Level, constraint: Constraint) -> Self {
@ -601,10 +596,10 @@ impl<T: LimitedDisplay> LimitedDisplay for Free<T> {
}
impl<T> Free<T> {
pub fn borrow(&self) -> Ref<'_, FreeKind<T>> {
pub fn borrow(&self) -> erg_common::shared::RwLockReadGuard<'_, FreeKind<T>> {
self.0.borrow()
}
pub fn borrow_mut(&self) -> RefMut<'_, FreeKind<T>> {
pub fn borrow_mut(&self) -> erg_common::shared::RwLockWriteGuard<'_, FreeKind<T>> {
self.0.borrow_mut()
}
/// very unsafe, use `force_replace` instead whenever possible
@ -620,8 +615,9 @@ impl<T> Free<T> {
return;
}
unsafe {
*self.0.as_ptr() = new;
self.0.force_unlock_write();
}
*self.0.borrow_mut() = new;
}
pub fn can_borrow(&self) -> bool {
self.0.can_borrow()
@ -650,7 +646,7 @@ impl Free<TyParam> {
}
}
impl<T: StructuralEq + CanbeFree + Clone + Default> StructuralEq for Free<T> {
impl<T: StructuralEq + CanbeFree + Clone + Default + fmt::Debug> StructuralEq for Free<T> {
fn structural_eq(&self, other: &Self) -> bool {
if let (Some((l, r)), Some((l2, r2))) = (self.get_subsup(), other.get_subsup()) {
self.dummy_link();
@ -736,14 +732,12 @@ impl<T> Free<T> {
}
pub fn new_unbound(level: Level, constraint: Constraint) -> Self {
UNBOUND_ID.with(|id| {
*id.borrow_mut() += 1;
*VAR_ID.borrow_mut() += 1;
Self(Shared::new(FreeKind::unbound(
*id.borrow(),
*VAR_ID.borrow(),
level,
constraint,
)))
})
}
pub fn new_named_unbound(name: Str, level: Level, constraint: Constraint) -> Self {
@ -766,8 +760,8 @@ impl<T> Free<T> {
/// returns linked type (panic if self is unbounded)
/// NOTE: check by `.is_linked` before call
pub fn crack(&self) -> Ref<'_, T> {
Ref::map(self.borrow(), |f| match f {
pub fn crack(&self) -> erg_common::shared::MappedRwLockReadGuard<'_, T> {
erg_common::shared::RwLockReadGuard::map(self.borrow(), |f| match f {
FreeKind::Linked(t) | FreeKind::UndoableLinked { t, .. } => t,
FreeKind::Unbound { .. } | FreeKind::NamedUnbound { .. } => {
panic!("the value is unbounded")
@ -775,8 +769,8 @@ impl<T> Free<T> {
})
}
pub fn crack_constraint(&self) -> Ref<'_, Constraint> {
Ref::map(self.borrow(), |f| match f {
pub fn crack_constraint(&self) -> erg_common::shared::MappedRwLockReadGuard<'_, Constraint> {
erg_common::shared::RwLockReadGuard::map(self.borrow(), |f| match f {
FreeKind::Linked(_) | FreeKind::UndoableLinked { .. } => panic!("the value is linked"),
FreeKind::Unbound { constraint, .. } | FreeKind::NamedUnbound { constraint, .. } => {
constraint
@ -814,7 +808,7 @@ impl<T> Free<T> {
}
}
impl<T: Clone> Free<T> {
impl<T: Clone + fmt::Debug> Free<T> {
/// SAFETY: use `Type/TyParam::link` instead of this.
/// This method may cause circular references.
pub(super) fn link(&self, to: &T) {
@ -871,7 +865,7 @@ impl<T: Clone> Free<T> {
let prev = *previous.clone();
self.force_replace(prev);
}
_other => panic!("cannot undo"),
_other => panic!("cannot undo: {_other:?}"),
}
}
@ -920,7 +914,7 @@ impl<T: Clone> Free<T> {
}
}
impl<T: Default + Clone> Free<T> {
impl<T: Default + Clone + fmt::Debug> Free<T> {
pub fn dummy_link(&self) {
self.forced_undoable_link(&T::default());
}