From bfedc614b7670b8766576b64afd426c292f8c2ce Mon Sep 17 00:00:00 2001 From: Brent Westbrook <36778786+ntBre@users.noreply.github.com> Date: Wed, 14 Oct 2026 11:56:00 -0400 Subject: [PATCH] Use workspace `rand` and `rust-version` in `ruff_unicode_names2` (#29261) Summary -- This updates `ruff_unicode_names2` and `ruff_unicode_names2_generator` to use our workspace `rand` dependency and `rust-version`, prompted by #29257 and #29359. Bumping the Rust version also introduces a handful of Clippy diagnostic that Clippy was also able to fix automatically. I originally pinned both of these to stay closer to the upstream version, but we've already diverged a bit, and the required changes were quite small anyway, so this seems like the better way to go. This also allows us to drop the `std` feature on `rand`, a transitive dependency on `zerocopy`, and the accompanying allowlist entry for its build script. While I was here, I also switched to our workspace edition, removed unused feature-gated code and unnecessary suppressions, enabled formatting and typo checks, and enabled doctests. These are the changes from `rand` for reference: - https://rust-random.github.io/book/update-0.10.html - https://rust-random.github.io/book/update-0.9.html Test Plan -- Existing tests --------- Co-authored-by: Alex Waygood --- .cargo/deny.toml | 1 - Cargo.lock | 48 +------------------ _typos.toml | 4 +- crates/ruff_unicode_names2/Cargo.toml | 12 +---- crates/ruff_unicode_names2/examples/count.rs | 2 +- crates/ruff_unicode_names2/rustfmt.toml | 2 - crates/ruff_unicode_names2/src/lib.rs | 35 +++----------- .../ruff_unicode_names2_generator/Cargo.toml | 13 ++--- .../rustfmt.toml | 2 - .../src/formatting.rs | 4 +- .../ruff_unicode_names2_generator/src/lib.rs | 19 ++++---- .../ruff_unicode_names2_generator/src/phf.rs | 28 +++-------- 12 files changed, 34 insertions(+), 136 deletions(-) delete mode 100644 crates/ruff_unicode_names2/rustfmt.toml delete mode 100644 crates/ruff_unicode_names2_generator/rustfmt.toml diff --git a/.cargo/deny.toml b/.cargo/deny.toml index 8eea09de68..24b8a1a4c1 100644 --- a/.cargo/deny.toml +++ b/.cargo/deny.toml @@ -73,7 +73,6 @@ allow-build-scripts = [ "windows_x86_64_gnullvm", "windows_x86_64_msvc", "wit-bindgen", - "zerocopy", "zmij", "zstd-safe", "zstd-sys", diff --git a/Cargo.lock b/Cargo.lock index fead3adc68..a07ef6fbbd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2634,15 +2634,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "predicates" version = "3.1.4" @@ -2893,8 +2884,6 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "libc", - "rand_chacha", "rand_core 0.6.4", ] @@ -2909,24 +2898,11 @@ dependencies = [ "rand_core 0.10.0", ] -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.16", -] [[package]] name = "rand_core" @@ -3791,7 +3767,7 @@ name = "ruff_unicode_names2" version = "0.0.17" dependencies = [ "phf 0.11.3", - "rand 0.8.5", + "rand 0.10.2", "ruff_unicode_names2_generator", ] @@ -3800,7 +3776,7 @@ name = "ruff_unicode_names2_generator" version = "0.0.17" dependencies = [ "phf_codegen", - "rand 0.8.5", + "rand 0.10.2", ] [[package]] @@ -5893,26 +5869,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zerocopy" -version = "0.8.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - [[package]] name = "zerofrom" version = "0.1.6" diff --git a/_typos.toml b/_typos.toml index 94af848df4..1eed158b68 100644 --- a/_typos.toml +++ b/_typos.toml @@ -2,8 +2,8 @@ # https://github.com/crate-ci/typos/issues/868 extend-exclude = [ "crates/ty_vendored/vendor/**/*", - "crates/ruff_unicode_names2/**/*", - "crates/ruff_unicode_names2_generator/**/*", + "crates/ruff_unicode_names2/data/NameAliases.txt", + "crates/ruff_unicode_names2/data/UnicodeData.txt", "**/resources/**/*", "**/snapshots/**/*", "crates/ruff_linter/src/rules/flake8_implicit_str_concat/rules/collection_literal.rs", diff --git a/crates/ruff_unicode_names2/Cargo.toml b/crates/ruff_unicode_names2/Cargo.toml index 7984d35713..26afe5ba50 100644 --- a/crates/ruff_unicode_names2/Cargo.toml +++ b/crates/ruff_unicode_names2/Cargo.toml @@ -17,20 +17,10 @@ phf = { workspace = true } ruff_unicode_names2_generator = { workspace = true } [dev-dependencies] -rand = { version = "0.8.5", default-features = false, features = ["std", "std_rng"] } - -[lints.rust] -# Ruff uses std; retain upstream's optional no_std code without enabling it. -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(feature, values("no_std"))'] } - -[lints.clippy] -# Preserve the vendored source. -unnecessary_map_or = "allow" -question_mark = "allow" +rand = { workspace = true } [lib] name = "unicode_names2" # Upstream unit tests, benchmarks, and macro doctests require nightly Rust. test = false -doctest = false bench = false diff --git a/crates/ruff_unicode_names2/examples/count.rs b/crates/ruff_unicode_names2/examples/count.rs index c3c2ccd262..8ef6b9f73a 100644 --- a/crates/ruff_unicode_names2/examples/count.rs +++ b/crates/ruff_unicode_names2/examples/count.rs @@ -12,7 +12,7 @@ use std::char; fn main() { let number = (0u32..0x10FFFF) - .filter(|x| char::from_u32(*x).map_or(false, |c| unicode_names2::name(c).is_some())) + .filter(|x| char::from_u32(*x).is_some_and(|c| unicode_names2::name(c).is_some())) .count(); println!("there are {} named code points", number) diff --git a/crates/ruff_unicode_names2/rustfmt.toml b/crates/ruff_unicode_names2/rustfmt.toml deleted file mode 100644 index 6282619024..0000000000 --- a/crates/ruff_unicode_names2/rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -# Preserve the vendored source formatting. -disable_all_formatting = true diff --git a/crates/ruff_unicode_names2/src/lib.rs b/crates/ruff_unicode_names2/src/lib.rs index 03d5017d8e..a060f527f3 100755 --- a/crates/ruff_unicode_names2/src/lib.rs +++ b/crates/ruff_unicode_names2/src/lib.rs @@ -1,9 +1,7 @@ //! Convert between characters and their standard names. //! //! This crate provides two functions for mapping from a `char` to the -//! name given by the Unicode standard (17.0). There are no runtime -//! requirements so this is usable with only `core` (this requires -//! specifying the `no_std` cargo feature). The tables are heavily +//! name given by the Unicode standard (17.0). The tables are heavily //! compressed, but still large (500KB), and still offer efficient //! `O(1)` look-ups in both directions (more precisely, `O(length of //! name)`). @@ -47,37 +45,24 @@ //! } //! ``` -#![cfg_attr(feature = "no_std", no_std)] #![cfg_attr(test, feature(test))] #![deny(missing_docs, unsafe_code)] -#[cfg(all(test, feature = "no_std"))] -#[macro_use] -extern crate std; - use core::{char, fmt}; use generated::{ - MAX_NAME_LENGTH, PHRASEBOOK_OFFSETS1, PHRASEBOOK_OFFSETS2, PHRASEBOOK_OFFSET_SHIFT, + MAX_NAME_LENGTH, PHRASEBOOK_OFFSET_SHIFT, PHRASEBOOK_OFFSETS1, PHRASEBOOK_OFFSETS2, }; -#[allow(dead_code)] -#[rustfmt::skip] -#[allow(clippy::all)] mod generated { include!(concat!(env!("OUT_DIR"), "/generated.rs")); } -#[allow(dead_code)] -#[rustfmt::skip] -#[allow(clippy::all)] mod generated_phf { include!(concat!(env!("OUT_DIR"), "/generated_phf.rs")); } -#[allow(dead_code)] mod jamo; /// A map of unicode aliases to their corresponding values. /// Generated in generator -#[allow(dead_code)] static ALIASES: phf::Map<&'static [u8], char> = include!(concat!(env!("OUT_DIR"), "/generated_alias.rs")); @@ -363,10 +348,7 @@ pub fn character(search_name: &str) -> Option { _ => return None, } } - let ch = match char::from_u32(v) { - Some(ch) => ch, - None => return None, - }; + let ch = char::from_u32(v)?; // check if the resulting code is indeed in the known ranges if is_cjk_unified_ideograph(ch) { @@ -422,7 +404,7 @@ pub fn character(search_name: &str) -> Option { mod tests { use super::*; use rand::{ - distributions::{Distribution, Standard}, + distr::{Distribution, StandardUniform}, prelude::{SeedableRng, StdRng}, }; use std::char; @@ -616,7 +598,7 @@ mod tests { fn name_10000_invalid(b: &mut Bencher) { // be consistent across runs, but avoid sequential/caching. let mut rng = StdRng::seed_from_u64(0x12345678); - let chars: Vec = Standard + let chars: Vec = StandardUniform .sample_iter(&mut rng) .take(10000) .filter_map(|c| match c { @@ -655,7 +637,7 @@ mod tests { // be consistent across runs, but avoid sequential/caching. let mut rng = StdRng::seed_from_u64(0x12345678); - let names: Vec<_> = Standard + let names: Vec<_> = StandardUniform .sample_iter(&mut rng) .take(10000) .filter_map(name) @@ -669,8 +651,3 @@ mod tests { }) } } - -#[cfg(all(feature = "no_std", not(test)))] -mod std { - pub use core::{clone, fmt, marker}; -} diff --git a/crates/ruff_unicode_names2_generator/Cargo.toml b/crates/ruff_unicode_names2_generator/Cargo.toml index ae4122cb4e..bf93c3d36b 100644 --- a/crates/ruff_unicode_names2_generator/Cargo.toml +++ b/crates/ruff_unicode_names2_generator/Cargo.toml @@ -3,8 +3,8 @@ name = "ruff_unicode_names2_generator" version = "0.0.17" description = "This is an internal component crate of Ruff" authors = { workspace = true } -edition = "2018" -rust-version = "1.65.0" +edition = { workspace = true } +rust-version = { workspace = true } homepage = { workspace = true } documentation = { workspace = true } repository = { workspace = true } @@ -12,14 +12,7 @@ license = "MIT OR Apache-2.0" [dependencies] phf_codegen = { workspace = true } -# Preserve the RNG used by upstream's table generator. -rand = { version = "0.8.5", default-features = false, features = ["std", "std_rng"] } - -[lints.rust] -unexpected_cfgs = { level = "warn", check-cfg = ['cfg(feature, values("timing"))'] } - -[lints.rustdoc] -bare_urls = "allow" +rand = { workspace = true } [lib] name = "unicode_names2_generator" diff --git a/crates/ruff_unicode_names2_generator/rustfmt.toml b/crates/ruff_unicode_names2_generator/rustfmt.toml deleted file mode 100644 index 6282619024..0000000000 --- a/crates/ruff_unicode_names2_generator/rustfmt.toml +++ /dev/null @@ -1,2 +0,0 @@ -# Preserve the vendored source formatting. -disable_all_formatting = true diff --git a/crates/ruff_unicode_names2_generator/src/formatting.rs b/crates/ruff_unicode_names2_generator/src/formatting.rs index ad74c9e577..77305e4815 100644 --- a/crates/ruff_unicode_names2_generator/src/formatting.rs +++ b/crates/ruff_unicode_names2_generator/src/formatting.rs @@ -11,7 +11,7 @@ impl Context { where F: Fn(&T) -> String, { - w!(self, "pub static {}: &'static [{}] = &[", name, ty); + w!(self, "pub static {}: &[{}] = &[", name, ty); let mut width = LINE_LIMIT; for e in elements.iter() { @@ -41,7 +41,7 @@ impl Context { pub fn write_plain_string(&mut self, name: &str, data: &str) { assert!(!data.contains('\\')); - w!(self, "pub static {}: &'static str = \"", name); + w!(self, "pub static {}: &str = \"", name); for chunk in data.as_bytes().chunks(LINE_LIMIT - 6) { w!(self, "\\\n "); diff --git a/crates/ruff_unicode_names2_generator/src/lib.rs b/crates/ruff_unicode_names2_generator/src/lib.rs index d4addc889a..192d1755cb 100644 --- a/crates/ruff_unicode_names2_generator/src/lib.rs +++ b/crates/ruff_unicode_names2_generator/src/lib.rs @@ -1,10 +1,9 @@ use formatting::Context; use std::{ char, cmp, - collections::{hash_map, HashMap}, + collections::{HashMap, hash_map}, fs::{self, File}, - io::{self, prelude::*, BufWriter}, - iter::repeat, + io::{self, BufWriter, prelude::*}, path::Path, }; @@ -156,7 +155,7 @@ fn create_lexicon_and_offsets( // insert the suffixes of this word which saves about // 10KB (we could theoretically insert all substrings, // upto a certain length, but this only saves ~300 - // bytes or so and is noticably slower). + // bytes or so and is noticeably slower). for i in 1..n.len() { if t.insert(n[i..].bytes(), Some(offset + i), true).0 { // once we've found a string that's already @@ -238,7 +237,7 @@ fn bin_data(dat: &[u32]) -> (Vec, Vec, usize) { fn write_codepoint_maps(ctxt: &mut Context, codepoint_names: Vec<(char, &str)>) { let (lexicon_string, mut lexicon_words) = create_lexicon_and_offsets(codepoint_names.clone()); - let num_escapes = (lexicon_words.len() + 255) / 256; + let num_escapes = lexicon_words.len().div_ceil(256); // we reserve the high bit (end of word) and 127,126... for // non-space splits. The high bit saves about 10KB, and doing the @@ -293,9 +292,11 @@ fn write_codepoint_maps(ctxt: &mut Context, codepoint_names: Vec<(char, &str)>) previous_len = len; } - assert!(word_encodings - .insert(word, vec![hi as u32, lo as u32]) - .is_none()); + assert!( + word_encodings + .insert(word, vec![hi as u32, lo as u32]) + .is_none() + ); } // don't forget the last one. lexicon_ordered_lengths.push((lexicon_offsets.len(), previous_len)); @@ -306,7 +307,7 @@ fn write_codepoint_maps(ctxt: &mut Context, codepoint_names: Vec<(char, &str)>) // this is a map from `char` -> the index in phrasebook. it is // currently huge, but it has a lot of 0's, so we compress it // using the binning, below. - let mut phrasebook_offsets = repeat(0).take(0x10FFFF + 1).collect::>(); + let mut phrasebook_offsets: Vec<_> = std::iter::repeat_n(0, 0x10FFFF + 1).collect(); let mut longest_name = 0; for &(cp, name) in codepoint_names.iter() { longest_name = cmp::max(name.len(), longest_name); diff --git a/crates/ruff_unicode_names2_generator/src/phf.rs b/crates/ruff_unicode_names2_generator/src/phf.rs index 67967aef22..25ce118eb0 100644 --- a/crates/ruff_unicode_names2_generator/src/phf.rs +++ b/crates/ruff_unicode_names2_generator/src/phf.rs @@ -1,10 +1,9 @@ //! Computes a perfect hash table using [the CHD //! algorithm](http://cmph.sourceforge.net/papers/esa09.pdf). //! -//! Strongly inspired by https://github.com/sfackler/rust-phf +//! Strongly inspired by -use rand::prelude::{Rng, SeedableRng, SliceRandom, StdRng}; -use std::iter::repeat; +use rand::prelude::{RngExt, SeedableRng, SliceRandom, StdRng}; static NOVAL: char = '\0'; @@ -51,7 +50,7 @@ fn try_phf_table( .collect(); let table_len = hashes.len(); - let buckets_len = (table_len + lambda - 1) / lambda; + let buckets_len = table_len.div_ceil(lambda); // group the elements into buckets of lambda (on average, for a // good hash) based on the suffix of their hash. @@ -67,8 +66,8 @@ fn try_phf_table( // value for `foo` is "just" `map[displace(hash(foo))]`, where // `displace` uses the pair of displacements that we computed // (stored in `disps`). - let mut map = repeat(NOVAL).take(table_len).collect::>(); - let mut disps = repeat((0, 0)).take(buckets_len).collect::>(); + let mut map: Vec<_> = std::iter::repeat_n(NOVAL, table_len).collect(); + let mut disps: Vec<_> = std::iter::repeat_n((0, 0), buckets_len).collect(); // the set of index -> value mappings for the next bucket to be // placed; we need it separate because it may not work, so we may @@ -80,7 +79,7 @@ fn try_phf_table( // having to clear the whole the whole array each time (just // compare against the generation). A u64 won't overflow. let mut generation = 0; - let mut try_map = repeat(0u64).take(table_len).collect::>(); + let mut try_map: Vec<_> = std::iter::repeat_n(0u64, table_len).collect(); // the placed (index, codepoint) pairs of the current bucket, to // be placed into the main map if the whole bucket fits. let mut values_to_add = vec![]; @@ -145,25 +144,12 @@ pub fn create_phf( max_tries: usize, ) -> (u64, Vec<(u32, u32)>, Vec) { let mut rng = StdRng::seed_from_u64(0xf0f0f0f0); - #[cfg(feature = "timing")] - let start = time::Instant::now(); for i in 0..(max_tries) { - #[cfg(feature = "timing")] - let my_start = time::Instant::now(); - #[cfg(feature = "timing")] - println!("PHF #{}: starting {:.2}", i, my_start - start); - #[cfg(not(feature = "timing"))] println!("PHF #{}", i); - let seed = rng.gen(); + let seed = rng.random(); if let Some((disp, map)) = try_phf_table(data, lambda, seed, &mut rng) { - #[cfg(feature = "timing")] - println!( - "PHF took: total {:.2} s, successive {:.2} s", - start.elapsed(), - my_start.elapsed() - ); return (seed, disp, map); } }