From ab30d379973041b93a3bc7de15c5cf00d58df27c Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Sat, 24 Oct 2026 03:54:19 -0400 Subject: [PATCH 1/2] chore: resolve SonarCloud maintainability issues (storytold/wordcraft#4083) * chore: resolve SonarCloud maintainability issues * fix: restore compiling refactors, revert behaviour changes, run cargo fmt - fontdb::norm: keep the closure for filter (char::is_alphanumeric takes self, not &self, so it does not fit Iterator::filter). - story.rs: write_mark_rpr needs &mut self (rev_attrs, rpr_change). - Revert the viewport meta change and the return 0 added to workspace_version/sha256, which changed behaviour or masked failures. - cargo fmt. Co-Authored-By: Claude Opus 5.5 * Import Document in odt page_parts after dropping glob re-export * fix: apply_kind_properties binds ContentControl; cell_ref keeps char closures * fix(engine): pass case helpers by value (clippy needless borrows) --------- Co-authored-by: Claude Opus 5.5 Co-authored-by: Dylan Taylor --- crates/proof/src/it/grammar.rs | 2 +- crates/proof/src/lib.rs | 4 ++-- crates/proof/src/ru/mod.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/proof/src/it/grammar.rs b/crates/proof/src/it/grammar.rs index 235012bd..46302936 100644 --- a/crates/proof/src/it/grammar.rs +++ b/crates/proof/src/it/grammar.rs @@ -276,7 +276,7 @@ fn e_apostrophe(text: &str, ws: &[(usize, usize)], v: &mut Vec) { } let mut after = text.get(*b..).unwrap_or("").chars(); let Some(ap) = after.next().filter(|&c| is_apostrophe(c)) else { continue }; - let ends = after.next().is_none_or(|c| c.is_whitespace()); + let ends = after.next().is_none_or(char::is_whitespace); let quoted = text.get(..*a).and_then(|t| t.chars().next_back()).is_some_and(|c| is_apostrophe(c) || c == '‘'); if ends && !quoted { v.push(issue(*a, *b + ap.len_utf8(), "«È» si scrive con l'accento, non con l'apostrofo".into(), vec!["È".into()])); diff --git a/crates/proof/src/lib.rs b/crates/proof/src/lib.rs index 0ab16529..38f274c7 100644 --- a/crates/proof/src/lib.rs +++ b/crates/proof/src/lib.rs @@ -320,7 +320,7 @@ const COMMON: &str = "a an the and or but if of to in on at by for with from as const EXTRA_EN: &str = include_str!("../../../assets/spelling/en-extra.txt"); fn extra_words() -> &'static HashSet<&'static str> { - static E: OnceLock> = OnceLock::new(); + static E: OnceLock> = OnceLock::new(); E.get_or_init(|| EXTRA_EN.lines().map(str::trim).filter(|l| !l.is_empty() && !l.starts_with('#')).collect()) } @@ -889,7 +889,7 @@ fn grammar_en(text: &str, capital_first: bool) -> Vec { if gap == " " && (w0 == "an" || w0 == "An") && w1.chars().next().is_some_and(|c| c.is_alphabetic() && !"aeiouAEIOUhH".contains(c)) - && !w1.chars().all(|c| c.is_uppercase()) + && !w1.chars().all(char::is_uppercase) { v.push(Issue { start: *a0, diff --git a/crates/proof/src/ru/mod.rs b/crates/proof/src/ru/mod.rs index c29bbc7c..50faac38 100644 --- a/crates/proof/src/ru/mod.rs +++ b/crates/proof/src/ru/mod.rs @@ -109,7 +109,7 @@ pub fn has_dictionary() -> bool { /// Is `c` a letter of the Cyrillic script (the only one the Russian dictionary covers)? pub(crate) fn is_cyrillic(c: char) -> bool { - matches!(c, '\u{0400}'..='\u{04FF}' | '\u{0500}'..='\u{052F}') + matches!(c, '\u{0400}'..='\u{052F}') } /// Particles joined to a word with a hyphen (`кто-то`, `где-нибудь`, `давай-ка`, `всё-таки`, From a75a9383b350b1ffb78150a8aa090ca9d748a9cb Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Sat, 24 Oct 2026 04:33:12 -0400 Subject: [PATCH 2/2] Sonar S1612: pass PoisonError::into_inner instead of a closure (storytold/wordcraft#4102) Co-authored-by: Claude Sonnet 5.5 --- crates/proof/src/cs/mod.rs | 10 +++++----- crates/proof/src/hr/mod.rs | 8 ++++---- crates/proof/src/hunspell.rs | 12 ++++++------ crates/proof/src/id/mod.rs | 8 ++++---- crates/proof/src/it/mod.rs | 8 ++++---- crates/proof/src/lib.rs | 20 +++++++++++--------- crates/proof/src/pl/mod.rs | 8 ++++---- crates/proof/src/pt/mod.rs | 8 ++++---- crates/proof/src/ru/mod.rs | 10 +++++----- crates/proof/src/tr/mod.rs | 8 ++++---- 10 files changed, 51 insertions(+), 49 deletions(-) diff --git a/crates/proof/src/cs/mod.rs b/crates/proof/src/cs/mod.rs index 7a910c72..fee7c561 100644 --- a/crates/proof/src/cs/mod.rs +++ b/crates/proof/src/cs/mod.rs @@ -31,11 +31,11 @@ const NAMES: &[&str] = &["cs_CZ", "cs-CZ", "cs"]; /// [`install_dictionary`], or an empty one when none is available (Czech spelling is off /// then; see [`has_dictionary`]). pub fn dictionary() -> Arc { - if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).dict.as_ref() { + if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).dict.as_ref() { return d.clone(); } let loaded = Arc::new(load_installed()); - let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner()); + let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner); // Another thread (or an install) may have filled it meanwhile: that one wins. slot.dict.get_or_insert(loaded).clone() } @@ -56,7 +56,7 @@ fn load_installed() -> AffixDict { /// UTF-8), for example one the user picked. On error the current dictionary stays. pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { let d = AffixDict::from_hunspell(aff, dic, &[])?; - let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner()); + let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner); slot.dict = Some(Arc::new(d)); slot.in_memory = true; Ok(()) @@ -65,7 +65,7 @@ pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { /// Forget the loaded dictionary, so the next check looks for an installed one again (after /// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed). pub fn reload_dictionary() { - let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner()); + let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner); slot.dict = None; slot.in_memory = false; } @@ -75,7 +75,7 @@ pub fn reload_dictionary() { /// none. A dictionary given with [`install_dictionary`] has no file and isn't reported, even if a /// matching file also happens to exist. pub fn installed_path() -> Option { - if DICT.read().unwrap_or_else(|e| e.into_inner()).in_memory { + if DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).in_memory { return None; } crate::hunspell::find(NAMES).map(|(_, dic)| dic) diff --git a/crates/proof/src/hr/mod.rs b/crates/proof/src/hr/mod.rs index 1c89b4fa..ee9d58e9 100644 --- a/crates/proof/src/hr/mod.rs +++ b/crates/proof/src/hr/mod.rs @@ -25,11 +25,11 @@ const NAMES: &[&str] = &["hr_HR", "hr-HR", "hr"]; /// [`install_dictionary`], or an empty one when none is available (Croatian spelling is off /// then; see [`has_dictionary`]). pub fn dictionary() -> Arc { - if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() { + if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() { return d.clone(); } let loaded = Arc::new(load_installed()); - let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner()); + let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner); // Another thread (or an install) may have filled it meanwhile: that one wins. slot.get_or_insert(loaded).clone() } @@ -51,14 +51,14 @@ fn load_installed() -> AffixDict { /// UTF-8), for example one the user picked. On error the current dictionary stays. pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { let d = AffixDict::from_hunspell(aff, dic, &[])?; - *DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d)); + *DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d)); Ok(()) } /// Forget the loaded dictionary, so the next check looks for an installed one again (after /// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed). pub fn reload_dictionary() { - *DICT.write().unwrap_or_else(|e| e.into_inner()) = None; + *DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None; } /// The `.dic` file of the Hunspell `hr_HR` dictionary found in the dictionaries folder or the diff --git a/crates/proof/src/hunspell.rs b/crates/proof/src/hunspell.rs index 6f0cab1d..0e4303be 100644 --- a/crates/proof/src/hunspell.rs +++ b/crates/proof/src/hunspell.rs @@ -27,7 +27,7 @@ static LOAD_ERRORS: RwLock> = RwLock::new(Vec::ne /// Remember (or, for `Ok`, forget) why the dictionary `key` found at `dic` failed to load, and /// hand the result back unchanged. pub fn note_load(key: &str, dic: &Path, result: Result) -> Result { - let mut errors = LOAD_ERRORS.write().unwrap_or_else(|e| e.into_inner()); + let mut errors = LOAD_ERRORS.write().unwrap_or_else(std::sync::PoisonError::into_inner); errors.retain(|(k, _, _)| k != key); if let Err(e) = &result { errors.push((key.to_string(), dic.to_path_buf(), e.clone())); @@ -37,19 +37,19 @@ pub fn note_load(key: &str, dic: &Path, result: Result) -> Result< /// Forget the load error of the dictionary `key` (none found, or it is about to be searched for again). pub fn clear_load_error(key: &str) { - LOAD_ERRORS.write().unwrap_or_else(|e| e.into_inner()).retain(|(k, _, _)| k != key); + LOAD_ERRORS.write().unwrap_or_else(std::sync::PoisonError::into_inner).retain(|(k, _, _)| k != key); } /// The `.dic` file and the reason of the last failed load of the dictionary `key`, if any. pub fn load_error(key: &str) -> Option<(PathBuf, String)> { - LOAD_ERRORS.read().unwrap_or_else(|e| e.into_inner()).iter().find(|(k, _, _)| k == key).map(|(_, p, e)| (p.clone(), e.clone())) + LOAD_ERRORS.read().unwrap_or_else(std::sync::PoisonError::into_inner).iter().find(|(k, _, _)| k == key).map(|(_, p, e)| (p.clone(), e.clone())) } /// Search `dir` before the system locations (a "dictionaries folder" setting); `None` clears it. /// Takes effect for dictionaries not loaded yet. pub fn set_dictionary_dir(dir: Option) { - *EXTRA_DIR.write().unwrap_or_else(|e| e.into_inner()) = dir; - LOAD_ERRORS.write().unwrap_or_else(|e| e.into_inner()).clear(); // they belong to the old search path + *EXTRA_DIR.write().unwrap_or_else(std::sync::PoisonError::into_inner) = dir; + LOAD_ERRORS.write().unwrap_or_else(std::sync::PoisonError::into_inner).clear(); // they belong to the old search path } /// The LibreOffice extension directories a Hunspell dictionary name may live in: LibreOffice's @@ -67,7 +67,7 @@ fn lo_ext_dirs(name: &str) -> Vec { /// language is being searched for, adds LibreOffice's extension folders for it (`dict-pt-BR`). pub fn search_dirs(lo_exts: Option<&[String]>) -> Vec { let mut dirs: Vec = Vec::new(); - if let Some(d) = EXTRA_DIR.read().unwrap_or_else(|e| e.into_inner()).clone() { + if let Some(d) = EXTRA_DIR.read().unwrap_or_else(std::sync::PoisonError::into_inner).clone() { dirs.push(d); } if cfg!(target_arch = "wasm32") { diff --git a/crates/proof/src/id/mod.rs b/crates/proof/src/id/mod.rs index 09771e85..012babc0 100644 --- a/crates/proof/src/id/mod.rs +++ b/crates/proof/src/id/mod.rs @@ -30,11 +30,11 @@ const CLITICS: &[&str] = &["se", "nya", "ku", "mu", "lah", "kah", "pun"]; /// [`install_dictionary`], or an empty one when none is available (Indonesian spelling is off /// then; see [`has_dictionary`]). pub fn dictionary() -> Arc { - if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() { + if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() { return d.clone(); } let loaded = Arc::new(load_installed()); - let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner()); + let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner); // Another thread (or an install) may have filled it meanwhile: that one wins. slot.get_or_insert(loaded).clone() } @@ -55,14 +55,14 @@ fn load_installed() -> AffixDict { /// UTF-8), for example one the user picked. On error the current dictionary stays. pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { let d = AffixDict::from_hunspell(aff, dic, &[])?; - *DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d)); + *DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d)); Ok(()) } /// Forget the loaded dictionary, so the next check looks for an installed one again (after /// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed). pub fn reload_dictionary() { - *DICT.write().unwrap_or_else(|e| e.into_inner()) = None; + *DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None; } /// The `.dic` file of the Hunspell `id_ID` dictionary found in the dictionaries folder or the diff --git a/crates/proof/src/it/mod.rs b/crates/proof/src/it/mod.rs index 0e11ccaa..027006a6 100644 --- a/crates/proof/src/it/mod.rs +++ b/crates/proof/src/it/mod.rs @@ -34,11 +34,11 @@ const NAMES: &[&str] = &["it_IT", "it_CH", "it-IT", "it"]; /// [`install_dictionary`], or an empty one when none is available (Italian spelling is off /// then; see [`has_dictionary`]). pub fn dictionary() -> Arc { - if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() { + if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() { return d.clone(); } let loaded = Arc::new(load_installed()); - let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner()); + let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner); // Another thread (or an install) may have filled it meanwhile: that one wins. slot.get_or_insert(loaded).clone() } @@ -59,14 +59,14 @@ fn load_installed() -> AffixDict { /// UTF-8), for example one the user picked. On error the current dictionary stays. pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { let d = AffixDict::from_hunspell(aff, dic, &[])?; - *DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d)); + *DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d)); Ok(()) } /// Forget the loaded dictionary, so the next check looks for an installed one again (after /// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed). pub fn reload_dictionary() { - *DICT.write().unwrap_or_else(|e| e.into_inner()) = None; + *DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None; } /// The `.dic` file of the Hunspell `it_IT` dictionary found in the dictionaries folder or the diff --git a/crates/proof/src/lib.rs b/crates/proof/src/lib.rs index 38f274c7..de596782 100644 --- a/crates/proof/src/lib.rs +++ b/crates/proof/src/lib.rs @@ -116,14 +116,14 @@ static DICTIONARY_GENERATION: AtomicU64 = AtomicU64::new(0); /// Add a word to the user dictionary ("Add to Dictionary"). It applies to every language. pub fn add_word(w: &str) { - if user_words().write().unwrap_or_else(|e| e.into_inner()).insert(w.to_lowercase()) { + if user_words().write().unwrap_or_else(std::sync::PoisonError::into_inner).insert(w.to_lowercase()) { DICTIONARY_GENERATION.fetch_add(1, Ordering::Relaxed); } } /// Take a word out of the user dictionary (File › Options › Proofing). Returns whether it was there. pub fn remove_word(w: &str) -> bool { - let removed = user_words().write().unwrap_or_else(|e| e.into_inner()).remove(&w.to_lowercase()); + let removed = user_words().write().unwrap_or_else(std::sync::PoisonError::into_inner).remove(&w.to_lowercase()); if removed { DICTIONARY_GENERATION.fetch_add(1, Ordering::Relaxed); } @@ -138,7 +138,7 @@ fn ignored_words() -> &'static RwLock> { /// Ignore a word everywhere until the app closes ("Ignore All"). Unlike [`add_word`] it isn't /// part of the user dictionary: it is never listed, saved or loaded, as in Word. pub fn ignore_word(w: &str) { - if ignored_words().write().unwrap_or_else(|e| e.into_inner()).insert(w.to_lowercase()) { + if ignored_words().write().unwrap_or_else(std::sync::PoisonError::into_inner).insert(w.to_lowercase()) { DICTIONARY_GENERATION.fetch_add(1, Ordering::Relaxed); } } @@ -198,13 +198,13 @@ pub fn dictionary_generation() -> u64 { /// Is `lower` (a lower-case word) in the user dictionary or ignored? pub(crate) fn in_user_dictionary(lower: &str) -> bool { - user_words().read().unwrap_or_else(|e| e.into_inner()).contains(lower) - || ignored_words().read().unwrap_or_else(|e| e.into_inner()).contains(lower) + user_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).contains(lower) + || ignored_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).contains(lower) } /// Words in the user dictionary. pub fn user_dictionary() -> Vec { - let mut v: Vec = user_words().read().unwrap_or_else(|e| e.into_inner()).iter().cloned().collect(); + let mut v: Vec = user_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).iter().cloned().collect(); v.sort(); v } @@ -252,7 +252,7 @@ fn read_dictionary_file(path: &std::path::Path) -> Vec { /// never a panic and never an error that stops startup. Returns the words added. pub fn load_user_dictionary(path: &std::path::Path) -> Vec { let words = read_dictionary_file(path); - let mut set = user_words().write().unwrap_or_else(|e| e.into_inner()); + let mut set = user_words().write().unwrap_or_else(std::sync::PoisonError::into_inner); let mut added = Vec::new(); for w in words { if set.len() >= MAX_CUSTOM_WORDS { @@ -278,7 +278,7 @@ pub fn save_user_dictionary(path: &std::path::Path, removed: &[String]) -> std:: let removed: HashSet = removed.iter().map(|w| w.to_lowercase()).collect(); let on_disk = read_dictionary_file(path); { - let mut set = user_words().write().unwrap_or_else(|e| e.into_inner()); + let mut set = user_words().write().unwrap_or_else(std::sync::PoisonError::into_inner); let mut changed = false; for w in on_disk { if set.len() >= MAX_CUSTOM_WORDS { @@ -334,7 +334,9 @@ fn known_core(w: &str) -> bool { if base_known(d, w) || COMMON.split(' ').any(|c| c == w) { return true; } - if user_words().read().unwrap_or_else(|e| e.into_inner()).contains(w) || ignored_words().read().unwrap_or_else(|e| e.into_inner()).contains(w) { + if user_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).contains(w) + || ignored_words().read().unwrap_or_else(std::sync::PoisonError::into_inner).contains(w) + { return true; } // Inflections. diff --git a/crates/proof/src/pl/mod.rs b/crates/proof/src/pl/mod.rs index 76fa455e..18c968fe 100644 --- a/crates/proof/src/pl/mod.rs +++ b/crates/proof/src/pl/mod.rs @@ -33,11 +33,11 @@ const NAMES: &[&str] = &["pl_PL", "pl-PL", "pl"]; /// [`install_dictionary`], or an empty one when none is available (Polish spelling is off then; /// see [`has_dictionary`]). pub fn dictionary() -> Arc { - if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() { + if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() { return d.clone(); } let loaded = Arc::new(load_installed()); - let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner()); + let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner); // Another thread (or an install) may have filled it meanwhile: that one wins. slot.get_or_insert(loaded).clone() } @@ -58,14 +58,14 @@ fn load_installed() -> AffixDict { /// for example one the user picked. On error the current dictionary stays. pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { let d = AffixDict::from_hunspell(aff, dic, &[])?; - *DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d)); + *DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d)); Ok(()) } /// Forget the loaded dictionary, so the next check looks for an installed one again (after /// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed). pub fn reload_dictionary() { - *DICT.write().unwrap_or_else(|e| e.into_inner()) = None; + *DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None; } /// The `.dic` file of the installed Polish dictionary, searching the dictionaries folder and diff --git a/crates/proof/src/pt/mod.rs b/crates/proof/src/pt/mod.rs index 3a8b059f..de419825 100644 --- a/crates/proof/src/pt/mod.rs +++ b/crates/proof/src/pt/mod.rs @@ -32,11 +32,11 @@ const NAMES: &[&str] = &["pt_BR", "pt-BR", "pt"]; /// [`install_dictionary`], or an empty one when none is available (Portuguese spelling is off /// then; see [`has_dictionary`]). pub fn dictionary() -> Arc { - if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() { + if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() { return d.clone(); } let loaded = Arc::new(load_installed()); - let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner()); + let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner); // Another thread (or an install) may have filled it meanwhile: that one wins. slot.get_or_insert(loaded).clone() } @@ -57,14 +57,14 @@ fn load_installed() -> AffixDict { /// UTF-8), for example one the user picked. On error the current dictionary stays. pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { let d = AffixDict::from_hunspell(aff, dic, &[])?; - *DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d)); + *DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d)); Ok(()) } /// Forget the loaded dictionary, so the next check looks for an installed one again (after /// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed). pub fn reload_dictionary() { - *DICT.write().unwrap_or_else(|e| e.into_inner()) = None; + *DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None; } /// The `.dic` file of the installed Portuguese dictionary, searching the dictionaries folder and diff --git a/crates/proof/src/ru/mod.rs b/crates/proof/src/ru/mod.rs index 50faac38..c92e2712 100644 --- a/crates/proof/src/ru/mod.rs +++ b/crates/proof/src/ru/mod.rs @@ -52,11 +52,11 @@ const NAMES: &[&str] = &["ru_RU", "ru-RU", "ru"]; /// [`install_dictionary`], or an empty one when none is available (Russian spelling is off then; /// see [`has_dictionary`]). pub fn dictionary() -> Arc { - if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).dict.as_ref() { + if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).dict.as_ref() { return d.clone(); } let loaded = Arc::new(load_installed()); - let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner()); + let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner); // Another thread (or an install) may have filled it meanwhile: that one wins. slot.dict.get_or_insert(loaded).clone() } @@ -77,7 +77,7 @@ fn load_installed() -> AffixDict { /// for example one the user picked. On error the current dictionary stays. pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { let d = AffixDict::from_hunspell(aff, dic, &[])?; - let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner()); + let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner); slot.dict = Some(Arc::new(d)); slot.in_memory = true; Ok(()) @@ -86,7 +86,7 @@ pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { /// Forget the loaded dictionary, so the next check looks for an installed one again (after /// [`crate::hunspell::set_dictionary_dir`] or a dictionary was installed). pub fn reload_dictionary() { - let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner()); + let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner); slot.dict = None; slot.in_memory = false; } @@ -96,7 +96,7 @@ pub fn reload_dictionary() { /// none. A dictionary given with [`install_dictionary`] has no file and isn't reported, even if a /// matching file also happens to exist. pub fn installed_path() -> Option { - if DICT.read().unwrap_or_else(|e| e.into_inner()).in_memory { + if DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).in_memory { return None; } crate::hunspell::find(NAMES).map(|(_, dic)| dic) diff --git a/crates/proof/src/tr/mod.rs b/crates/proof/src/tr/mod.rs index d814dc2a..bcab1546 100644 --- a/crates/proof/src/tr/mod.rs +++ b/crates/proof/src/tr/mod.rs @@ -30,11 +30,11 @@ const NAMES: &[&str] = &["tr_TR", "tr-TR", "tr"]; /// The Turkish dictionary: the installed Hunspell `tr_TR` (read on first use), one given with /// [`install_dictionary`], or an empty one when none is available. pub fn dictionary() -> Arc { - if let Some(d) = DICT.read().unwrap_or_else(|e| e.into_inner()).as_ref() { + if let Some(d) = DICT.read().unwrap_or_else(std::sync::PoisonError::into_inner).as_ref() { return d.clone(); } let loaded = Arc::new(load_installed()); - let mut slot = DICT.write().unwrap_or_else(|e| e.into_inner()); + let mut slot = DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner); slot.get_or_insert(loaded).clone() } @@ -61,13 +61,13 @@ fn load_installed() -> TrDict { /// Use this Turkish dictionary from now on. pub fn install_dictionary(aff: &str, dic: &str) -> Result<(), String> { let d = TrDict::from_hunspell(aff, dic)?; - *DICT.write().unwrap_or_else(|e| e.into_inner()) = Some(Arc::new(d)); + *DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = Some(Arc::new(d)); Ok(()) } /// Reload the dictionary on next check. pub fn reload_dictionary() { - *DICT.write().unwrap_or_else(|e| e.into_inner()) = None; + *DICT.write().unwrap_or_else(std::sync::PoisonError::into_inner) = None; } /// The `.dic` file of the Hunspell `tr_TR` dictionary found in the dictionaries folder or the