From 486b4aa6ff268efa420ec36aca31c1de28003df5 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 12:36:15 +0300 Subject: [PATCH 01/21] refactor: cargo manifests --- Cargo.toml | 131 +++++++++++++++++++++++++++++++++--------- pad/editor/Cargo.toml | 63 ++++++++------------ parser/Cargo.toml | 35 ++++++----- site/Cargo.toml | 63 +++++++------------- tests_ffi/Cargo.toml | 9 ++- 5 files changed, 175 insertions(+), 126 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 731a5f434..754f0907a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,36 +1,111 @@ -[package] +[workspace] +members = ["site", "tests_ffi", "pad/editor", "parser"] + +[workspace.package] categories = ["compilers", "algorithms", "multimedia", "parser-implementations"] -description = "A stack-based array programming language" -documentation = "https://docs.rs/uiua" edition = "2021" keywords = ["uiua", "array", "stack", "language", "apl"] license = "MIT" -name = "uiua" readme = "readme.md" repository = "https://github.com/uiua-lang/uiua" rust-version = "1.82.0" version = "0.17.0-dev.2" +[workspace.lints.clippy] +cargo = {level = "warn", priority = -1} +dbg_macro = "warn" +print_stdout = "warn" +multiple_crate_versions = "allow" + +[workspace.dependencies] +base64 = "0.22.0" +bytemuck = "1.17" +colored = "2" +dashmap = {version = "6", features = ["serde"]} +ecow = {version = "0.2.3", features = ["serde"]} +enum-iterator = "2.1.0" +hound = "3.5.1" +js-sys = "0.3.69" +leptos = "0.6.11" +leptos_router = {version = "0.6.11", features = ["csr"]} +leptos_meta = {version = "0.6.11", features = ["csr"]} +once_cell = "1" +rand = {version = "0.8.5", features = ["small_rng"]} +serde = {version = "1", features = ["derive"]} +serde_json = "1.0.115" +unicode-segmentation = "1.10" +urlencoding = "2" +# NOTE: if you change the wasm-bindgen version, remember to change it in nix/site.nix as well +wasm-bindgen = "=0.2.93" + +[workspace.dependencies.web-sys] +version = "0.3.70" +features = [ + "Clipboard", + "ClipboardEvent", + "CssStyleDeclaration", + "DataTransfer", + "DataTransfer", + "DomRect", + "EventInit", + "File", + "FileList", + "FileReader", + "HtmlAudioElement", + "HtmlBrElement", + "Navigator", + "Node", + "Performance", + "Permissions", + "ResizeObserver", + "ResizeObserverEntry", + "ScrollBehavior", + "ScrollIntoViewOptions", + "ScrollLogicalPosition", + "Selection", + "Storage", + "StorageManager", +] + + +[package] +description = "A stack-based array programming language" +documentation = "https://docs.rs/uiua" +name = "uiua" +categories.workspace = true +edition.workspace = true +keywords.workspace = true +license.workspace = true +readme.workspace = true +repository.workspace = true +rust-version.workspace = true +version.workspace = true + + [dependencies] # Uiua dependencies uiua_parser = {path = "parser", version = "0.17.0-dev.2"} # Core dependencies bitflags = {version = "2", features = ["serde"]} -bytemuck = {version = "1.17", features = ["must_cast", "derive", "extern_crate_alloc"]} -colored = "2" +bytemuck = {workspace = true, features = [ + "must_cast", + "derive", + "extern_crate_alloc", +]} +colored.workspace = true crossbeam-channel = "0.5.12" -dashmap = {version = "6", features = ["serde"]} -ecow = {version = "0.2.3", features = ["serde"]} -enum-iterator = "2.1.0" +dashmap.workspace = true +ecow.workspace = true +enum-iterator.workspace = true indexmap = {version = "2", features = ["serde"]} num_cpus = "1.16.0" -once_cell = "1" +once_cell.workspace = true open = {version = "5", optional = true} parking_lot = "0.12.1" paste = "1.0.14" pathdiff = "0.2.1" -rand = {version = "0.8.5", features = ["small_rng"]} +rand.workspace = true rawrrr = {version = "0.2.1", optional = true} rayon = "1.9.0" regex = "1.10.3" @@ -39,15 +114,15 @@ rustls = {version = "0.23.2", optional = true, default-features = false, feature "tls12", "ring", ]} -serde = {version = "1", features = ["derive", "rc"]} -serde_json = "1" +serde = {workspace = true, features = ["rc"]} +serde_json.workspace = true smallvec = {version = "1.9", features = ["serde", "union", "const_new"]} terminal_size = {version = "0.3.0", optional = true} thread_local = "1" threadpool = "1.8.1" time = {version = "0.3.36", features = ["local-offset"]} trash = {version = "5.2.2", optional = true} -unicode-segmentation = "1.10" +unicode-segmentation.workspace = true viuer = {version = "0.9", optional = true} webpki-roots = {version = "1.0.2", optional = true} @@ -75,13 +150,23 @@ color_quant = {version = "1.1", optional = true} cosmic-text = {version = "0.12.1", optional = true} csv = {version = "1", optional = true} gif = {version = "0.13.1", optional = true} -hound = {version = "3", optional = true} -image = {version = "0.25", optional = true, default-features = false, features = ["bmp", "gif", "ico", "jpeg", "png", "qoi", "webp"]} +hound = {workspace = true, optional = true} +image = {version = "0.25", optional = true, default-features = false, features = [ + "bmp", + "gif", + "ico", + "jpeg", + "png", + "qoi", + "webp", +]} json5 = {version = "0.4.1", optional = true} libffi = {version = "4", optional = true} libloading = {version = "0.8.3", optional = true} nokhwa = {version = "0.10.7", optional = true, features = ["input-native"]} -num-complex = {version = ">=0.4.1", optional = true, default-features = false, features = ["bytemuck"]} +num-complex = {version = ">=0.4.1", optional = true, default-features = false, features = [ + "bytemuck", +]} png = {version = "0.17.16", optional = true} rustfft = {version = "6.2.0", optional = true} rustls-pemfile = {version = "2.1.2", optional = true} @@ -89,8 +174,8 @@ simple_excel_writer = {version = "0.2.0", optional = true} sys-locale = {version = "0.3.1", optional = true} # Web-only dependencies -js-sys = {version = "0.3", optional = true} -wasm-bindgen = {version = "0.2.92", optional = true} +js-sys = {workspace = true, optional = true} +wasm-bindgen = {workspace = true, optional = true} web-sys = {version = "0.3.60", optional = true} # Window dependencies @@ -167,14 +252,6 @@ system = ["libffi?/system"] name = "uiua" required-features = ["binary"] -[workspace] -members = ["site", "tests_ffi", "pad/editor", "parser"] - -[workspace.lints.clippy] -dbg_macro = "warn" -print_stderr = "allow" -print_stdout = "warn" - [lints] workspace = true diff --git a/pad/editor/Cargo.toml b/pad/editor/Cargo.toml index 3cc39adbd..8b47088c7 100644 --- a/pad/editor/Cargo.toml +++ b/pad/editor/Cargo.toml @@ -1,7 +1,14 @@ [package] +description = "Uiua editor" name = "uiua-editor" version = "0.1.0" -edition = "2021" +categories.workspace = true +edition.workspace = true +keywords.workspace = true +license.workspace = true +readme.workspace = true +repository.workspace = true +rust-version.workspace = true [lib] crate-type = ["cdylib", "rlib"] @@ -10,45 +17,21 @@ crate-type = ["cdylib", "rlib"] workspace = true [dependencies] -leptos = { version = "0.6.10", features = ["csr"] } -js-sys = "0.3.69" -web-sys = { version = "0.3.70", features = [ - "Window", - "CustomElementRegistry", - "CssStyleDeclaration", - "DomRect", - "Storage", - "HtmlAudioElement", - "HtmlBrElement", - "Selection", - "Node", - "Clipboard", - "ClipboardEvent", - "DataTransfer", - "Navigator", - "Permissions", - "ScrollIntoViewOptions", - "ScrollBehavior", - "ScrollLogicalPosition", - "StorageManager", - "FileReader", - "EventInit", - "DataTransfer", - "File", - "FileList", - "ResizeObserver", - "ResizeObserverEntry", - "Performance", -] } -base64 = "0.22.0" -leptos_router = {version = "0.6.11", features = ["csr"]} -leptos-use = "0.12.0" -uiua = {path = "../..", default-features = false, features = ["batteries", "web"]} +base64.workspace = true +hound.workspace = true +js-sys.workspace = true +leptos = {workspace = true, features = ["csr"]} +leptos_router.workspace = true +serde_json.workspace = true +unicode-segmentation.workspace = true +urlencoding.workspace = true +wasm-bindgen.workspace = true +web-sys = {workspace = true, features = ["CustomElementRegistry", "Window"]} +uiua = {path = "../..", default-features = false, features = [ + "batteries", + "web", +]} image = "0.25" -unicode-segmentation = "1.10" -urlencoding = "2" -wasm-bindgen = "0.2.93" +leptos-use = "0.12.0" wasm-bindgen-futures = "0.4.43" -hound = "3.5.1" -serde_json = "1.0.115" futures = "0.3.30" diff --git a/parser/Cargo.toml b/parser/Cargo.toml index 152e2f751..e0af76862 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -1,25 +1,30 @@ [package] -categories = ["parser-implementations"] description = "Uiua parser implementation" documentation = "https://docs.rs/uiua_parser" -edition = "2021" -keywords = ["uiua", "array", "stack", "language", "apl"] -license = "MIT" name = "uiua_parser" -repository = "https://github.com/uiua-lang/uiua" -rust-version = "1.82.0" -version = "0.17.0-dev.2" +categories.workspace = true +edition.workspace = true +keywords.workspace = true +license.workspace = true +readme.workspace = true +repository.workspace = true +rust-version.workspace = true +version.workspace = true [lints] workspace = true [dependencies] -bytemuck = {version = "1.17", features = ["must_cast", "derive", "extern_crate_alloc"]} -colored = "2" -dashmap = {version = "6", features = ["serde"]} -ecow = {version = "0.2.3", features = ["serde"]} -enum-iterator = "2.1.0" -once_cell = "1" -serde = {version = "1", features = ["derive", "rc"]} +bytemuck = {workspace = true, features = [ + "must_cast", + "derive", + "extern_crate_alloc", +]} +colored.workspace = true +dashmap.workspace = true +ecow.workspace = true +enum-iterator.workspace = true +once_cell.workspace = true +serde = {workspace = true, features = ["rc"]} +unicode-segmentation.workspace = true serde_tuple = "0.5.0" -unicode-segmentation = "1.10" diff --git a/site/Cargo.toml b/site/Cargo.toml index 5206fde12..cb67c4e3e 100644 --- a/site/Cargo.toml +++ b/site/Cargo.toml @@ -1,58 +1,35 @@ [package] -edition = "2021" +description = "Uiua website" name = "site" version = "0.1.0" +categories.workspace = true +edition.workspace = true +keywords.workspace = true +license.workspace = true +readme.workspace = true +repository.workspace = true +rust-version.workspace = true [lints] workspace = true [dependencies] -base64 = "0.22.0" +base64.workspace = true +enum-iterator.workspace = true +js-sys.workspace = true +leptos.workspace = true +leptos_meta.workspace = true +leptos_router.workspace = true +rand.workspace = true +serde.workspace = true +serde_json.workspace = true +urlencoding.workspace = true +wasm-bindgen.workspace = true +web-sys = {workspace = true, features = ["HtmlElement"]} comrak = "0.39.0" console_error_panic_hook = "0.1.7" -enum-iterator = "2.0.0" -js-sys = "0.3" -leptos = "0.6.11" -leptos_meta = {version = "0.6.11", features = ["csr"]} -leptos_router = {version = "0.6.11", features = ["csr"]} -rand = {version = "0.8.5", features = ["small_rng"]} -serde = {version = "1", features = ["derive"]} -serde_json = "1" uiua = {path = "..", default-features = false, features = ["batteries", "web"]} uiua-editor = {path = "../pad/editor"} -urlencoding = "2" -# NOTE: if you change the wasm-bindgen version, remember to change it in nix/site.nix as well -wasm-bindgen = "=0.2.93" - -[dependencies.web-sys] -features = [ - "CssStyleDeclaration", - "DomRect", - "Storage", - "HtmlAudioElement", - "HtmlBrElement", - "HtmlElement", - "Selection", - "Node", - "Clipboard", - "ClipboardEvent", - "DataTransfer", - "Navigator", - "Permissions", - "ScrollIntoViewOptions", - "ScrollBehavior", - "ScrollLogicalPosition", - "StorageManager", - "FileReader", - "EventInit", - "DataTransfer", - "File", - "FileList", - "ResizeObserver", - "ResizeObserverEntry", - "Performance", -] -version = "0.3.70" [features] audio = [] # Dummy for rust-analyzer diff --git a/tests_ffi/Cargo.toml b/tests_ffi/Cargo.toml index caa4971da..4d8546d40 100644 --- a/tests_ffi/Cargo.toml +++ b/tests_ffi/Cargo.toml @@ -1,7 +1,14 @@ [package] -edition = "2021" +description = "Uiua FFI tests" name = "tests_ffi" version = "0.1.0" +categories.workspace = true +edition.workspace = true +keywords.workspace = true +license.workspace = true +readme.workspace = true +repository.workspace = true +rust-version.workspace = true [lib] crate-type = ["cdylib"] From 0c06bc179e6ab9b7fd5b67d08f504c98d65798b0 Mon Sep 17 00:00:00 2001 From: Tau Date: Thu, 7 Aug 2025 06:06:00 +0300 Subject: [PATCH 02/21] refactor: remove `once_cell` --- Cargo.lock | 2 -- Cargo.toml | 3 +-- parser/Cargo.toml | 1 - parser/src/split.rs | 7 +++---- src/constant.rs | 11 +++++------ src/main.rs | 3 +-- src/stand.rs | 8 +++----- src/sys/mod.rs | 7 +++---- src/sys/native.rs | 5 ++--- 9 files changed, 18 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 35116a96c..49d40f2f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6613,7 +6613,6 @@ dependencies = [ "notify", "num-complex", "num_cpus", - "once_cell", "open", "parking_lot", "paste", @@ -6680,7 +6679,6 @@ dependencies = [ "dashmap 6.1.0", "ecow", "enum-iterator", - "once_cell", "serde", "serde_tuple", "unicode-segmentation", diff --git a/Cargo.toml b/Cargo.toml index 754f0907a..72316aa0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ cargo = {level = "warn", priority = -1} dbg_macro = "warn" print_stdout = "warn" multiple_crate_versions = "allow" +non_std_lazy_statics = "warn" [workspace.dependencies] base64 = "0.22.0" @@ -29,7 +30,6 @@ js-sys = "0.3.69" leptos = "0.6.11" leptos_router = {version = "0.6.11", features = ["csr"]} leptos_meta = {version = "0.6.11", features = ["csr"]} -once_cell = "1" rand = {version = "0.8.5", features = ["small_rng"]} serde = {version = "1", features = ["derive"]} serde_json = "1.0.115" @@ -100,7 +100,6 @@ ecow.workspace = true enum-iterator.workspace = true indexmap = {version = "2", features = ["serde"]} num_cpus = "1.16.0" -once_cell.workspace = true open = {version = "5", optional = true} parking_lot = "0.12.1" paste = "1.0.14" diff --git a/parser/Cargo.toml b/parser/Cargo.toml index e0af76862..19003b0dc 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -24,7 +24,6 @@ colored.workspace = true dashmap.workspace = true ecow.workspace = true enum-iterator.workspace = true -once_cell.workspace = true serde = {workspace = true, features = ["rc"]} unicode-segmentation.workspace = true serde_tuple = "0.5.0" diff --git a/parser/src/split.rs b/parser/src/split.rs index 66be6c8e2..1d306db2f 100644 --- a/parser/src/split.rs +++ b/parser/src/split.rs @@ -1,13 +1,12 @@ -use std::{collections::HashMap, fmt}; +use std::{collections::HashMap, fmt, sync::LazyLock}; use enum_iterator::Sequence; -use once_cell::sync::Lazy; use crate::{ast::NumWord, Complex, SysOp}; use super::Primitive; -static ALIASES: Lazy> = Lazy::new(|| { +static ALIASES: LazyLock> = LazyLock::new(|| { [ (Primitive::Identity, &["id"] as &[_]), (Primitive::Gap, &["ga"]), @@ -148,7 +147,7 @@ impl Primitive { if name.len() < 2 { return None; } - static REVERSE_ALIASES: Lazy> = Lazy::new(|| { + static REVERSE_ALIASES: LazyLock> = LazyLock::new(|| { ALIASES .iter() .flat_map(|(prim, aliases)| aliases.iter().map(|&s| (s, *prim))) diff --git a/src/constant.rs b/src/constant.rs index f0464a374..68adfdb60 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -1,11 +1,10 @@ use std::{ f64::consts::TAU, path::{Path, PathBuf}, - sync::OnceLock, + sync::{LazyLock, OnceLock}, }; use ecow::EcoVec; -use once_cell::sync::Lazy; use rand::prelude::*; use crate::{ @@ -19,9 +18,9 @@ pub struct ConstantDef { /// The constant's class pub class: ConstClass, /// The constant's value - pub value: Lazy, + pub value: LazyLock, /// The constant's documentation - pub doc: Lazy, + pub doc: LazyLock, /// The suggested replacement because of deprecation pub deprecation: Option<&'static str>, } @@ -135,9 +134,9 @@ macro_rules! constant { $(#[$attr])* ConstantDef { name: $name, - value: Lazy::new(|| {$value.into()}), + value: LazyLock::new(|| {$value.into()}), class: ConstClass::$class, - doc: Lazy::new(|| { + doc: LazyLock::new(|| { let mut s = String::new(); $( s.push_str($doc.trim()); diff --git a/src/main.rs b/src/main.rs index d909d8674..c2bc10e7f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,6 @@ use std::{ use clap::{Parser, Subcommand}; use colored::*; use notify::{event::ModifyKind, EventKind, RecursiveMode, Watcher}; -use once_cell::sync::Lazy; use parking_lot::Mutex; use rustyline::{error::ReadlineError, DefaultEditor}; use terminal_size::terminal_size; @@ -34,7 +33,7 @@ use uiua::{ }; static PRESSED_CTRL_C: AtomicBool = AtomicBool::new(false); -static WATCH_CHILD: Lazy>> = Lazy::new(Default::default); +static WATCH_CHILD: Mutex> = Mutex::new(None); fn fail(e: UiuaError) -> T { eprintln!("{}", e.report()); diff --git a/src/stand.rs b/src/stand.rs index 91babb79c..c65ddcfad 100644 --- a/src/stand.rs +++ b/src/stand.rs @@ -1,6 +1,4 @@ -use std::{env, fs, io, path::Path}; - -use once_cell::sync::Lazy; +use std::{env, fs, io, path::Path, sync::LazyLock}; use crate::{Assembly, Compiler, NativeSys, UiuaResult}; @@ -43,5 +41,5 @@ fn load_asm() -> io::Result> { Ok(Some(asm)) } -pub static STAND_ASM: Lazy> = - Lazy::new(|| load_asm().unwrap_or_else(|e| panic!("{e}"))); +pub static STAND_ASM: LazyLock> = + LazyLock::new(|| load_asm().unwrap_or_else(|e| panic!("{e}"))); diff --git a/src/sys/mod.rs b/src/sys/mod.rs index d134866a9..1a97f329f 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -7,13 +7,12 @@ use std::{ mem::take, net::SocketAddr, path::{Path, PathBuf}, - sync::Arc, + sync::{Arc, LazyLock}, time::Duration, }; #[cfg(feature = "image")] use image::DynamicImage; -use once_cell::sync::Lazy; use parking_lot::Mutex; use time::UtcOffset; @@ -46,13 +45,13 @@ use in example Uiua code ✨"; /// Access the built-in `example.ua` file pub fn example_ua(f: impl FnOnce(&mut String) -> T) -> T { - static S: Lazy> = Lazy::new(|| Mutex::new(EXAMPLE_UA.to_string())); + static S: LazyLock> = LazyLock::new(|| Mutex::new(EXAMPLE_UA.to_string())); f(&mut S.lock()) } /// Access the built-in `example.txt` file pub fn example_txt(f: impl FnOnce(&mut String) -> T) -> T { - static S: Lazy> = Lazy::new(|| Mutex::new(EXAMPLE_TXT.to_string())); + static S: LazyLock> = LazyLock::new(|| Mutex::new(EXAMPLE_TXT.to_string())); f(&mut S.lock()) } diff --git a/src/sys/native.rs b/src/sys/native.rs index f059dfde6..f440b66ba 100644 --- a/src/sys/native.rs +++ b/src/sys/native.rs @@ -9,7 +9,7 @@ use std::{ slice, sync::{ atomic::{self, AtomicBool, AtomicU64}, - Arc, + Arc, LazyLock, }, thread::sleep, time::Duration, @@ -19,7 +19,6 @@ use colored::Colorize; #[cfg(feature = "webcam")] use crossbeam_channel as channel; use dashmap::DashMap; -use once_cell::sync::Lazy; use crate::{ terminal_size, GitTarget, Handle, MetaPtr, ReadLinesFn, ReadLinesReturnFn, Span, SysBackend, @@ -298,7 +297,7 @@ impl GlobalNativeSys { } } -static NATIVE_SYS: Lazy = Lazy::new(Default::default); +static NATIVE_SYS: LazyLock = LazyLock::new(Default::default); #[cfg(all(feature = "audio", feature = "binary"))] #[doc(hidden)] From edc208495cb32c92a6d042b7865653b5caa2fabc Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 12:36:15 +0300 Subject: [PATCH 03/21] refactor: deduplicate dependencies --- .clippy.toml | 35 +++++++ Cargo.lock | 225 +++++++++++------------------------------- Cargo.toml | 9 +- pad/editor/Cargo.toml | 4 +- parser/Cargo.toml | 2 +- 5 files changed, 99 insertions(+), 176 deletions(-) create mode 100644 .clippy.toml diff --git a/.clippy.toml b/.clippy.toml new file mode 100644 index 000000000..37e85de6b --- /dev/null +++ b/.clippy.toml @@ -0,0 +1,35 @@ +allowed-duplicate-crates = [ + "bitflags", + "dashmap", # upgraded to 6.* by dependabot, not sure if it should be downgraded back + + "getrandom", + "wasi", # 0.14 needed by getrandom@0.3.2, 0.11 by mio@1.0.3 and getrandom@0.2.15 + + "hashbrown", # TODO: can be resolved by updating dashmap to 7.0.0-rc0 + "objc2", + "objc2-foundation", + + "proc-macro-utils", # TODO: can be resolved by updating leptos crates to 0.7.0 + "serde_qs", # TODO: can be resolved by updating leptos crates to 0.7.0 + + "rustix", + "linux-raw-sys", # needed by rustix@0.38 + + "thiserror", + "thiserror-impl", + "ttf-parser", # both versions are brought by cosmic-text@0.12.1 + "windows-core", + "windows-implement", + "windows-interface", + "windows-result", + "windows-sys", + "windows-targets", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", + "zip", # 0.5.13 needed by simple_excel_writer, 4.2.0 by calamine +] diff --git a/Cargo.lock b/Cargo.lock index 49d40f2f5..d48ed1ae9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1080,7 +1080,7 @@ dependencies = [ "anstyle", "clap_lex", "strsim", - "terminal_size 0.4.2", + "terminal_size", ] [[package]] @@ -1155,15 +1155,6 @@ dependencies = [ "objc", ] -[[package]] -name = "codee" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af40247be877a1e3353fb406aa27ab3ef4bd3ff18cef91e75e667bfa3fde701d" -dependencies = [ - "thiserror 1.0.69", -] - [[package]] name = "codepage" version = "0.1.2" @@ -1354,17 +1345,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "cookie" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - [[package]] name = "coolor" version = "1.0.0" @@ -1600,7 +1580,7 @@ checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ "bitflags 2.9.1", "crossterm_winapi", - "mio 1.0.3", + "mio", "parking_lot", "rustix 0.38.44", "signal-hook", @@ -1656,12 +1636,12 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.4" +version = "3.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "672465ae37dc1bc6380a6547a8883d5dd397b0f1faaad4f265726cc7042a5345" +checksum = "697b5419f348fd5ae2478e8018cb016c00a5881c7f46c717de98ffd135a5651c" dependencies = [ - "nix 0.28.0", - "windows-sys 0.52.0", + "nix", + "windows-sys 0.59.0", ] [[package]] @@ -2578,18 +2558,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "gloo-timers" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - [[package]] name = "gloo-utils" version = "0.2.0" @@ -2902,7 +2870,7 @@ dependencies = [ "displaydoc", "yoke", "zerofrom", - "zerovec 0.10.4", + "zerovec", ] [[package]] @@ -2913,9 +2881,9 @@ checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ "displaydoc", "litemap", - "tinystr 0.7.6", + "tinystr", "writeable", - "zerovec 0.10.4", + "zerovec", ] [[package]] @@ -2928,8 +2896,8 @@ dependencies = [ "icu_locid", "icu_locid_transform_data", "icu_provider", - "tinystr 0.7.6", - "zerovec 0.10.4", + "tinystr", + "zerovec", ] [[package]] @@ -2953,7 +2921,7 @@ dependencies = [ "utf16_iter", "utf8_iter", "write16", - "zerovec 0.10.4", + "zerovec", ] [[package]] @@ -2973,8 +2941,8 @@ dependencies = [ "icu_locid_transform", "icu_properties_data", "icu_provider", - "tinystr 0.7.6", - "zerovec 0.10.4", + "tinystr", + "zerovec", ] [[package]] @@ -2993,11 +2961,11 @@ dependencies = [ "icu_locid", "icu_provider_macros", "stable_deref_trait", - "tinystr 0.7.6", + "tinystr", "writeable", "yoke", "zerofrom", - "zerovec 0.10.4", + "zerovec", ] [[package]] @@ -3105,9 +3073,9 @@ dependencies = [ [[package]] name = "inotify" -version = "0.9.6" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc" dependencies = [ "bitflags 1.3.2", "inotify-sys", @@ -3123,6 +3091,15 @@ dependencies = [ "libc", ] +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "interpolate_name" version = "0.2.4" @@ -3342,24 +3319,17 @@ dependencies = [ [[package]] name = "leptos-use" -version = "0.12.0" +version = "0.13.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "268b9df23d8c68ed0518c39d6f0d3b99fcbe30190a6dce4a7e5f342027ab0033" +checksum = "a6a93d93201701e3d46ad005e96f5ebad7212a9e0e2a1405f087523cc55d9a81" dependencies = [ - "async-trait", "cfg-if 1.0.0", - "codee", - "cookie", "default-struct-builder", - "futures-util", - "gloo-timers", - "gloo-utils", "js-sys", "lazy_static", "leptos", "paste", "thiserror 1.0.69", - "unic-langid", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -3808,18 +3778,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", -] - [[package]] name = "mio" version = "1.0.3" @@ -3987,18 +3945,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "nix" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" -dependencies = [ - "bitflags 2.9.1", - "cfg-if 1.0.0", - "cfg_aliases 0.1.1", - "libc", -] - [[package]] name = "nix" version = "0.29.0" @@ -4012,18 +3958,6 @@ dependencies = [ "memoffset", ] -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags 2.9.1", - "cfg-if 1.0.0", - "cfg_aliases 0.2.1", - "libc", -] - [[package]] name = "nohash-hasher" version = "0.2.0" @@ -4114,21 +4048,30 @@ checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" [[package]] name = "notify" -version = "6.1.1" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009" dependencies = [ "bitflags 2.9.1", - "crossbeam-channel", "filetime", "fsevent-sys", "inotify", "kqueue", "libc", "log", - "mio 0.8.11", + "mio", + "notify-types", "walkdir", - "windows-sys 0.48.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "notify-types" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585d3cb5e12e01aed9e8a1f70d5c6b5e86fe2a6e48fc8cd0b3e0b8df6f6eb174" +dependencies = [ + "instant", ] [[package]] @@ -5482,9 +5425,9 @@ dependencies = [ [[package]] name = "rustyline" -version = "16.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62fd9ca5ebc709e8535e8ef7c658eb51457987e48c98ead2be482172accc408d" +checksum = "2ee1e066dc922e513bda599c6ccb5f3bb2b0ea5870a579448f2622993f0a9a2f" dependencies = [ "bitflags 2.9.1", "cfg-if 1.0.0", @@ -5494,7 +5437,7 @@ dependencies = [ "libc", "log", "memchr", - "nix 0.30.1", + "nix", "radix_trie", "unicode-segmentation", "unicode-width 0.2.1", @@ -5653,9 +5596,9 @@ dependencies = [ [[package]] name = "serde_tuple" -version = "0.5.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f025b91216f15a2a32aa39669329a475733590a015835d1783549a56d09427" +checksum = "52569c5296679bd28e2457f067f97d270077df67da0340647da5412c8eac8d9e" dependencies = [ "serde", "serde_tuple_macros", @@ -5663,13 +5606,13 @@ dependencies = [ [[package]] name = "serde_tuple_macros" -version = "0.5.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4076151d1a2b688e25aaf236997933c66e18b870d0369f8b248b8ab2be630d7e" +checksum = "2f46c707781471741d5f2670edb36476479b26e94cf43efe21ca3c220b97ef2e" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.100", ] [[package]] @@ -5789,7 +5732,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", - "mio 1.0.3", + "mio", "signal-hook", ] @@ -6136,16 +6079,6 @@ dependencies = [ "xterm-query", ] -[[package]] -name = "terminal_size" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" -dependencies = [ - "rustix 0.38.44", - "windows-sys 0.48.0", -] - [[package]] name = "terminal_size" version = "0.4.2" @@ -6298,17 +6231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ "displaydoc", - "zerovec 0.10.4", -] - -[[package]] -name = "tinystr" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" -dependencies = [ - "displaydoc", - "zerovec 0.11.2", + "zerovec", ] [[package]] @@ -6634,7 +6557,7 @@ dependencies = [ "smallvec", "sys-locale", "terminal-light", - "terminal_size 0.3.0", + "terminal_size", "thread_local", "threadpool", "time", @@ -6684,24 +6607,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "unic-langid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28ba52c9b05311f4f6e62d5d9d46f094bd6e84cb8df7b3ef952748d752a7d05" -dependencies = [ - "unic-langid-impl", -] - -[[package]] -name = "unic-langid-impl" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658" -dependencies = [ - "tinystr 0.8.1", -] - [[package]] name = "unicode-bidi" version = "0.3.18" @@ -7527,15 +7432,6 @@ dependencies = [ "windows-targets 0.42.2", ] -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -7899,7 +7795,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "292c33df434fde4ecd87a7afecdfa1681a3d29567fc69c774a0d83d32c095331" dependencies = [ - "nix 0.29.0", + "nix", "thiserror 1.0.69", ] @@ -7976,7 +7872,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix 0.29.0", + "nix", "ordered-stream", "rand", "serde", @@ -8117,15 +8013,6 @@ dependencies = [ "zerovec-derive", ] -[[package]] -name = "zerovec" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" -dependencies = [ - "zerofrom", -] - [[package]] name = "zerovec-derive" version = "0.10.3" diff --git a/Cargo.toml b/Cargo.toml index 72316aa0d..53510381c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,6 @@ version = "0.17.0-dev.2" cargo = {level = "warn", priority = -1} dbg_macro = "warn" print_stdout = "warn" -multiple_crate_versions = "allow" non_std_lazy_statics = "warn" [workspace.dependencies] @@ -116,7 +115,7 @@ rustls = {version = "0.23.2", optional = true, default-features = false, feature serde = {workspace = true, features = ["rc"]} serde_json.workspace = true smallvec = {version = "1.9", features = ["serde", "union", "const_new"]} -terminal_size = {version = "0.3.0", optional = true} +terminal_size = {version = "0.4.2", optional = true} thread_local = "1" threadpool = "1.8.1" time = {version = "0.3.36", features = ["local-offset"]} @@ -131,10 +130,10 @@ hodaun = {version = "0.4.1", optional = true, features = ["output", "wav"]} # Binary dependencies clap = {version = "4", optional = true, features = ["derive"]} color-backtrace = {version = "0.6.1", optional = true} -ctrlc = {version = "=3.4.4", optional = true} +ctrlc = {version = "3.4.6", optional = true} icy_sixel = {version = "0.1.2", optional = true} -notify = {version = "6", optional = true} -rustyline = {version = "16.0.0", optional = true} +notify = {version = "7", optional = true} +rustyline = {version = "15.0.0", optional = true} terminal-light = {version = "1.4.0", optional = true} tokio = {version = "1", optional = true, features = ["io-std", "rt"]} tower-lsp = {version = "0.20.0", optional = true, features = ["proposed"]} diff --git a/pad/editor/Cargo.toml b/pad/editor/Cargo.toml index 8b47088c7..ba274dd73 100644 --- a/pad/editor/Cargo.toml +++ b/pad/editor/Cargo.toml @@ -32,6 +32,8 @@ uiua = {path = "../..", default-features = false, features = [ "web", ]} image = "0.25" -leptos-use = "0.12.0" +leptos-use = {version = "0.13.0", default-features = false, features = [ + "use_resize_observer", +]} wasm-bindgen-futures = "0.4.43" futures = "0.3.30" diff --git a/parser/Cargo.toml b/parser/Cargo.toml index 19003b0dc..b38ea8af3 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -26,4 +26,4 @@ ecow.workspace = true enum-iterator.workspace = true serde = {workspace = true, features = ["rc"]} unicode-segmentation.workspace = true -serde_tuple = "0.5.0" +serde_tuple = "1.0.0" From 1dab9d7a6da93f52771ea2d820559003d70dc389 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 15:27:40 +0300 Subject: [PATCH 04/21] lint: clippy::pedantic (init) --- Cargo.toml | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 53510381c..6b910fb6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,75 @@ cargo = {level = "warn", priority = -1} dbg_macro = "warn" print_stdout = "warn" non_std_lazy_statics = "warn" +pedantic = {level = "warn", priority = -1} +flat_map_option = "allow" # 1 +format_collect = "allow" # 1 +inefficient_to_string = "allow" # 1 +match_wild_err_arm = "allow" # 1 +maybe_infinite_iter = "allow" # 1 +missing_fields_in_debug = "allow" # 1 +same_functions_in_if_condition = "allow" # 1 +unnecessary_debug_formatting = "allow" # 1 +unreadable_literal = "allow" # 1 +implicit_clone = "allow" # 2 +inconsistent_struct_constructor = "allow" # 2 +match_bool = "allow" # 2 +no_mangle_with_rust_abi = "allow" # 2 +struct_excessive_bools = "allow" # 2 +struct_field_names = "allow" # 2 +unicode_not_nfc = "allow" # 2 +unused_self = "allow" # 2 +case_sensitive_file_extension_comparisons = "allow" # 3 +cloned_instead_of_copied = "allow" # 3 +ref_as_ptr = "allow" # 3 +unsafe_derive_deserialize = "allow" # 3 +doc_markdown = "allow" # 5 +match_wildcard_for_single_variants = "allow" # 5 +needless_continue = "allow" # 5 +range_plus_one = "allow" # 5 +if_not_else = "allow" # 6 +manual_let_else = "allow" # 6 +single_char_pattern = "allow" # 6 +needless_raw_string_hashes = "allow" # 7 +unnecessary_wraps = "allow" # 7 +unnested_or_patterns = "allow" # 8 +borrow_as_ptr = "allow" # 9 +explicit_iter_loop = "allow" # 9 +ignored_unit_patterns = "allow" # 9 +many_single_char_names = "allow" # 9 +single_match_else = "allow" # 11 +manual_string_new = "allow" # 12 +trivially_copy_pass_by_ref = "allow" # 12 +ptr_cast_constness = "allow" # 15 +redundant_else = "allow" # 15 +unnecessary_semicolon = "allow" # 15 +manual_assert = "allow" # 16 +inline_always = "allow" # 18 +from_iter_instead_of_collect = "allow" # 20 +default_trait_access = "allow" # 23 +format_push_string = "allow" # 27 +missing_panics_doc = "allow" # 37 +used_underscore_binding = "allow" # 39 +float_cmp = "allow" # 40 +map_unwrap_or = "allow" # 59 +return_self_not_must_use = "allow" # 61 +needless_pass_by_value = "allow" # 70 +items_after_statements = "allow" # 74 +redundant_closure_for_method_calls = "allow" # 75 +ptr_as_ptr = "allow" # 83 +similar_names = "allow" # 93 +enum_glob_use = "allow" # 96 +cast_possible_wrap = "allow" # 105 +too_many_lines = "allow" # 106 +wildcard_imports = "allow" # 134 +cast_precision_loss = "allow" # 172 +match_same_arms = "allow" # 176 +cast_sign_loss = "allow" # 190 +missing_errors_doc = "allow" # 224 +semicolon_if_nothing_returned = "allow" # 263 +must_use_candidate = "allow" # 301 +cast_possible_truncation = "allow" # 349 +cast_lossless = "allow" # 355 [workspace.dependencies] base64 = "0.22.0" From 895186b6ae309cb1b93f956e82b3f678664e7665 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 15:45:39 +0300 Subject: [PATCH 05/21] lint: fix clippy::pedantic (1 entry) --- Cargo.toml | 9 --------- pad/editor/src/lib.rs | 2 +- parser/src/inputs.rs | 2 +- parser/src/parse.rs | 5 +++++ site/src/markdown.rs | 8 +++++--- src/algorithm/encode.rs | 6 +++--- src/assembly.rs | 2 +- src/ffi.rs | 2 +- src/format.rs | 4 ++++ src/main.rs | 2 +- 10 files changed, 22 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6b910fb6e..9f2e44a4e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,15 +17,6 @@ dbg_macro = "warn" print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} -flat_map_option = "allow" # 1 -format_collect = "allow" # 1 -inefficient_to_string = "allow" # 1 -match_wild_err_arm = "allow" # 1 -maybe_infinite_iter = "allow" # 1 -missing_fields_in_debug = "allow" # 1 -same_functions_in_if_condition = "allow" # 1 -unnecessary_debug_formatting = "allow" # 1 -unreadable_literal = "allow" # 1 implicit_clone = "allow" # 2 inconsistent_struct_constructor = "allow" # 2 match_bool = "allow" # 2 diff --git a/pad/editor/src/lib.rs b/pad/editor/src/lib.rs index 849c45a23..9cab6ddd2 100644 --- a/pad/editor/src/lib.rs +++ b/pad/editor/src/lib.rs @@ -79,7 +79,7 @@ pub fn Editor<'a>( id.set(i + 1); i }); - let help: Vec = help.iter().map(|s| s.to_string()).collect(); + let help: Vec = help.iter().copied().map(|s| s.to_string()).collect(); // Initialize all the examples let examples = match mode { EditorMode::Example if !nonprogressive => progressive_strings(example), diff --git a/parser/src/inputs.rs b/parser/src/inputs.rs index ce585d21e..34c2f12b8 100644 --- a/parser/src/inputs.rs +++ b/parser/src/inputs.rs @@ -48,7 +48,7 @@ impl Inputs { InputSrc::File(path) => self .files .get(&**path) - .unwrap_or_else(|| panic!("File {path:?} not found")) + .unwrap_or_else(|| panic!("File {} not found", path.display())) .clone(), InputSrc::Str(index) => self .strings diff --git a/parser/src/parse.rs b/parser/src/parse.rs index f294dbdd6..4773089ba 100644 --- a/parser/src/parse.rs +++ b/parser/src/parse.rs @@ -1216,6 +1216,11 @@ impl Parser<'_> { if self.too_deep() { return None; } + #[expect( + clippy::same_functions_in_if_condition, + reason = "methods seem to mutate self, so the second if may or may not be needed", + // TODO + )] let mut word = if let Some(n) = self.num() { n.map(|(n, s)| Word::Number(n, s)) } else if let Some(prim) = self.prim() { diff --git a/site/src/markdown.rs b/site/src/markdown.rs index 5174ec18c..8d92677fb 100644 --- a/site/src/markdown.rs +++ b/site/src/markdown.rs @@ -217,6 +217,7 @@ fn node_view<'a>(node: &'a AstNode<'a>) -> View { #[cfg(test)] fn node_html<'a>(node: &'a AstNode<'a>) -> String { + use std::fmt::Write; use uiua::{Compiler, PrimDoc, SafeSys, Uiua, UiuaErrorKind, Value}; use uiua_editor::prim_class; @@ -393,9 +394,10 @@ fn node_html<'a>(node: &'a AstNode<'a>) -> String { NodeValue::Table(_) => format!(r#"{}
"#, children()), &NodeValue::TableRow(is_header) => { let tag = if is_header { "th" } else { "td" }; - children_iter - .map(|s| format!("<{tag}>{s}")) - .collect() + children_iter.fold(String::new(), |mut acc, cur| { + write!(acc, "<{tag}>{cur}").ok(); + acc + }) } _ => children(), } diff --git a/src/algorithm/encode.rs b/src/algorithm/encode.rs index ae09c0af9..796d8bb6e 100644 --- a/src/algorithm/encode.rs +++ b/src/algorithm/encode.rs @@ -307,9 +307,9 @@ impl Value { &Data::Float(f) => f.into(), Data::String(s) => s.clone().into(), &Data::Bool(b) => b.into(), - Data::DateTime(dt) => { - ((dt.as_f64() - 2.0) * 24.0 * 60.0 * 60.0 - 2208988800.0).into() - } + Data::DateTime(dt) => ((dt.as_f64() - 2.0) * 24.0 * 60.0 * 60.0 + - 2_208_988_800.0) + .into(), Data::DateTimeIso(dt) => dt.clone().into(), Data::DurationIso(dur) => dur.clone().into(), Data::Error(e) => e.to_string().into(), diff --git a/src/assembly.rs b/src/assembly.rs index a2c959ce6..c5bb9c3df 100644 --- a/src/assembly.rs +++ b/src/assembly.rs @@ -648,6 +648,6 @@ impl fmt::Debug for Assembly { f.debug_struct("Assembly") .field("root", &self.root) .field("functions", &FmtFunctions(self)) - .finish() + .finish_non_exhaustive() // TODO: maybe show all fields instead? } } diff --git a/src/ffi.rs b/src/ffi.rs index 99fe01044..49af651a4 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -364,7 +364,7 @@ mod enabled { let mut len_indices = arg_tys .iter() .enumerate() - .flat_map(|(i, arg)| arg.len_index.map(|index| (i, index))) + .filter_map(|(i, arg)| arg.len_index.map(|index| (i, index))) .collect::>(); len_indices.sort_by_key(|tup| tup.1); let len_indices = len_indices; diff --git a/src/format.rs b/src/format.rs index 6b22bcda0..99071594d 100644 --- a/src/format.rs +++ b/src/format.rs @@ -1441,6 +1441,10 @@ impl Formatter<'_> { let mut values = env.rt.output_comments; if let Err(e) = res { + #[expect( + clippy::maybe_infinite_iter, + reason="values doesn't contain all possible keys,so this should terminate at some point", + )] let next = (0..).take_while(|i| values.contains_key(i)).count(); values.insert(next, vec![vec![e.to_string().into()]]); } diff --git a/src/main.rs b/src/main.rs index c2bc10e7f..899b5a130 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1175,7 +1175,7 @@ fn repl(mut env: Uiua, mut compiler: Compiler, color: bool, stack: bool, config: code } Err(ReadlineError::Eof | ReadlineError::Interrupted) => break, - Err(_) => panic!("Failed to read from Stdin"), + Err(e) => panic!("Failed to read from Stdin: {e}"), }; if code.is_empty() { continue; From 618ac95159126fd4c13a0141a5ed6e3bb06686e4 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 15:47:00 +0300 Subject: [PATCH 06/21] lint: fix clippy::pedantic (2 entries) --- Cargo.toml | 8 -------- pad/editor/src/backend.rs | 8 ++++---- pad/editor/src/lib.rs | 15 +++++---------- parser/src/parse.rs | 2 +- site/src/main.rs | 2 +- site/src/tutorial.rs | 5 +++++ src/algorithm/path.rs | 2 +- src/compile/mod.rs | 4 ++++ src/fill.rs | 18 +++++++++--------- src/format.rs | 2 +- src/window.rs | 4 ++++ tests_ffi/src/lib.rs | 4 ++-- 12 files changed, 37 insertions(+), 37 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9f2e44a4e..e7b86b176 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,14 +17,6 @@ dbg_macro = "warn" print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} -implicit_clone = "allow" # 2 -inconsistent_struct_constructor = "allow" # 2 -match_bool = "allow" # 2 -no_mangle_with_rust_abi = "allow" # 2 -struct_excessive_bools = "allow" # 2 -struct_field_names = "allow" # 2 -unicode_not_nfc = "allow" # 2 -unused_self = "allow" # 2 case_sensitive_file_extension_comparisons = "allow" # 3 cloned_instead_of_copied = "allow" # 3 ref_as_ptr = "allow" # 3 diff --git a/pad/editor/src/backend.rs b/pad/editor/src/backend.rs index 8f525736e..26a53d7f6 100644 --- a/pad/editor/src/backend.rs +++ b/pad/editor/src/backend.rs @@ -144,7 +144,7 @@ impl WebBackend { } panic!("Ran out of file handles"); } - fn file(&self, path: &Path, f: impl FnOnce(&[u8]) -> T) -> Result { + fn file(path: &Path, f: impl FnOnce(&[u8]) -> T) -> Result { FILES.with(|files| { let files = files.borrow(); files @@ -251,10 +251,10 @@ impl SysBackend for WebBackend { Ok(set.into_iter().collect()) } fn is_file(&self, path: &str) -> Result { - Ok(self.file(path.as_ref(), |_| {}).is_ok()) + Ok(Self::file(path.as_ref(), |_| {}).is_ok()) } fn file_exists(&self, path: &str) -> bool { - self.file(path.as_ref(), |_| {}).is_ok() + Self::file(path.as_ref(), |_| {}).is_ok() } fn file_write_all(&self, path: &Path, contents: &[u8]) -> Result<(), String> { FILES.with(|files| { @@ -267,7 +267,7 @@ impl SysBackend for WebBackend { Ok(()) } fn file_read_all(&self, path: &Path) -> Result, String> { - self.file(path, |contents| contents.to_vec()) + Self::file(path, |contents| contents.to_vec()) } fn open_file(&self, path: &Path, write: bool) -> Result { let handle = self.new_handle(); diff --git a/pad/editor/src/lib.rs b/pad/editor/src/lib.rs index 9cab6ddd2..8ef4ac7f7 100644 --- a/pad/editor/src/lib.rs +++ b/pad/editor/src/lib.rs @@ -1403,9 +1403,10 @@ pub fn Editor<'a>( EditorMode::Showcase | EditorMode::Pad => "medium-editor", }; - let editor_layout = match fullscreen_enabled.get() { - true => "fullscreen-editor", - false => "normal-editor", + let editor_layout = if fullscreen_enabled.get() { + "fullscreen-editor" + } else { + "normal-editor" }; format!("editor {editor_size} {editor_layout}") @@ -1460,13 +1461,7 @@ pub fn Editor<'a>( .unwrap() .unchecked_into::() .style() - .set_property( - "overflow", - match *s { - true => "hidden", - false => "auto", - }, - ); + .set_property("overflow", if *s { "hidden" } else { "auto" }); if !*s { set_timeout( move || state.update(|state| state.update_line_number_width()), diff --git a/parser/src/parse.rs b/parser/src/parse.rs index 4773089ba..07212bd93 100644 --- a/parser/src/parse.rs +++ b/parser/src/parse.rs @@ -666,8 +666,8 @@ impl Parser<'_> { let close_span = self.exact(CloseParen.into()); validator = Some(FieldValidator { open_span, - close_span, words, + close_span, }); } diff --git a/site/src/main.rs b/site/src/main.rs index 7d9c7b4e8..5c09d32bd 100644 --- a/site/src/main.rs +++ b/site/src/main.rs @@ -630,7 +630,7 @@ fn site() { continue; } threads.push(( - path.to_path_buf(), + path.clone(), code.clone(), std::thread::spawn(move || { ( diff --git a/site/src/tutorial.rs b/site/src/tutorial.rs index bcbafd589..1deb070d6 100644 --- a/site/src/tutorial.rs +++ b/site/src/tutorial.rs @@ -144,6 +144,11 @@ impl IntoParam for TutorialPage { } } +#[expect( + clippy::unicode_not_nfc, + reason = "the suggested CJK characters don't look as good", + // TODO: maybe replace with better "arrows" that don't use characters +)] #[component] fn TutorialNav(page: TutorialPage) -> impl IntoView { let next = move || { diff --git a/src/algorithm/path.rs b/src/algorithm/path.rs index f89f0d3f4..546947a21 100644 --- a/src/algorithm/path.rs +++ b/src/algorithm/path.rs @@ -254,8 +254,8 @@ fn path_impl( let mut env = PathEnv { env, neighbors, - heuristic, is_goal, + heuristic, args, }; diff --git a/src/compile/mod.rs b/src/compile/mod.rs index 4f9e9563a..a9be7e25e 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -206,6 +206,10 @@ struct CurrentBinding { } /// A scope where names are defined +#[expect( + clippy::struct_excessive_bools, + reason = "doesn't seem to be a state machine" +)] #[derive(Debug, Clone)] pub(crate) struct Scope { kind: ScopeKind, diff --git a/src/fill.rs b/src/fill.rs index 57bcb2448..88b092315 100644 --- a/src/fill.rs +++ b/src/fill.rs @@ -2,8 +2,8 @@ use crate::{Array, Boxed, Complex, SubSide, Uiua, Value}; pub struct Fill<'a> { env: &'a Uiua, - value_fill: fn(env: &'a Uiua) -> Option<&'a FillValue>, - other_value_fill: fn(env: &'a Uiua) -> Option<&'a FillValue>, + value: fn(env: &'a Uiua) -> Option<&'a FillValue>, + other_value: fn(env: &'a Uiua) -> Option<&'a FillValue>, other_error: &'static str, } @@ -44,21 +44,21 @@ impl<'a> Fill<'a> { pub fn new(env: &'a Uiua) -> Self { Self { env, - value_fill: Uiua::value_fill, - other_value_fill: Uiua::value_unfill, + value: Uiua::value_fill, + other_value: Uiua::value_unfill, other_error: ". An unfill is set, but not a normal fill.", } } pub fn new_un(env: &'a Uiua) -> Self { Self { env, - value_fill: Uiua::value_unfill, - other_value_fill: Uiua::value_fill, + value: Uiua::value_unfill, + other_value: Uiua::value_fill, other_error: ". A normal fill is set, but not an unfill.", } } pub fn value(&self) -> Option<&FillValue> { - (self.value_fill)(self.env) + (self.value)(self.env) } fn value_map( &self, @@ -178,7 +178,7 @@ impl<'a> Fill<'a> { Some(Value::Complex(_)) => ". A complex fill is set, but it is not a scalar.", Some(Value::Box(_)) => ". A box fill is set, but it is not a scalar.", None => { - if (self.other_value_fill)(self.env).is_some() { + if (self.other_value)(self.env).is_some() { self.other_error } else { "" @@ -197,7 +197,7 @@ impl<'a> Fill<'a> { } Some(Value::Box(_)) => ". A box fill is set, but the array is not boxed values.", None => { - if (self.other_value_fill)(self.env).is_some() { + if (self.other_value)(self.env).is_some() { self.other_error } else { "" diff --git a/src/format.rs b/src/format.rs index 99071594d..6ba99efc7 100644 --- a/src/format.rs +++ b/src/format.rs @@ -678,7 +678,7 @@ impl Formatter<'_> { } Item::Words(words) => { self.prev_import_function = None; - let lines = flip_unsplit_lines(split_words(words.to_vec())); + let lines = flip_unsplit_lines(split_words(words.clone())); let extra_newlines = lines.len() > 1 && self.output.ends_with('(') && depth > 0; for (i, line) in lines.into_iter().enumerate() { let line = trim_spaces(&line, true); diff --git a/src/window.rs b/src/window.rs index 4ef6bc66c..d3c91849a 100644 --- a/src/window.rs +++ b/src/window.rs @@ -179,6 +179,10 @@ pub fn run_window() { .unwrap(); } +#[expect( + clippy::struct_excessive_bools, + reason = "doesn't seem to be a state machine" +)] struct App { items: Vec, recv: Receiver, diff --git a/tests_ffi/src/lib.rs b/tests_ffi/src/lib.rs index 4cc75321e..d292261ee 100644 --- a/tests_ffi/src/lib.rs +++ b/tests_ffi/src/lib.rs @@ -36,13 +36,13 @@ pub unsafe extern "C" fn multi_list( } #[no_mangle] -pub unsafe fn change_string(s: *mut *const c_char) { +pub unsafe extern "C" fn change_string(s: *mut *const c_char) { let new_str = CString::new("Hello, World!").unwrap(); *s = new_str.into_raw(); } #[no_mangle] -pub unsafe fn change_string_to_sum(a: c_int, b: c_int, s: *mut *const c_char) { +pub unsafe extern "C" fn change_string_to_sum(a: c_int, b: c_int, s: *mut *const c_char) { let sum = a + b; let new_str = CString::new(format!("{a} + {b} = {sum}")).unwrap(); *s = new_str.into_raw(); From 0027ba948d722a61161c18730e5df1b472925296 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 16:05:57 +0300 Subject: [PATCH 07/21] lint: fix clippy::pedantic (3 entries) --- Cargo.toml | 4 ---- pad/editor/src/backend.rs | 10 ++++++++-- parser/src/parse.rs | 4 ++-- src/algorithm/dyadic/search.rs | 2 +- src/algorithm/table.rs | 2 +- src/array.rs | 4 ++++ src/compile/mod.rs | 4 ++-- src/main.rs | 13 +++++++------ src/shape.rs | 4 ++++ src/tree.rs | 4 ++++ src/value.rs | 8 ++++++-- tests_ffi/src/lib.rs | 2 +- 12 files changed, 40 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e7b86b176..a9650bd60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,10 +17,6 @@ dbg_macro = "warn" print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} -case_sensitive_file_extension_comparisons = "allow" # 3 -cloned_instead_of_copied = "allow" # 3 -ref_as_ptr = "allow" # 3 -unsafe_derive_deserialize = "allow" # 3 doc_markdown = "allow" # 5 match_wildcard_for_single_variants = "allow" # 5 needless_continue = "allow" # 5 diff --git a/pad/editor/src/backend.rs b/pad/editor/src/backend.rs index 26a53d7f6..4d72f4de3 100644 --- a/pad/editor/src/backend.rs +++ b/pad/editor/src/backend.rs @@ -491,7 +491,10 @@ impl SysBackend for WebBackend { .replace("github.com", "raw.githubusercontent.com") .replace("src/branch/master", "raw/branch/master"); - if !url.ends_with(".ua") { + if !std::path::Path::new(&url) + .extension() + .is_some_and(|ext| ext.eq_ignore_ascii_case("ua")) + { url = format!("{url}/main/lib.ua"); } @@ -525,7 +528,10 @@ impl SysBackend for WebBackend { .iter() .filter_map(|entry| { let path = entry.get("path")?.as_str()?; - if path.ends_with(".ua") { + if Path::new(path) + .extension() + .is_some_and(|ext| ext.eq_ignore_ascii_case("ua")) + { Some(path.to_string()) } else { None diff --git a/parser/src/parse.rs b/parser/src/parse.rs index 07212bd93..db352d212 100644 --- a/parser/src/parse.rs +++ b/parser/src/parse.rs @@ -213,7 +213,7 @@ pub fn parse( errors, diagnostics, next_output_comment: 0, - start_addr: &base as *const u8 as usize, + start_addr: std::ptr::from_ref(&base) as usize, }; let items = parser.items(ItemsKind::TopLevel); if parser.errors.is_empty() && parser.index < parser.tokens.len() { @@ -1203,7 +1203,7 @@ impl Parser<'_> { #[cfg(target_arch = "wasm32")] const MAX_RECURSION_DEPTH: usize = 512 * 1024; let curr = 0u8; - let curr_addr = &curr as *const u8 as usize; + let curr_addr = std::ptr::from_ref(&curr) as usize; let diff = curr_addr.abs_diff(self.start_addr); let too_deep = diff > MAX_RECURSION_DEPTH; if too_deep { diff --git a/src/algorithm/dyadic/search.rs b/src/algorithm/dyadic/search.rs index 6d5b9b2f4..94ce9f545 100644 --- a/src/algorithm/dyadic/search.rs +++ b/src/algorithm/dyadic/search.rs @@ -65,7 +65,7 @@ impl Array { result_data.push(is_member as u8); } } - let shape: Shape = elems.shape.iter().cloned().take(1).collect(); + let shape: Shape = elems.shape.iter().copied().take(1).collect(); Array::new(shape, result_data) } Ordering::Greater => { diff --git a/src/algorithm/table.rs b/src/algorithm/table.rs index 16ab1ab4c..e7f6e023f 100644 --- a/src/algorithm/table.rs +++ b/src/algorithm/table.rs @@ -817,7 +817,7 @@ where let acc_slice = acc.make_mut(); for a in a.data { let mut i = 0; - for b in b.data.iter().cloned() { + for b in b.data.iter().copied() { acc_slice[i] = f(acc_slice[i], a); i += 1; acc_slice[i] = f(acc_slice[i], b); diff --git a/src/array.rs b/src/array.rs index 5ccaa9b4e..21e80bc43 100644 --- a/src/array.rs +++ b/src/array.rs @@ -25,6 +25,10 @@ use crate::{ }; /// Uiua's array type +#[expect( + clippy::unsafe_derive_deserialize, + reason = "done through ArrayRep which is safe" +)] #[derive(Clone, Serialize, Deserialize)] #[serde( from = "ArrayRep", diff --git a/src/compile/mod.rs b/src/compile/mod.rs index a9be7e25e..da7d2d612 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -478,7 +478,7 @@ impl Compiler { } let base = 0u8; - self.start_addrs.push(&base as *const u8 as usize); + self.start_addrs.push(std::ptr::from_ref(&base) as usize); let res = self.catching_crash(input, |env| env.items(items, ItemCompMode::TopLevel)); self.start_addrs.pop(); @@ -1212,7 +1212,7 @@ impl Compiler { }; let start_addr = *self.start_addrs.first().unwrap(); let curr = 0u8; - let curr_addr = &curr as *const u8 as usize; + let curr_addr = std::ptr::from_ref(&curr) as usize; let diff = curr_addr.abs_diff(start_addr); if diff > MAX_RECURSION_DEPTH { return Err(self.error(span.clone(), "Compilation recursion limit reached")); diff --git a/src/main.rs b/src/main.rs index 899b5a130..f343208d6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use std::{ error::Error, fmt, fs, io::{self, stderr, stdin, stdout, BufRead, Write}, - path::{is_separator, Path, PathBuf}, + path::{Path, PathBuf}, process::{exit, Child, Command, Stdio}, sync::{ atomic::{AtomicBool, Ordering}, @@ -122,12 +122,13 @@ fn main() { set_use_window(true); args.next(); } - if let Some(path) = args - .next() - .filter(|arg| arg.ends_with(".ua") || arg.contains(is_separator)) - { + if let Some(path) = args.next().map(PathBuf::from).filter(|arg| { + arg.extension() + .is_some_and(|ext| ext.eq_ignore_ascii_case("ua")) + || arg.components().count() > 1 + }) { let args = args.collect(); - run(path.as_ref(), args, false, None, None, None, false); + run(&path, args, false, None, None, None, false); return; } diff --git a/src/shape.rs b/src/shape.rs index 9f0190f69..bf110c921 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -9,6 +9,10 @@ use serde::*; use smallvec::SmallVec; /// Uiua's array shape type +#[expect( + clippy::unsafe_derive_deserialize, + reason = "just a wrapper around SmallVec with no additional invariants" +)] #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize)] #[serde(transparent)] pub struct Shape { diff --git a/src/tree.rs b/src/tree.rs index 3ac89fbba..65b23e730 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -1098,6 +1098,10 @@ macro_rules! node { /// A node is a tree structure of instructions. It can be used as both a single unit as well as a list. #[derive(Clone, Serialize, Deserialize)] #[repr(u8)] + #[expect( + clippy::unsafe_derive_deserialize, + reason="seems to be triggered by thread_local! usage", + )] #[allow(missing_docs)] #[serde(from = "NodeRep", into = "NodeRep")] pub enum Node { diff --git a/src/value.rs b/src/value.rs index 11ba5bd4e..33f97d13f 100644 --- a/src/value.rs +++ b/src/value.rs @@ -181,6 +181,10 @@ impl Value { } } /// Get an iterator over the elements of the value + #[expect( + clippy::cloned_instead_of_copied, + reason = "not all value types are Copy" + )] pub fn elements(&self) -> Box + '_> { val_as_arr!(self, |array| Box::new( array.data.iter().cloned().map(Value::from) @@ -360,14 +364,14 @@ impl Deref for Value { type Target = ValueRepr; fn deref(&self) -> &Self::Target { // Safety: The layout of `Value` should always match that of `Value` - unsafe { &*(self as *const Self as *const ValueRepr) } + unsafe { &*(std::ptr::from_ref(self) as *const ValueRepr) } } } impl DerefMut for Value { fn deref_mut(&mut self) -> &mut Self::Target { // Safety: The layout of `Value` should always match that of `Value` - unsafe { &mut *(self as *mut Self as *mut ValueRepr) } + unsafe { &mut *(std::ptr::from_mut(self) as *mut ValueRepr) } } } diff --git a/tests_ffi/src/lib.rs b/tests_ffi/src/lib.rs index d292261ee..d5208bc11 100644 --- a/tests_ffi/src/lib.rs +++ b/tests_ffi/src/lib.rs @@ -125,7 +125,7 @@ pub unsafe extern "C" fn person_children(name: *const c_char, age: c_int) -> *co name: CString::new(format!("{name}ina")).unwrap().into_raw(), age: age - 27, }); - children.leak() as *mut _ as *const _ + std::ptr::from_mut(children.leak()) as *const _ } #[no_mangle] From 966842635166e67c9dc4ae568ff9f66452ab8504 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 16:56:45 +0300 Subject: [PATCH 08/21] lint: fix clippy::pedantic (5 entries) --- Cargo.toml | 4 ---- parser/src/lex.rs | 2 +- parser/src/parse.rs | 4 +--- parser/src/split.rs | 6 +++--- src/algorithm/dyadic/combine.rs | 4 ++-- src/algorithm/dyadic/mod.rs | 4 ++-- src/algorithm/map.rs | 8 ++++---- src/algorithm/media.rs | 4 ++-- src/array.rs | 2 +- src/compile/data.rs | 2 +- src/cowslice.rs | 2 +- src/grid_fmt.rs | 4 ++++ src/lsp.rs | 2 +- src/run.rs | 2 +- src/sys/native.rs | 2 +- 15 files changed, 25 insertions(+), 27 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a9650bd60..af3e06b38 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,10 +17,6 @@ dbg_macro = "warn" print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} -doc_markdown = "allow" # 5 -match_wildcard_for_single_variants = "allow" # 5 -needless_continue = "allow" # 5 -range_plus_one = "allow" # 5 if_not_else = "allow" # 6 manual_let_else = "allow" # 6 single_char_pattern = "allow" # 6 diff --git a/parser/src/lex.rs b/parser/src/lex.rs index 8ad1b9d01..b14ef80e5 100644 --- a/parser/src/lex.rs +++ b/parser/src/lex.rs @@ -1407,7 +1407,7 @@ impl<'a> Lexer<'a> { while self.next_char_exact(" ") || self.next_char_exact("\t") {} self.end(Spaces, start) } - c if c.chars().all(|c| c.is_whitespace()) => continue, + c if c.chars().all(|c| c.is_whitespace()) => {} c => { if c.chars().count() == 1 { let c = c.chars().next().unwrap(); diff --git a/parser/src/parse.rs b/parser/src/parse.rs index db352d212..faabf0cd0 100644 --- a/parser/src/parse.rs +++ b/parser/src/parse.rs @@ -386,9 +386,7 @@ impl Parser<'_> { loop { if let Some(ident) = self.ident() { items.push(ident); - } else if self.spaces().is_some() { - continue; - } else { + } else if self.spaces().is_none() { break; } } diff --git a/parser/src/split.rs b/parser/src/split.rs index 1d306db2f..e1da99137 100644 --- a/parser/src/split.rs +++ b/parser/src/split.rs @@ -290,7 +290,7 @@ pub fn split_name(name: &str) -> Option> { 'p' => Primitive::Pop, _ => unreachable!(), }; - prims.push((prim.into(), &sub_name[i..i + 1])) + prims.push((prim.into(), &sub_name[i..=i])) } start += len; continue 'outer; @@ -356,7 +356,7 @@ pub fn split_name(name: &str) -> Option> { 'p' => Primitive::Pop, _ => unreachable!(), }; - prims.push((prim.into(), &sub_name[i..i + 1])) + prims.push((prim.into(), &sub_name[i..=i])) } end -= len; continue 'outer; @@ -374,7 +374,7 @@ pub fn split_name(name: &str) -> Option> { 'f' => Primitive::Fix, _ => unreachable!(), }; - prims.push((prim.into(), &sub_name[i..i + 1])) + prims.push((prim.into(), &sub_name[i..=i])) } end -= len; continue 'outer; diff --git a/src/algorithm/dyadic/combine.rs b/src/algorithm/dyadic/combine.rs index beb185af9..d165af3dd 100644 --- a/src/algorithm/dyadic/combine.rs +++ b/src/algorithm/dyadic/combine.rs @@ -1069,7 +1069,7 @@ impl Value { Value::Char(_) => { return Err(ctx.error("Cannot combine number and character arrays")) } - _ => {} + Value::Byte(_) => {} } } row_values = values.into_iter(); @@ -1120,7 +1120,7 @@ impl Value { Value::Complex(_) => { return Err(ctx.error("Cannot combine character and complex arrays")) } - _ => {} + Value::Char(_) => {} } } row_values = values.into_iter(); diff --git a/src/algorithm/dyadic/mod.rs b/src/algorithm/dyadic/mod.rs index 3ef4684e2..c34a1b151 100644 --- a/src/algorithm/dyadic/mod.rs +++ b/src/algorithm/dyadic/mod.rs @@ -395,7 +395,7 @@ impl Array { new_shape.extend_from_slice(&self.shape); self.shape = new_shape.into(); } - _ => {} + Ordering::Equal => {} } // If converting to rank 0, the rank-matching process @@ -459,7 +459,7 @@ impl Value { if irank >= 0 { // Positive rank if rank >= shape.len() { - for _ in 0..rank - shape.len() + 1 { + for _ in 0..=rank - shape.len() { shape.prepend(1); } } else { diff --git a/src/algorithm/map.rs b/src/algorithm/map.rs index 86cc54593..4ad3be298 100644 --- a/src/algorithm/map.rs +++ b/src/algorithm/map.rs @@ -446,13 +446,13 @@ impl MapKeys { &key_data[key_index * key_row_len..(key_index + 1) * key_row_len]; if cell_key[0].is_any_tombstone() { continue; - } else if cell_key[0].is_any_empty_cell() { + } + if cell_key[0].is_any_empty_cell() { key_index = orig; break false; - } else if ArrayCmpSlice(cell_key) == ArrayCmpSlice(&key.data) { + } + if ArrayCmpSlice(cell_key) == ArrayCmpSlice(&key.data) { break true; - } else { - continue; } } } else { diff --git a/src/algorithm/media.rs b/src/algorithm/media.rs index 14552b1ce..7ffa541fc 100644 --- a/src/algorithm/media.rs +++ b/src/algorithm/media.rs @@ -31,13 +31,13 @@ pub enum SmartOutput { const MIN_AUTO_IMAGE_DIM: usize = 30; impl SmartOutput { - /// Convert a value to a SmartOutput + /// Convert a value to a `SmartOutput` /// /// Animations default to GIF pub fn from_value(value: Value, frame_rate: f64, backend: &dyn SysBackend) -> Self { Self::from_value_impl(value, frame_rate, false, backend) } - /// Convert a value to a SmartOutput + /// Convert a value to a `SmartOutput` /// /// Animations default to APNG pub fn from_value_prefer_apng(value: Value, frame_rate: f64, backend: &dyn SysBackend) -> Self { diff --git a/src/array.rs b/src/array.rs index 21e80bc43..75dae36ab 100644 --- a/src/array.rs +++ b/src/array.rs @@ -604,7 +604,7 @@ impl Array { row.meta.take_label(); return row; } - let row_count: usize = self.shape[..depth + 1].iter().product(); + let row_count: usize = self.shape[..=depth].iter().product(); if row >= row_count { panic!("row index out of bounds: {row} >= {row_count}"); } diff --git a/src/compile/data.rs b/src/compile/data.rs index 38a328b11..ed22fa6d6 100644 --- a/src/compile/data.rs +++ b/src/compile/data.rs @@ -428,7 +428,7 @@ impl Compiler { }; for field in &fields { match field.init.as_ref().map(|sn| sn.sig.args()) { - Some(0) => continue, + Some(0) => {} Some(1) | None => { constr_comment.push(' '); constr_comment.push_str(&field.name); diff --git a/src/cowslice.rs b/src/cowslice.rs index 3d5d706df..05772eec8 100644 --- a/src/cowslice.rs +++ b/src/cowslice.rs @@ -479,7 +479,7 @@ impl IntoIterator for CowSlice { } } -/// An iterator over a CowSlice +/// An iterator over a `CowSlice` pub struct CowSliceIntoIter { data: EcoVec, start: usize, diff --git a/src/grid_fmt.rs b/src/grid_fmt.rs index 65bc15524..4fbb28ad7 100644 --- a/src/grid_fmt.rs +++ b/src/grid_fmt.rs @@ -86,6 +86,10 @@ pub trait GridFmt: Sized { rows.map(|row| row.len()).max().unwrap_or(0) } /// Get SoA rows + #[expect( + clippy::doc_markdown, + reason = "SoA is just an acronym, not a type/trait name" + )] fn soa_rows(_arr: &Array) -> Option> { None } diff --git a/src/lsp.rs b/src/lsp.rs index 770646f02..a28a026f6 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -2083,7 +2083,7 @@ mod server { Span::Code(span) => path_locs(span, &path)?, Span::Builtin => err.meta.trace.iter().find_map(|frame| match &frame.span { Span::Code(span) => Some(span), - _ => None, + Span::Builtin => None, })?, }; Some(uiua_span_to_lsp(span, &doc.asm.inputs)) diff --git a/src/run.rs b/src/run.rs index f42639428..2343405e9 100644 --- a/src/run.rs +++ b/src/run.rs @@ -1744,7 +1744,7 @@ impl Uiua { /// A trait for types that can be used as argument specifiers for [`Uiua::pop`] /// -/// If the stack is empty, the error message will be "Stack was empty when getting {arg_name}" +/// If the stack is empty, the error message will be "Stack was empty when getting {`arg_name`}" pub trait StackArg { /// Get the name of the argument fn arg_name(self) -> String; diff --git a/src/sys/native.rs b/src/sys/native.rs index f440b66ba..abdca83f2 100644 --- a/src/sys/native.rs +++ b/src/sys/native.rs @@ -379,7 +379,7 @@ impl SysBackend for NativeSys { match b { #[cfg(feature = "raw_mode")] b'\r' if rawrrr::is_raw() => break, - b'\r' => continue, + b'\r' => {} b'\n' | 3 => break, b => buffer.push(b), } From f47c5b6aa4a40cf26a1af8a5ca8075913e08ffa7 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 17:30:19 +0300 Subject: [PATCH 09/21] lint: fix clippy::pedantic (6 entries) --- Cargo.toml | 3 -- pad/editor/src/backend.rs | 6 +-- parser/src/lex.rs | 6 +-- parser/src/parse.rs | 2 +- site/src/idioms.rs | 2 +- site/src/markdown.rs | 6 +-- site/src/primitive.rs | 2 +- src/algorithm/dyadic/combine.rs | 74 +++++++++++++++---------------- src/algorithm/dyadic/structure.rs | 28 ++++++------ src/algorithm/monadic/mod.rs | 35 +++++++-------- src/ffi.rs | 14 +++--- src/lsp.rs | 8 +--- 12 files changed, 84 insertions(+), 102 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index af3e06b38..39fd7b239 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,6 @@ dbg_macro = "warn" print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} -if_not_else = "allow" # 6 -manual_let_else = "allow" # 6 -single_char_pattern = "allow" # 6 needless_raw_string_hashes = "allow" # 7 unnecessary_wraps = "allow" # 7 unnested_or_patterns = "allow" # 8 diff --git a/pad/editor/src/backend.rs b/pad/editor/src/backend.rs index 4d72f4de3..01f2eda07 100644 --- a/pad/editor/src/backend.rs +++ b/pad/editor/src/backend.rs @@ -258,11 +258,7 @@ impl SysBackend for WebBackend { } fn file_write_all(&self, path: &Path, contents: &[u8]) -> Result<(), String> { FILES.with(|files| { - if !files.borrow().contains_key(path) { - files.borrow_mut().insert(path.into(), contents.to_vec()); - } else { - *files.borrow_mut().get_mut(path).unwrap() = contents.to_vec(); - } + files.borrow_mut().insert(path.into(), contents.to_vec()); }); Ok(()) } diff --git a/parser/src/lex.rs b/parser/src/lex.rs index b14ef80e5..d440c5536 100644 --- a/parser/src/lex.rs +++ b/parser/src/lex.rs @@ -1159,12 +1159,12 @@ impl<'a> Lexer<'a> { let has_2nd_subscript = self.next_char_exact(",") || self.next_chars_exact(["_"; 2]) || self.peek_char().is_some_and(is_formatted_subscript); - if !has_2nd_subscript { - self.end(Subscr(Subscript::numeric(n + num + m)), start); - } else { + if has_2nd_subscript { let sub_num = n + num + (m - 1).max(0); self.loc = before_last_2nd_chain; self.end(Subscr(Subscript::numeric(sub_num)), start); + } else { + self.end(Subscr(Subscript::numeric(n + num + m)), start); } } Some(_) => { diff --git a/parser/src/parse.rs b/parser/src/parse.rs index faabf0cd0..62fe7bb8e 100644 --- a/parser/src/parse.rs +++ b/parser/src/parse.rs @@ -1753,7 +1753,7 @@ impl Parser<'_> { loop { self.ignore_whitespace(); if let Some(span) = self.exact(Comment) { - let s = span.as_str(self.inputs, |s| s.trim_start_matches("#").trim().into()); + let s = span.as_str(self.inputs, |s| s.trim_start_matches('#').trim().into()); lines.push(span.sp(s)); } else if let Some(sem) = self.next_token_map(Token::as_semantic_comment) { semantic.insert(sem.value, sem.span); diff --git a/site/src/idioms.rs b/site/src/idioms.rs index 28cfc7feb..69222a157 100644 --- a/site/src/idioms.rs +++ b/site/src/idioms.rs @@ -45,7 +45,7 @@ fn aliases() -> impl IntoView { .map(|&s| view!({s}" ")) .collect::>() }{ - (p.aliases().iter().any(|a| a.contains("&")) || matches!(p, Primitive::Sys(_))) + (p.aliases().iter().any(|a| a.contains('&')) || matches!(p, Primitive::Sys(_))) .then(|| view!("Temporary")) }) }) diff --git a/site/src/markdown.rs b/site/src/markdown.rs index 8d92677fb..267b9835d 100644 --- a/site/src/markdown.rs +++ b/site/src/markdown.rs @@ -291,10 +291,10 @@ fn node_html<'a>(node: &'a AstNode<'a>) -> String { if let Some(prim) = Primitive::from_name(name).or_else(|| Primitive::from_name(&text)) { let symbol_class = format!("prim-glyph {}", prim_class(prim)); let symbol = prim.to_string(); - let name = if symbol != prim.name() { - format!(" {}", prim.name()) - } else { + let name = if symbol == prim.name() { "".to_string() + } else { + format!(" {}", prim.name()) }; format!( r#""); - let Some(end) = line.rfind("\"") else { + let Some(end) = line.rfind('"') else { continue; }; eprintln!("{line}"); diff --git a/src/algorithm/dyadic/combine.rs b/src/algorithm/dyadic/combine.rs index d165af3dd..df7bb413c 100644 --- a/src/algorithm/dyadic/combine.rs +++ b/src/algorithm/dyadic/combine.rs @@ -355,33 +355,7 @@ impl Array { }))? } - if self.shape[1..] != other.shape[1..] { - // Fill - match ctx.scalar_fill::() { - Ok(fill) => { - if map_keys.is_some() { - return Err(ctx.error(format!( - "Cannot {} {} map arrays", - Primitive::Fill, - Primitive::Join - ))); - } - let new_row_shape = max_shape(&self.shape[1..], &other.shape[1..]); - for (array, fill) in [(&mut self, fill.clone()), (&mut other, fill)] - { - let mut new_shape = new_row_shape.clone(); - new_shape.prepend(array.shape[0]); - array.fill_to_shape(&new_shape, fill); - } - } - Err(e) => { - return Err(C::fill_error(ctx.error(format!( - "Cannot join arrays of shapes {} and {}. {e}", - self.shape, other.shape - )))); - } - } - } else { + if self.shape[1..] == other.shape[1..] { // Set sorted flags match (self.row_count(), other.row_count()) { (0, 0) => { @@ -412,6 +386,32 @@ impl Array { } } } + } else { + // Fill + match ctx.scalar_fill::() { + Ok(fill) => { + if map_keys.is_some() { + return Err(ctx.error(format!( + "Cannot {} {} map arrays", + Primitive::Fill, + Primitive::Join + ))); + } + let new_row_shape = max_shape(&self.shape[1..], &other.shape[1..]); + for (array, fill) in [(&mut self, fill.clone()), (&mut other, fill)] + { + let mut new_shape = new_row_shape.clone(); + new_shape.prepend(array.shape[0]); + array.fill_to_shape(&new_shape, fill); + } + } + Err(e) => { + return Err(C::fill_error(ctx.error(format!( + "Cannot join arrays of shapes {} and {}. {e}", + self.shape, other.shape + )))); + } + } } if self.data.len() >= other.data.len() { @@ -1045,9 +1045,8 @@ impl Value { } } row_values = values.into_iter(); - let arr = match row_values.next().unwrap() { - Value::Num(arr) => arr, - _ => unreachable!(), + let Value::Num(arr) = row_values.next().unwrap() else { + unreachable!() }; if let Some(box_rank) = box_rank { Value::Box(arr.box_depth(box_rank)) @@ -1073,9 +1072,8 @@ impl Value { } } row_values = values.into_iter(); - let arr = match row_values.next().unwrap() { - Value::Byte(arr) => arr, - _ => unreachable!(), + let Value::Byte(arr) = row_values.next().unwrap() else { + unreachable!() }; if let Some(box_rank) = box_rank { Value::Box(arr.box_depth(box_rank)) @@ -1099,9 +1097,8 @@ impl Value { } } row_values = values.into_iter(); - let arr = match row_values.next().unwrap() { - Value::Complex(arr) => arr, - _ => unreachable!(), + let Value::Complex(arr) = row_values.next().unwrap() else { + unreachable!() }; if let Some(box_rank) = box_rank { Value::Box(arr.box_depth(box_rank)) @@ -1124,9 +1121,8 @@ impl Value { } } row_values = values.into_iter(); - let arr = match row_values.next().unwrap() { - Value::Char(arr) => arr, - _ => unreachable!(), + let Value::Char(arr) = row_values.next().unwrap() else { + unreachable!() }; if let Some(box_rank) = box_rank { Value::Box(arr.box_depth(box_rank)) diff --git a/src/algorithm/dyadic/structure.rs b/src/algorithm/dyadic/structure.rs index d3a2c988f..ab8ecc690 100644 --- a/src/algorithm/dyadic/structure.rs +++ b/src/algorithm/dyadic/structure.rs @@ -96,22 +96,20 @@ impl Value { Value::Num(arr) => { let mut index_data = Vec::with_capacity(arr.element_count()); for &n in &arr.data { - index_data.push(if n.fract() != 0.0 { - if filled { - isize::MAX - } else if n.fract().is_nan() { - return Err(env.error(format!( - "{} cannot be used as an index without a fill", - n.grid_string(false) - ))); - } else { - return Err(env.error(format!( - "Index must be an array of integers, but {} is not an integer", - n.grid_string(false) - ))); - } - } else { + index_data.push(if n.fract() == 0.0 { n as isize + } else if filled { + isize::MAX + } else if n.fract().is_nan() { + return Err(env.error(format!( + "{} cannot be used as an index without a fill", + n.grid_string(false) + ))); + } else { + return Err(env.error(format!( + "Index must be an array of integers, but {} is not an integer", + n.grid_string(false) + ))); }); } (&arr.shape, index_data) diff --git a/src/algorithm/monadic/mod.rs b/src/algorithm/monadic/mod.rs index 306a182d4..9f1af0359 100644 --- a/src/algorithm/monadic/mod.rs +++ b/src/algorithm/monadic/mod.rs @@ -222,9 +222,9 @@ impl Value { (0 | 1, Value::Char(arr)) => { let s: String = arr.data.iter().copied().collect(); match ( - s.strip_suffix("i").and_then(|s| s.split_once("r")), - s.strip_suffix("i").and_then(|s| s.split_once("+")), - s.strip_suffix("i").and_then(|s| s.split_once("-")), + s.strip_suffix('i').and_then(|s| s.split_once('r')), + s.strip_suffix('i').and_then(|s| s.split_once('+')), + s.strip_suffix('i').and_then(|s| s.split_once('-')), ) { (Some((re, im)), None, _) | (None, Some((re, im)), _) => { let re = parse_uiua_num(re.into(), env); @@ -374,8 +374,8 @@ impl Value { let parse_base_str = |mut s: &str| -> UiuaResult { if base == 64 { let mut s = s.to_string(); - s = s.replace("-", "+"); - s = s.replace("_", "/"); + s = s.replace('-', "+"); + s = s.replace('_', "/"); let mut num = 0.0; for (place, c) in s.chars().rev().enumerate() { @@ -409,7 +409,7 @@ impl Value { return Err(env.error("Number must have digits")); } - let fract = if let Some((num, sfract)) = s.split_once(".") { + let fract = if let Some((num, sfract)) = s.split_once('.') { if num.is_empty() && sfract.is_empty() { return Err(env.error("Number must have digits")); } @@ -533,7 +533,9 @@ impl Value { .map(|(i, c)| if i <= sigfigs { c } else { '0' }) .collect(); - let fract = if fract != 0.0 { + let fract = if fract == 0.0 { + String::new() + } else { let mut digits = ".".to_string(); for _ in 0..sigfigs - num.len() { fract *= base as f64; @@ -545,11 +547,9 @@ impl Value { ); fract %= 1.0; } - let digits = digits.trim_end_matches("0"); - let digits = digits.trim_end_matches("."); + let digits = digits.trim_end_matches('0'); + let digits = digits.trim_end_matches('.'); digits.to_string() - } else { - String::new() }; if num.is_empty() { @@ -2287,17 +2287,16 @@ impl Array { let max = r.max(g).max(b); let min = r.min(g).min(b); let delta = max - min; - let recip_delta = if delta != 0.0 { 1.0 / delta } else { 0.0 }; - let h = if delta != 0.0 { + let h = if delta == 0.0 { + 0.0 + } else { (TAU * if max == r { - ((g - b) * recip_delta).rem_euclid(6.0) + ((g - b) / delta).rem_euclid(6.0) } else if max == g { - (b - r).mul_add(recip_delta, 2.0) + (b - r) / delta + 2.0 } else { - (r - g).mul_add(recip_delta, 4.0) + (r - g) / delta + 4.0 }) / 6.0 - } else { - 0.0 }; let s = if max == 0.0 { 0.0 } else { 1.0 - min / max }; let v = max; diff --git a/src/ffi.rs b/src/ffi.rs index 49af651a4..f231672db 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -94,11 +94,11 @@ impl FromStr for FfiType { let input = input.trim(); // Pointer - if let Some(ptr) = input.strip_suffix("*") { + if let Some(ptr) = input.strip_suffix('*') { return Ok(Self::Ptr(ptr.parse::()?.into())); } - if let Some((arr, len)) = input.strip_suffix("]").and_then(|s| s.rsplit_once("[")) { + if let Some((arr, len)) = input.strip_suffix(']').and_then(|s| s.rsplit_once('[')) { let len = len.parse::().map_err(|e| e.to_string())?; let ty = arr.parse::()?; if len == 0 { @@ -109,7 +109,7 @@ impl FromStr for FfiType { let (unsigned, input) = match input .strip_prefix("unsigned ") - .or_else(|| input.strip_prefix("u")) + .or_else(|| input.strip_prefix('u')) { Some(scalar) => (true, scalar), None => (false, input), @@ -137,9 +137,9 @@ impl FromStr for FfiType { // Struct if let Some(body) = input - .strip_prefix("{") - .and_then(|s| s.strip_suffix("}")) - .map(|s| s.trim_end_matches(";")) + .strip_prefix('{' ) + .and_then(|s| s.strip_suffix('}')) + .map(|s| s.trim_end_matches(';')) { let mut depth = 0_usize; let mut field = String::new(); @@ -196,7 +196,7 @@ impl FromStr for FfiArg { }; // Lists - if let Some((arg, len_index)) = input.split_once(":") { + if let Some((arg, len_index)) = input.split_once(':') { let len_index = Some( len_index .trim() diff --git a/src/lsp.rs b/src/lsp.rs index a28a026f6..d1c751a69 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -1314,9 +1314,7 @@ mod server { } let doc_uri = ¶ms.text_document_position.text_document.uri; - let doc = if let Some(doc) = self.doc(doc_uri) { - doc - } else { + let Some(doc) = self.doc(doc_uri) else { return Ok(None); }; let (line, col) = lsp_pos_to_uiua(params.text_document_position.position, &doc.input); @@ -1432,9 +1430,7 @@ mod server { &self, params: DocumentFormattingParams, ) -> Result>> { - let doc = if let Some(doc) = self.doc(¶ms.text_document.uri) { - doc - } else { + let Some(doc) = self.doc(¶ms.text_document.uri) else { return Ok(None); }; match format_str(&doc.input, &FormatConfig::find().unwrap_or_default()) { From 007bba83ef5239958629ea40175a0f1e351832f7 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 18:29:44 +0300 Subject: [PATCH 10/21] lint: fix clippy::pedantic (7 entries) --- Cargo.toml | 2 -- site/src/main.rs | 2 +- site/src/markdown.rs | 2 +- site/src/tutorial.rs | 4 ++-- src/algorithm/groups.rs | 22 +++++++++++----------- src/check.rs | 41 ++++++++++++++++++++--------------------- src/compile/binding.rs | 8 ++++---- src/compile/data.rs | 11 +++++------ src/compile/mod.rs | 28 ++++++++++++++-------------- src/compile/modifier.rs | 5 +---- src/format.rs | 8 ++++---- src/run_prim.rs | 9 ++++----- src/sys/native.rs | 10 +++++----- 13 files changed, 72 insertions(+), 80 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 39fd7b239..3cf4c66b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,8 +17,6 @@ dbg_macro = "warn" print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} -needless_raw_string_hashes = "allow" # 7 -unnecessary_wraps = "allow" # 7 unnested_or_patterns = "allow" # 8 borrow_as_ptr = "allow" # 9 explicit_iter_loop = "allow" # 9 diff --git a/site/src/main.rs b/site/src/main.rs index 5c09d32bd..3f9de5b59 100644 --- a/site/src/main.rs +++ b/site/src/main.rs @@ -246,7 +246,7 @@ pub fn MainPage() -> impl IntoView { rich_prim( Under, "for modifying only part of an array (among other things)", - r#"⍜(↙2|×10) 1_2_3_4_5"#, + r"⍜(↙2|×10) 1_2_3_4_5", ), ]; diff --git a/site/src/markdown.rs b/site/src/markdown.rs index 267b9835d..04f5b6662 100644 --- a/site/src/markdown.rs +++ b/site/src/markdown.rs @@ -60,7 +60,7 @@ pub fn markdown_html(text: &str) -> String { .replace("``", "` `") .replace("", "```"); let root = parse_document(&arena, &text, &options()); - let body = format!(r#"
{}
"#, node_html(root)); + let body = format!(r"
{}
", node_html(root)); let head = r#" diff --git a/site/src/tutorial.rs b/site/src/tutorial.rs index 1deb070d6..7d44e5e5c 100644 --- a/site/src/tutorial.rs +++ b/site/src/tutorial.rs @@ -1435,9 +1435,9 @@ fn TutorialThinkingWithArrays() -> impl IntoView { number=2 prompt="returns the last word of a string" example=r#""What's the last word?""# - answer=r#"▽ ⍜⇌\× ⊸≠@ "# + answer=r"▽ ⍜⇌\× ⊸≠@ " tests={&[r#""Um, I um, arrays""#, r#""I like trains""#]} - hidden=r#"Wow"#/> + hidden=r"Wow"/> ) -> R, - ) -> UiuaResult> { + ) -> EcoVec { let haystack = self.data.as_slice(); let delim_slice = delim.data.as_slice(); if delim_slice.is_empty() { - return Ok(eco_vec![f(self.data.clone())]); + return eco_vec![f(self.data.clone())]; } let mut curr = 0; let mut data = EcoVec::new(); @@ -136,7 +136,7 @@ where data.push(f(CowSlice::new())); } } - Ok(data) + data } } diff --git a/src/check.rs b/src/check.rs index cb06fb6b6..ba2425013 100644 --- a/src/check.rs +++ b/src/check.rs @@ -169,9 +169,8 @@ impl VirtualEnv { fn nodes(&mut self, nodes: &[Node]) -> Result<(), SigCheckError> { nodes.iter().try_for_each(|node| self.node(node)) } - fn sig_node(&mut self, sn: &SigNode) -> Result<(), SigCheckError> { + fn sig_node(&mut self, sn: &SigNode) { self.handle_sig(sn.sig); - Ok(()) } fn node(&mut self, node: &Node) -> Result<(), SigCheckError> { use ImplPrimitive::*; @@ -294,7 +293,7 @@ impl VirtualEnv { } Each | Rows | Inventory => { let [f] = get_args_nodes(args)?; - self.sig_node(f)?; + self.sig_node(f); } Table | Tuples => { let [sig] = get_args(args)?; @@ -318,7 +317,7 @@ impl VirtualEnv { Repeat => { let [f] = get_args_nodes(args)?; self.pop(); - self.repeat(f)?; + self.repeat(f); } Do => { let [body, cond] = get_args(args)?; @@ -383,38 +382,38 @@ impl VirtualEnv { Both => { let [f] = get_args_nodes(args)?; self.stack.pop_n(f.sig.args()); - self.sig_node(f)?; + self.sig_node(f); self.stack.push_n(f.sig.args()); - self.sig_node(f)?; + self.sig_node(f); } Dip => { let [f] = get_args_nodes(args)?; self.pop(); - self.sig_node(f)?; + self.sig_node(f); self.push(); } Gap => { let [f] = get_args_nodes(args)?; self.pop(); - self.sig_node(f)?; + self.sig_node(f); } Reach => { let [f] = get_args_nodes(args)?; self.pop(); self.pop(); self.push(); - self.sig_node(f)?; + self.sig_node(f); } On => { let [f] = get_args_nodes(args)?; self.pop(); self.push(); - self.sig_node(f)?; + self.sig_node(f); self.push(); } By => { let [f] = get_args_nodes(args)?; - self.sig_node(f)?; + self.sig_node(f); self.push(); } Above | Below => { @@ -458,7 +457,7 @@ impl VirtualEnv { let [sn] = get_args_nodes(args)?; let args = sn.sig.args().max(n); self.handle_args_outputs(args, args); - self.sig_node(sn)?; + self.sig_node(sn); self.handle_args_outputs(0, n); } &DipN(n) => { @@ -483,11 +482,11 @@ impl VirtualEnv { )); } self.pop(); - self.repeat(f)?; + self.repeat(f); } RepeatCountConvergence => { let [f] = get_args_nodes(args)?; - self.repeat(f)?; + self.repeat(f); self.push(); } UnFill | SidedFill(_) => self.fill(args)?, @@ -508,7 +507,7 @@ impl VirtualEnv { } EachSub(_) => { let [f] = get_args_nodes(args)?; - self.sig_node(f)?; + self.sig_node(f); } RowsSub(sub, _) => { let [mut f] = get_args(args)?; @@ -522,7 +521,7 @@ impl VirtualEnv { UndoRows | UndoInventory => { let [f] = get_args_nodes(args)?; self.stack.pop(); - self.sig_node(f)?; + self.sig_node(f); } UnScan => self.handle_args_outputs(1, 1), SplitBy | SplitByScalar | SplitByKeepEmpty => { @@ -591,18 +590,18 @@ impl VirtualEnv { fn fill(&mut self, args: &[SigNode]) -> Result<(), SigCheckError> { let [fill, f] = get_args_nodes(args)?; if fill.sig.outputs() > 0 || fill.sig.args() > 0 && fill.sig.outputs() != 0 { - self.sig_node(fill)?; + self.sig_node(fill); } self.handle_args_outputs(fill.sig.outputs(), 0); - self.sig_node(f) + self.sig_node(f); + Ok(()) } - fn repeat(&mut self, sn: &SigNode) -> Result<(), SigCheckError> { + fn repeat(&mut self, sn: &SigNode) { let sig = sn.sig; - self.sig_node(sn)?; + self.sig_node(sn); if sig.outputs() > sig.args() { self.stack.pop_n(sig.args()); } - Ok(()) } } diff --git a/src/compile/binding.rs b/src/compile/binding.rs index a2324fb6d..5471300e0 100644 --- a/src/compile/binding.rs +++ b/src/compile/binding.rs @@ -456,7 +456,7 @@ impl Compiler { sig = declared_sig.value; } let func = make_fn(node, sig, self); - self.compile_bind_function(name, local, func, spandex, meta)?; + self.compile_bind_function(name, local, func, spandex, meta); } else { // Binds some |0.1 code self.compile_bind_const(name, local, None, spandex, meta); @@ -468,7 +468,7 @@ impl Compiler { } else { // Binding is a normal function let func = make_fn(node, sig, self); - self.compile_bind_function(name, local, func, spandex, meta)?; + self.compile_bind_function(name, local, func, spandex, meta); } self.code_meta.function_sigs.insert( @@ -518,8 +518,8 @@ impl Compiler { }; // Compile items let (module, ()) = self.in_scope(scope_kind, |comp| { - comp.items(m.items, ItemCompMode::TopLevel)?; - comp.end_enum()?; + comp.items(m.items, ItemCompMode::TopLevel); + comp.end_enum(); Ok(()) })?; if let Some((name, local)) = name_and_local { diff --git a/src/compile/data.rs b/src/compile/data.rs index ed22fa6d6..d4317d1ee 100644 --- a/src/compile/data.rs +++ b/src/compile/data.rs @@ -327,7 +327,7 @@ impl Compiler { comment: Some(DocComment::from(comment.as_str())), ..Default::default() }; - self.compile_bind_function(field_name.clone(), local, func, span, meta)?; + self.compile_bind_function(field_name.clone(), local, func, span, meta); self.code_meta .global_references .insert(field.name_span.clone(), local.index); @@ -552,7 +552,7 @@ impl Compiler { comment: def_comment, ..Default::default() }; - self.compile_bind_function("Call".into(), local, func, span, meta)?; + self.compile_bind_function("Call".into(), local, func, span, meta); } if let Some((local, func, span)) = args_function_stuff { let meta = BindingMeta { @@ -563,7 +563,7 @@ impl Compiler { })), ..Default::default() }; - self.compile_bind_function("Args".into(), local, func, span, meta)?; + self.compile_bind_function("Args".into(), local, func, span, meta); } // Bind the constructor @@ -571,11 +571,11 @@ impl Compiler { comment: Some(DocComment::from(constr_comment.as_str())), ..Default::default() }; - self.compile_bind_function(constructor_name, constr_local, constructor_func, span, meta)?; + self.compile_bind_function(constructor_name, constr_local, constructor_func, span, meta); Ok(()) } - pub(super) fn end_enum(&mut self) -> UiuaResult { + pub(super) fn end_enum(&mut self) { // Add Variants binding if !self.scope.data_variants.is_empty() && !self.scope.names.get("Variants").is_some_and(|ln| ln.public) @@ -596,6 +596,5 @@ impl Compiler { }; self.compile_bind_const("Variants".into(), local, Some(value), 0, meta); } - Ok(()) } } diff --git a/src/compile/mod.rs b/src/compile/mod.rs index da7d2d612..9ab971628 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -521,7 +521,7 @@ impl Compiler { } // Collect errors match res { - Err(e) | Ok(Err(e)) => { + Err(e) => { self.asm.root.truncate(node_start); self.errors.push(e); } @@ -565,7 +565,7 @@ enum ItemCompMode { } impl Compiler { - fn items(&mut self, items: Vec, mode: ItemCompMode) -> UiuaResult { + fn items(&mut self, items: Vec, mode: ItemCompMode) { // Set scope comment let mut started = false; let mut comment = String::new(); @@ -625,7 +625,6 @@ impl Compiler { item_errored = true; } } - Ok(()) } fn item( &mut self, @@ -797,7 +796,7 @@ impl Compiler { function: Function, span: usize, meta: BindingMeta, - ) -> UiuaResult { + ) { self.scope.names.insert(name.clone(), local); let span = if span == 0 { Some(CodeSpan::literal(name)) @@ -806,7 +805,6 @@ impl Compiler { }; self.asm .add_binding_at(local, BindingKind::Func(function), span, meta); - Ok(()) } fn compile_bind_const( &mut self, @@ -1404,8 +1402,9 @@ impl Compiler { } let root_start = self.asm.root.len(); self.in_scope(ScopeKind::Function, |comp| { - comp.items(item_lines, ItemCompMode::Function)?; - comp.items(word_lines, ItemCompMode::Function) + comp.items(item_lines, ItemCompMode::Function); + comp.items(word_lines, ItemCompMode::Function); + Ok(()) })?; let inner = self.asm.root.split_off(root_start); // Calculate length @@ -2028,7 +2027,8 @@ impl Compiler { fn func(&mut self, func: Func, span: CodeSpan) -> UiuaResult { let root_start = self.asm.root.len(); self.in_scope(ScopeKind::Function, |comp| { - comp.items(func.lines, ItemCompMode::Function) + comp.items(func.lines, ItemCompMode::Function); + Ok(()) })?; let mut root = self.asm.root.split_off(root_start); @@ -2755,22 +2755,22 @@ impl Compiler { /// # Errors /// Returns an error in the binding name is not valid pub fn bind_function(&mut self, name: impl Into, function: Function) -> UiuaResult { - self.bind_function_with_meta(name, function, BindingMeta::default()) + self.bind_function_with_meta(name, function, BindingMeta::default()); + Ok(()) } fn bind_function_with_meta( &mut self, name: impl Into, function: Function, meta: BindingMeta, - ) -> UiuaResult { + ) { let name = name.into(); let local = LocalName { index: self.next_global, public: true, }; self.next_global += 1; - self.compile_bind_function(name, local, function, 0, meta)?; - Ok(()) + self.compile_bind_function(name, local, function, 0, meta); } /// Create and bind a function in the current scope /// @@ -2788,15 +2788,15 @@ impl Compiler { if let Some(index) = self.externals.get(&name).copied() { let df = self.create_dynamic_function(signature.into(), f); self.asm.functions.make_mut()[index] = Node::Dynamic(df); - Ok(()) } else { let function = self.create_function(signature, f); let meta = BindingMeta { external: true, ..Default::default() }; - self.bind_function_with_meta(name, function, meta) + self.bind_function_with_meta(name, function, meta); } + Ok(()) } fn sig_of(&self, node: &Node, span: &CodeSpan) -> UiuaResult { node.sig().map_err(|e| { diff --git a/src/compile/modifier.rs b/src/compile/modifier.rs index c79d4368b..c5203b2f3 100644 --- a/src/compile/modifier.rs +++ b/src/compile/modifier.rs @@ -1877,9 +1877,7 @@ impl Compiler { return Err(self.error(span.clone(), "Compile-time evaluation recurs too deep")); } let errors_before = self.errors.len(); - let res = self - .items(items, ItemCompMode::CodeMacro) - .map_err(|e| e.trace_macro(name, span.clone())); + self.items(items, ItemCompMode::CodeMacro); let errors_after = self.errors.len(); self.comptime_depth -= 1; self.pre_eval_mode = pre_eval_mod; @@ -1888,7 +1886,6 @@ impl Compiler { return Ok(Node::empty()); } let mut node = self.asm.root.split_off(root_node_len); - res?; if errors_after > errors_before { node = Node::empty(); } diff --git a/src/format.rs b/src/format.rs index 6ba99efc7..d10aef2fd 100644 --- a/src/format.rs +++ b/src/format.rs @@ -114,7 +114,7 @@ macro_rules! create_config { #[test] fn generate_format_cfg_docs() { paste! { - let mut s: String = r#" + let mut s: String = r" # Uiua Formatter Configuration You can configure Uiua's formatter by creating a file called `.fmt.ua` in the directory from which you run the interpreter. This configuration file is also a Uiua program. @@ -123,14 +123,14 @@ Configuration options are specified by binding values to specific names. Example with default values: ```uiua -"#.into(); +".into(); $( s.push_str(&format!("{} ← {}\n", stringify!([<$name:camel>]), default_to_uiua!($default))); )* - s.push_str(r#"``` + s.push_str(r"``` The following configuration options are available: -"#); +"); $( s.push_str(&format!("### {}\n", stringify!([<$name:camel>]))); diff --git a/src/run_prim.rs b/src/run_prim.rs index 81551caa6..71d81fd84 100644 --- a/src/run_prim.rs +++ b/src/run_prim.rs @@ -288,7 +288,7 @@ pub fn run_prim_func(prim: &Primitive, env: &mut Uiua) -> UiuaResult { vals.map(keys, env)?; env.push(vals); } - Primitive::Stack => stack(env, false)?, + Primitive::Stack => stack(env, false), Primitive::Regex => { regex(env)?; // NOTE: if you want to expose the match locations, n.t. they are given in bytes rather than codepoints @@ -695,7 +695,7 @@ impl ImplPrimitive { ImplPrimitive::UnFix => env.monadic_mut_env(Value::unfix)?, ImplPrimitive::UnShape => env.monadic_ref_env(Value::unshape)?, ImplPrimitive::StackN { n, inverse } => stack_n(env, *n, *inverse)?, - ImplPrimitive::UnStack => stack(env, true)?, + ImplPrimitive::UnStack => stack(env, true), ImplPrimitive::Primes => env.monadic_ref_env(Value::primes)?, ImplPrimitive::UnBox => { let val = env.pop(1)?; @@ -1774,7 +1774,7 @@ fn stack_n(env: &mut Uiua, n: usize, inverse: bool) -> UiuaResult { Ok(()) } -fn stack(env: &Uiua, inverse: bool) -> UiuaResult { +fn stack(env: &Uiua, inverse: bool) { let span = if inverse { format!("{}{} {}", Primitive::Un, Primitive::Stack, env.span()) } else { @@ -1807,7 +1807,6 @@ fn stack(env: &Uiua, inverse: bool) -> UiuaResult { env.rt.backend.print_str_trace("╴"); } env.rt.backend.print_str_trace("\n"); - Ok(()) } fn dump(ops: Ops, env: &mut Uiua, inverse: bool) -> UiuaResult { @@ -2369,7 +2368,7 @@ mod tests { literal_names.reverse(); let literal_names = literal_names.join(""); format!( - r#"[{glyphs}]|(? Result { + fn new(index: usize) -> Self { use nokhwa::{ pixel_format::RgbFormat, utils::{CameraIndex, RequestedFormat, RequestedFormatType}, @@ -139,10 +139,10 @@ impl WebcamChannel { sleep(); } }); - Ok(Self { + Self { send: req_send, recv: image_recv, - }) + } } } @@ -1134,7 +1134,7 @@ impl SysBackend for NativeSys { fn webcam_capture(&self, index: usize) -> Result { let cam_channels = &NATIVE_SYS.cam_channels; if !cam_channels.contains_key(&index) { - let ch = WebcamChannel::new(index)?; + let ch = WebcamChannel::new(index); cam_channels.insert(index, ch); } let ch = cam_channels.get_mut(&index).unwrap(); @@ -1145,7 +1145,7 @@ impl SysBackend for NativeSys { Err("Failed to interact with webcam".into()) } } else { - let ch = WebcamChannel::new(index)?; + let ch = WebcamChannel::new(index); cam_channels.insert(index, ch); let ch = cam_channels.get_mut(&index).unwrap(); if ch.send.send(()).is_ok() { From 21ee1b2f22a462baef053f131d83640a09cab971 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 18:30:47 +0300 Subject: [PATCH 11/21] lint: fix clippy::pedantic (8-9 entries) --- Cargo.toml | 5 --- pad/editor/src/lib.rs | 2 +- pad/editor/src/utils.rs | 2 +- site/src/markdown.rs | 6 +-- src/algorithm/dyadic/search.rs | 4 +- src/algorithm/encode.rs | 5 +-- src/algorithm/ga.rs | 24 +++++------ src/algorithm/media.rs | 3 +- src/algorithm/monadic/mod.rs | 50 ++++++++++++----------- src/algorithm/reduce.rs | 8 ++-- src/assembly.rs | 2 +- src/check.rs | 8 +--- src/compile/invert/mod.rs | 2 +- src/compile/invert/un.rs | 5 +-- src/compile/mod.rs | 4 +- src/compile/modifier.rs | 73 +++++++++++++++++----------------- src/format.rs | 2 +- src/grid_fmt.rs | 2 +- src/lib.rs | 2 +- src/lsp.rs | 2 +- src/run.rs | 6 +-- 21 files changed, 102 insertions(+), 115 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3cf4c66b6..20181c1ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,11 +17,6 @@ dbg_macro = "warn" print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} -unnested_or_patterns = "allow" # 8 -borrow_as_ptr = "allow" # 9 -explicit_iter_loop = "allow" # 9 -ignored_unit_patterns = "allow" # 9 -many_single_char_names = "allow" # 9 single_match_else = "allow" # 11 manual_string_new = "allow" # 12 trivially_copy_pass_by_ref = "allow" # 12 diff --git a/pad/editor/src/lib.rs b/pad/editor/src/lib.rs index 8ef4ac7f7..aac41d4af 100644 --- a/pad/editor/src/lib.rs +++ b/pad/editor/src/lib.rs @@ -702,7 +702,7 @@ pub fn Editor<'a>( let first_char = *chars.first().unwrap(); let class = char_class(first_char); let mut encountered_space = false; - for &c in chars.iter() { + for &c in &chars { if c.is_whitespace() && c != '\n' || char_class(c) == class && !encountered_space { diff --git a/pad/editor/src/utils.rs b/pad/editor/src/utils.rs index 1c180d23e..1e1c7ebeb 100644 --- a/pad/editor/src/utils.rs +++ b/pad/editor/src/utils.rs @@ -1694,7 +1694,7 @@ pub fn element(id: &str) -> T { pub fn format_insert_file_code(path: &Path, content: Vec) -> String { let function = match path.extension().and_then(|ext| ext.to_str()) { Some("ua") => "~", - Some("txt") | Some("md") | Some("json") | None => "&fras", + Some("txt" | "md" | "json") | None => "&fras", _ => "&frab", }; diff --git a/site/src/markdown.rs b/site/src/markdown.rs index 04f5b6662..1b0803926 100644 --- a/site/src/markdown.rs +++ b/site/src/markdown.rs @@ -22,7 +22,7 @@ pub fn Fetch, F: Fn(&str) -> View + 'static>(src: S, f: F) -> im let (src, _) = create_signal(src); let once = create_resource( || (), - move |_| async move { fetch(&src.get_untracked()).await.unwrap() }, + move |()| async move { fetch(&src.get_untracked()).await.unwrap() }, ); view! {{ move || match once.get() { @@ -345,7 +345,7 @@ fn node_html<'a>(node: &'a AstNode<'a>) -> String { line.push_str(&" ".repeat(max_len - line_len)); } match comp.load_str(line).and_then(|comp| env.run_compiler(comp)) { - Ok(_) => { + Ok(()) => { let values = env.take_stack(); if !values.is_empty() && !values.iter().any(|v| v.shape.elements() > 200) { let formatted: Vec = values.iter().map(Value::show).collect(); @@ -467,7 +467,7 @@ fn text_code_blocks() { .load_str(&block) .and_then(|comp| env.run_compiler(comp)); let failure_report = match res { - Ok(_) => comp + Ok(()) => comp .take_diagnostics() .into_iter() .next() diff --git a/src/algorithm/dyadic/search.rs b/src/algorithm/dyadic/search.rs index 94ce9f545..9033dd58f 100644 --- a/src/algorithm/dyadic/search.rs +++ b/src/algorithm/dyadic/search.rs @@ -503,9 +503,7 @@ impl Array { if haystack.shape.iter().all(|&d| d > 0) { 'windows: loop { // Reset curr - for i in curr.iter_mut() { - *i = 0; - } + curr.fill(0); // Search the window whose top-left is the current corner 'items: loop { // Get index for the current item in the haystack diff --git a/src/algorithm/encode.rs b/src/algorithm/encode.rs index 796d8bb6e..e589cf950 100644 --- a/src/algorithm/encode.rs +++ b/src/algorithm/encode.rs @@ -268,10 +268,7 @@ impl Value { let mut rows = Vec::new(); for result in reader.records() { let record = result.map_err(|e| env.error(e))?; - let mut row = EcoVec::new(); - for field in record.iter() { - row.push(Boxed(field.into())); - } + let row: EcoVec<_> = record.iter().map(|x| Boxed(x.into())).collect(); rows.push(Array::new(row.len(), row)); } Array::from_row_arrays(rows, env).map(Into::into) diff --git a/src/algorithm/ga.rs b/src/algorithm/ga.rs index ff866ab1c..7b32d5c20 100644 --- a/src/algorithm/ga.rs +++ b/src/algorithm/ga.rs @@ -367,9 +367,9 @@ fn fast_dyadic_complex( drop(b); for chunk in a.data.as_mut_slice().chunks_exact_mut(2) { let [ar, ai] = [chunk[0], chunk[1]]; - let [r, i] = f(ar, ai, ar, ai); - chunk[0] = r; - chunk[1] = i; + let [real, imag] = f(ar, ai, ar, ai); + chunk[0] = real; + chunk[1] = imag; } Ok(a) } else { @@ -381,9 +381,9 @@ fn fast_dyadic_complex( .zip(b.data.as_mut_slice().chunks_exact_mut(2)) { let [ar, ai, br, bi] = [a[0], a[1], b[0], b[1]]; - let [r, i] = f(ar, ai, br, bi); - b[0] = r; - b[1] = i; + let [real, imag] = f(ar, ai, br, bi); + b[0] = real; + b[1] = imag; } Ok(b) } @@ -391,9 +391,9 @@ fn fast_dyadic_complex( let [br, bi] = [b.data[0], b.data[1]]; for a in a.data.as_mut_slice().chunks_exact_mut(2) { let [ar, ai] = [a[0], a[1]]; - let [r, i] = f(ar, ai, br, bi); - a[0] = r; - a[1] = i; + let [real, imag] = f(ar, ai, br, bi); + a[0] = real; + a[1] = imag; } Ok(a) } @@ -401,9 +401,9 @@ fn fast_dyadic_complex( let [ar, ai] = [a.data[0], a.data[1]]; for b in b.data.as_mut_slice().chunks_exact_mut(2) { let [br, bi] = [b[0], b[1]]; - let [r, i] = f(ar, ai, br, bi); - b[0] = r; - b[1] = i; + let [real, imag] = f(ar, ai, br, bi); + b[0] = real; + b[1] = imag; } Ok(b) } diff --git a/src/algorithm/media.rs b/src/algorithm/media.rs index 7ffa541fc..1a663a8f9 100644 --- a/src/algorithm/media.rs +++ b/src/algorithm/media.rs @@ -849,6 +849,7 @@ builtin_params!( (Camera, "The position of the camera"), ); +#[expect(clippy::many_single_char_names, reason = "TODO")] pub(crate) fn voxels(val: &Value, env: &mut Uiua) -> UiuaResult { let args = take(&mut env.rt.set_args); let converted: Array; @@ -1482,7 +1483,7 @@ fn layout_text_impl(size: Value, text: Value, env: &mut Uiua) -> UiuaResult [bg.data[0], bg.data[0], bg.data[0], 1.0], - [3] | [4] => { + [3 | 4] => { let alpha = bg.data.get(3).copied().unwrap_or(1.0); [bg.data[0], bg.data[1], bg.data[2], alpha] } diff --git a/src/algorithm/monadic/mod.rs b/src/algorithm/monadic/mod.rs index 9f1af0359..090e48f45 100644 --- a/src/algorithm/monadic/mod.rs +++ b/src/algorithm/monadic/mod.rs @@ -1136,8 +1136,8 @@ impl Array { for i in 0..chunk_row_count / 2 { let left = i * chunk_row_len; let right = (chunk_row_count - i - 1) * chunk_row_len; - let left = &mut data[left] as *mut T; - let right = &mut data[right] as *mut T; + let left = &raw mut data[left]; + let right = &raw mut data[right]; unsafe { ptr::swap_nonoverlapping(left, right, chunk_row_len); } @@ -2287,7 +2287,7 @@ impl Array { let max = r.max(g).max(b); let min = r.min(g).min(b); let delta = max - min; - let h = if delta == 0.0 { + let hue = if delta == 0.0 { 0.0 } else { (TAU * if max == r { @@ -2298,11 +2298,11 @@ impl Array { (r - g) / delta + 4.0 }) / 6.0 }; - let s = if max == 0.0 { 0.0 } else { 1.0 - min / max }; - let v = max; - rgb[0] = h; - rgb[1] = s; - rgb[2] = v; + let sat = if max == 0.0 { 0.0 } else { 1.0 - min / max }; + let val = max; + rgb[0] = hue; + rgb[1] = sat; + rgb[2] = val; } self.meta.take_sorted_flags(); self.validate(); @@ -2319,10 +2319,10 @@ impl Array { } let channels = *self.shape.last().unwrap(); for hsv in self.data.as_mut_slice().chunks_exact_mut(channels) { - let [h, s, v, ..] = *hsv else { + let [hue, sat, val, ..] = *hsv else { unreachable!(); }; - let [r, g, b] = hsv_to_rgb(h, s, v); + let [r, g, b] = hsv_to_rgb(hue, sat, val); hsv[0] = r; hsv[1] = g; hsv[2] = b; @@ -2333,20 +2333,22 @@ impl Array { } } -pub(crate) fn hsv_to_rgb(h: f64, s: f64, v: f64) -> [f64; 3] { - let h = h / TAU * 6.0; - let i = h.floor() as isize; - let f = h - i as f64; - let p = v * (1.0 - s); - let q = v * (1.0 - f * s); - let t = v * (1.0 - (1.0 - f) * s); - match i.rem_euclid(6) { - 0 => [v, t, p], - 1 => [q, v, p], - 2 => [p, v, t], - 3 => [p, q, v], - 4 => [t, p, v], - _ => [v, p, q], +pub(crate) fn hsv_to_rgb(hue: f64, sat: f64, val: f64) -> [f64; 3] { + let hue = hue / TAU * 6.0; + let sect = hue.floor() as isize; + let f = hue - sect as f64; + let chroma = val * sat; + let min = val - chroma; + let mid1 = val - f * chroma; + let mid0 = val - (1.0 - f) * chroma; + match sect.rem_euclid(6) { + 0 => [val, mid0, min], + 1 => [mid1, val, min], + 2 => [min, val, mid0], + 3 => [min, mid1, val], + 4 => [mid0, min, val], + 5 => [val, min, mid1], + _ => unreachable!(), } } diff --git a/src/algorithm/reduce.rs b/src/algorithm/reduce.rs index 7e59c5645..0fd357c72 100644 --- a/src/algorithm/reduce.rs +++ b/src/algorithm/reduce.rs @@ -834,7 +834,7 @@ where return arr; } let mut acc = arr.data[0]; - for val in arr.data.as_mut_slice()[1..].iter_mut() { + for val in &mut arr.data.as_mut_slice()[1..] { acc = f(acc, *val); *val = acc; } @@ -1019,10 +1019,8 @@ where return arr; } let mut acc = arr.data[0]; - for val in arr.data.as_mut_slice()[1..].iter_mut() { - let temp = *val; - *val = f(acc, *val); - acc = temp; + for val in &mut arr.data.as_mut_slice()[1..] { + acc = std::mem::replace(val, f(acc, *val)); } arr } diff --git a/src/assembly.rs b/src/assembly.rs index c5bb9c3df..084632136 100644 --- a/src/assembly.rs +++ b/src/assembly.rs @@ -249,7 +249,7 @@ impl Assembly { /// Serialize the assembly into a `.uasm` file pub fn to_uasm(&self) -> String { let mut uasm = String::new(); - for node in self.root.iter() { + for node in &self.root { uasm.push_str(&serde_json::to_string(node).unwrap()); uasm.push('\n'); } diff --git a/src/check.rs b/src/check.rs index ba2425013..e1140ea13 100644 --- a/src/check.rs +++ b/src/check.rs @@ -207,9 +207,7 @@ impl VirtualEnv { self.handle_args_outputs(1, parts.len().saturating_sub(1)) } Node::Unpack { count, .. } => self.handle_args_outputs(1, *count), - Node::ImplMod(Astar, args, _) - | Node::ImplMod(AstarFirst, args, _) - | Node::ImplMod(AstarSignLen, args, _) => { + Node::ImplMod(Astar | AstarFirst | AstarSignLen, args, _) => { self.pop(); let [neighbors, heuristic, is_goal] = get_args(args)?; let has_costs = neighbors.outputs() == 2; @@ -243,9 +241,7 @@ impl VirtualEnv { .saturating_sub(1); self.handle_args_outputs(args, has_costs as usize); } - Node::Mod(Path, args, _) - | Node::ImplMod(PathFirst, args, _) - | Node::ImplMod(PathSignLen, args, _) => { + Node::Mod(Path, args, _) | Node::ImplMod(PathFirst | PathSignLen, args, _) => { self.pop(); let [neighbors, is_goal] = get_args(args)?; let has_costs = neighbors.outputs() == 2; diff --git a/src/compile/invert/mod.rs b/src/compile/invert/mod.rs index 842b9f4cc..3124608f1 100644 --- a/src/compile/invert/mod.rs +++ b/src/compile/invert/mod.rs @@ -287,7 +287,7 @@ impl From for InversionError { } } impl From<()> for InversionError { - fn from(_: ()) -> Self { + fn from((): ()) -> Self { InversionError::Generic } } diff --git a/src/compile/invert/un.rs b/src/compile/invert/un.rs index 70b8868ba..c0984c9ae 100644 --- a/src/compile/invert/un.rs +++ b/src/compile/invert/un.rs @@ -647,8 +647,7 @@ inverse!( inverse!(ScanPat, input, asm, { let un = matches!(input, [ImplMod(UnScan, ..), ..]); - let ([Mod(Scan, args, span), input @ ..] | [ImplMod(UnScan, args, span), input @ ..]) = input - else { + let [Mod(Scan, args, span) | ImplMod(UnScan, args, span), input @ ..] = input else { return generic(); }; let [f] = args.as_slice() else { @@ -1121,7 +1120,7 @@ inverse!(AntiContraFlip, input, asm, Prim(Flip, span), { if nodes_clean_sig(input).is_none_or(|sig| sig != (2, 1)) { return generic(); } - for pat in CONTRA_PATTERNS.iter() { + for pat in CONTRA_PATTERNS { if let Ok((inp, mut inv)) = pat.invert_extract(input, asm) { inv.prepend(Prim(Flip, span)); return Ok((inp, inv)); diff --git a/src/compile/mod.rs b/src/compile/mod.rs index 9ab971628..435f4da92 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -2072,8 +2072,7 @@ impl Compiler { (0..end).rev().any(|start| { let sub = node.slice(start..end); match sub.as_slice() { - [Node::Push(val), Node::Prim(Primitive::Dup, _)] - | [Node::Push(val), Node::Push(..)] + [Node::Push(val), Node::Prim(Primitive::Dup, _) | Node::Push(..)] if val != &Value::from(1) => { return true; @@ -2198,6 +2197,7 @@ impl Compiler { self.modified(*m, Some(scr.map(Into::into)))? } Modifier::Primitive(prim) => { + #[expect(clippy::unnested_or_patterns, reason = "intentionally grouped")] if !matches!( prim, (Both | Bracket) diff --git a/src/compile/modifier.rs b/src/compile/modifier.rs index c5203b2f3..79e2b6feb 100644 --- a/src/compile/modifier.rs +++ b/src/compile/modifier.rs @@ -169,87 +169,87 @@ impl Compiler { ..Default::default() }; match nodes.as_slice() { - [a, b] => { - cust.normal = Ok(a.clone()); - if a.sig == b.sig.inverse() { - cust.un = Some(b.clone()); - } else if a.sig.anti().is_some_and(|sig| sig == b.sig) { - cust.anti = Some(b.clone()); + [normal, other] => { + cust.normal = Ok(normal.clone()); + if normal.sig == other.sig.inverse() { + cust.un = Some(other.clone()); + } else if normal.sig.anti().is_some_and(|sig| sig == other.sig) { + cust.anti = Some(other.clone()); } else { - cust.under = Some((a.clone(), b.clone())); + cust.under = Some((normal.clone(), other.clone())); } } - [a, b, c] => { - cust.normal = Ok(a.clone()); - if !b.node.is_empty() && !c.node.is_empty() { - cust.under = Some((b.clone(), c.clone())); + [normal, under_do, under_undo] => { + cust.normal = Ok(normal.clone()); + if !under_do.node.is_empty() && !under_undo.node.is_empty() { + cust.under = Some((under_do.clone(), under_undo.clone())); } } - [a, b, c, d] => { - cust.normal = Ok(a.clone()); - if !b.node.is_empty() { - if !a.sig.is_compatible_with(b.sig.inverse()) { + [normal, un, under_do, under_undo] => { + cust.normal = Ok(normal.clone()); + if !un.node.is_empty() { + if !normal.sig.is_compatible_with(un.sig.inverse()) { self.emit_diagnostic( format!( "First and second functions must have \ opposite signatures, \ but their signatures are {} and {}", - a.sig, b.sig + normal.sig, un.sig ), DiagnosticKind::Warning, modifier.span.clone(), ); } - cust.un = Some(b.clone()); + cust.un = Some(un.clone()); } - if !d.node.is_empty() { - if !c.node.is_empty() { - cust.under = Some((c.clone(), d.clone())); + if !under_undo.node.is_empty() { + if !under_do.node.is_empty() { + cust.under = Some((under_do.clone(), under_undo.clone())); } - if a.sig.anti().is_some_and(|sig| sig == d.sig) { - cust.anti = Some(d.clone()); + if normal.sig.anti().is_some_and(|sig| sig == under_undo.sig) { + cust.anti = Some(under_undo.clone()); } } } - [a, b, c, d, e] => { - cust.normal = Ok(a.clone()); - if !b.node.is_empty() { - if !a.sig.is_compatible_with(b.sig.inverse()) { + [normal, un, under_do, under_undo, anti] => { + cust.normal = Ok(normal.clone()); + if !un.node.is_empty() { + if !normal.sig.is_compatible_with(un.sig.inverse()) { self.emit_diagnostic( format!( "First and second functions must have \ opposite signatures, \ but their signatures are {} and {}", - a.sig, b.sig + normal.sig, un.sig ), DiagnosticKind::Warning, modifier.span.clone(), ); } - cust.un = Some(b.clone()); + cust.un = Some(un.clone()); } - if !c.node.is_empty() && !d.node.is_empty() { - cust.under = Some((c.clone(), d.clone())); + if !under_do.node.is_empty() && !under_undo.node.is_empty() { + cust.under = Some((under_do.clone(), under_undo.clone())); } - if !e.node.is_empty() { - match a.sig.anti() { + if !anti.node.is_empty() { + match normal.sig.anti() { None => self.emit_diagnostic( format!( "An anti inverse is specified, but the first \ function's signature {} cannot have an \ anti inverse", - a.sig + normal.sig ), DiagnosticKind::Warning, modifier.span.clone(), ), - Some(sig) if sig != e.sig => { + Some(sig) if sig != anti.sig => { self.emit_diagnostic( format!( "The first function's signature implies an \ anti inverse with signature {sig}, but the \ fifth function's signature is {}", - e.sig + anti.sig ), DiagnosticKind::Warning, modifier.span.clone(), @@ -257,7 +257,7 @@ impl Compiler { } Some(_) => {} } - cust.anti = Some(e.clone()); + cust.anti = Some(anti.clone()); } } funcs => { @@ -2105,6 +2105,7 @@ impl Compiler { Prim(Identity | Dup | Flip | Pop | Stack | Sys(_), _) => {} ImplPrim(Over | StackN { .. }, _) => {} Push(_) | Array { .. } => {} + #[expect(clippy::unnested_or_patterns, reason = "intentionally grouped")] Mod( (Fork | Bracket | Both) | (Dip | Gap | Reach) diff --git a/src/format.rs b/src/format.rs index d10aef2fd..e92c4fa5c 100644 --- a/src/format.rs +++ b/src/format.rs @@ -613,7 +613,7 @@ impl Formatter<'_> { // Update subsequent mappings let byte_len_diff = line.len() - start_byte_len - 1; let char_len_diff = line.chars().count() - start_char_len - 1; - for (before, after) in self.glyph_map.iter_mut() { + for (before, after) in &mut self.glyph_map { if before.start.line as usize > line_number { after.0.byte_pos += byte_len_diff as u32; after.0.char_pos += char_len_diff as u32; diff --git a/src/grid_fmt.rs b/src/grid_fmt.rs index 4fbb28ad7..4871449c5 100644 --- a/src/grid_fmt.rs +++ b/src/grid_fmt.rs @@ -1038,7 +1038,7 @@ impl GridFmt for Array { // Handle really big grid if self.rank() > 1 { let max_width = terminal_size().map_or(1000, |(w, _)| w); - for row in grid.iter_mut() { + for row in &mut grid { if row.len() > max_width { let diff = row.len() - max_width; row.truncate(max_width); diff --git a/src/lib.rs b/src/lib.rs index c220e58fa..2bccccba0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -305,7 +305,7 @@ mod tests { .load_str_src(section, path) .and_then(|comp| env.run_asm(comp.finish())); match res { - Ok(_) => { + Ok(()) => { if (comp.take_diagnostics().into_iter()) .filter(|diag| diag.kind > DiagnosticKind::Advice) .count() diff --git a/src/lsp.rs b/src/lsp.rs index d1c751a69..5f6938bb9 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -2392,7 +2392,7 @@ mod server { path.canonicalize() .map_err(|e| Error::invalid_params(format!("Invalid file path: {e}")))?, ) - .map_err(|_| Error::invalid_params("Invalid file path")) + .map_err(|()| Error::invalid_params("Invalid file path")) } fn uri_path(uri: &Url) -> PathBuf { diff --git a/src/run.rs b/src/run.rs index 2343405e9..97cd81a23 100644 --- a/src/run.rs +++ b/src/run.rs @@ -538,7 +538,7 @@ impl Uiua { } } BindingKind::Func(f) => { - self.respect_recursion_limit().and_then(|_| self.call(&f)) + self.respect_recursion_limit().and_then(|()| self.call(&f)) } BindingKind::Import { .. } | BindingKind::Module(_) | BindingKind::Scope(_) => { Err(self.error( @@ -1568,11 +1568,11 @@ impl Uiua { std::thread::yield_now(); } let mut env = make_env(); - pool.execute(move || _ = send.send(env.exec(f).map(|_| env.take_stack()))); + pool.execute(move || _ = send.send(env.exec(f).map(|()| env.take_stack()))); } else { let mut env = make_env(); std::thread::Builder::new() - .spawn(move || _ = send.send(env.exec(f).map(|_| env.take_stack()))) + .spawn(move || _ = send.send(env.exec(f).map(|()| env.take_stack()))) .map_err(|e| self.error(format!("Error spawning thread: {e}")))?; } recv From 93c8a5cac9204c9f73f02bc981bf5a107f2ae183 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 19:40:14 +0300 Subject: [PATCH 12/21] lint: fix clippy::pedantic (11-12 entries) --- Cargo.toml | 3 - pad/editor/src/backend.rs | 103 +++++++++++++++--------------- pad/editor/src/lib.rs | 4 +- pad/editor/src/utils.rs | 10 +-- parser/src/parse.rs | 102 +++++++++++++---------------- site/src/main.rs | 2 +- site/src/markdown.rs | 2 +- site/src/other_tutorial.rs | 8 +-- site/src/tutorial.rs | 4 +- src/algorithm/dyadic/search.rs | 23 +++---- src/algorithm/dyadic/structure.rs | 40 ++++++------ src/algorithm/ga.rs | 2 +- src/compile/algebra.rs | 12 ++-- src/compile/pre_eval.rs | 4 +- src/ffi.rs | 21 +++--- src/grid_fmt.rs | 6 +- src/lsp.rs | 2 +- src/run_prim.rs | 6 +- src/sys/mod.rs | 12 ++-- src/sys/native.rs | 4 +- 20 files changed, 170 insertions(+), 200 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 20181c1ca..6f0ec0737 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,6 @@ dbg_macro = "warn" print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} -single_match_else = "allow" # 11 -manual_string_new = "allow" # 12 -trivially_copy_pass_by_ref = "allow" # 12 ptr_cast_constness = "allow" # 15 redundant_else = "allow" # 15 unnecessary_semicolon = "allow" # 15 diff --git a/pad/editor/src/backend.rs b/pad/editor/src/backend.rs index 01f2eda07..5ab03f3eb 100644 --- a/pad/editor/src/backend.rs +++ b/pad/editor/src/backend.rs @@ -189,7 +189,7 @@ impl SysBackend for WebBackend { stdout.push(OutputItem::String(line.into())); } if s.ends_with('\n') { - stdout.push(OutputItem::String("".into())); + stdout.push(OutputItem::String(String::new())); } Ok(()) } @@ -510,64 +510,61 @@ impl SysBackend for WebBackend { )) .await; - match tree_res { - Err(_) => { - cache_url(&url, tree_res); + if tree_res.is_err() { + cache_url(&url, tree_res); + unmark_working(&original_url); + return; + } else { + let tree = tree_res.unwrap(); + let tree: serde_json::Value = serde_json::from_str(&tree).unwrap(); + let tree = tree.get("tree").unwrap().as_array().unwrap(); + let paths = tree + .iter() + .filter_map(|entry| { + let path = entry.get("path")?.as_str()?; + if Path::new(path) + .extension() + .is_some_and(|ext| ext.eq_ignore_ascii_case("ua")) + { + Some(path.to_string()) + } else { + None + } + }) + .collect::>(); + + if !paths.contains("lib.ua") { + cache_url(&url, Err("lib.ua not found".into())); unmark_working(&original_url); return; } - Ok(_) => { - let tree = tree_res.unwrap(); - let tree: serde_json::Value = serde_json::from_str(&tree).unwrap(); - let tree = tree.get("tree").unwrap().as_array().unwrap(); - let paths = tree - .iter() - .filter_map(|entry| { - let path = entry.get("path")?.as_str()?; - if Path::new(path) - .extension() - .is_some_and(|ext| ext.eq_ignore_ascii_case("ua")) - { - Some(path.to_string()) - } else { - None - } - }) - .collect::>(); - - if !paths.contains("lib.ua") { - cache_url(&url, Err("lib.ua not found".into())); - unmark_working(&original_url); - return; - } - let results = join_all(paths.iter().map(|path| { - let repo_owner = repo_owner.clone(); - let repo_name = repo_name.clone(); - async move { - let fetch_url = format!( - "https://raw.githubusercontent.com\ - /{repo_owner}/{repo_name}/main/{path}", - ); - let internal_path = Path::new("uiua-modules") - .join(repo_owner) - .join(repo_name) - .join(path.clone()); - - (path, internal_path, fetch(fetch_url.as_str()).await) - } - })) - .await; + let results = join_all(paths.iter().map(|path| { + let repo_owner = repo_owner.clone(); + let repo_name = repo_name.clone(); + async move { + let fetch_url = format!( + "https://raw.githubusercontent.com\ + /{repo_owner}/{repo_name}/main/{path}", + ); + let internal_path = Path::new("uiua-modules") + .join(repo_owner) + .join(repo_name) + .join(path.clone()); + + (path, internal_path, fetch(fetch_url.as_str()).await) + } + })) + .await; - for (original_path, internal_path, res) in results { - if original_path.eq("lib.ua") { - cache_url(&url, res.clone()); - } + for (original_path, internal_path, res) in results { + if original_path.eq("lib.ua") { + cache_url(&url, res.clone()); + } - if let Ok(text) = res { - let contents = text.as_bytes().to_vec(); - drop_file(internal_path.clone(), contents); - } + if let Ok(text) = res { + let contents = text.as_bytes().to_vec(); + drop_file(internal_path.clone(), contents); } } } diff --git a/pad/editor/src/lib.rs b/pad/editor/src/lib.rs index aac41d4af..bfdd94f8a 100644 --- a/pad/editor/src/lib.rs +++ b/pad/editor/src/lib.rs @@ -1868,7 +1868,7 @@ pub fn Editor<'a>( let editor_style = move || { if !fullscreen_enabled.get() { - return "".to_string(); + return String::new(); } let ratio = splitter_ratio.get(); @@ -2270,7 +2270,7 @@ pub fn Prim( let name = if !glyph_only && symbol != prim.name() { format!(" {}", prim.name()) } else { - "".to_string() + String::new() }; let href = format!("/docs/{}", prim.name()); let mut title = String::new(); diff --git a/pad/editor/src/utils.rs b/pad/editor/src/utils.rs index 1e1c7ebeb..ea613815f 100644 --- a/pad/editor/src/utils.rs +++ b/pad/editor/src/utils.rs @@ -1257,7 +1257,7 @@ fn run_code_single(id: &str, code: &str) -> (Vec, Option) } if !stdout.is_empty() { if !output.is_empty() { - output.push(OutputItem::String("".into())); + output.push(OutputItem::String(String::new())); } if label { output.push(OutputItem::String("stdout:".to_string())); @@ -1266,7 +1266,7 @@ fn run_code_single(id: &str, code: &str) -> (Vec, Option) } if !stderr.is_empty() { if !output.is_empty() { - output.push(OutputItem::String("".into())); + output.push(OutputItem::String(String::new())); } if label { output.push(OutputItem::String("stderr:".to_string())); @@ -1281,7 +1281,7 @@ fn run_code_single(id: &str, code: &str) -> (Vec, Option) } if let Some(error) = &error { if !output.is_empty() { - output.push(OutputItem::String("".into())); + output.push(OutputItem::String(String::new())); } const MAX_OUTPUT_BEFORE_ERROR: usize = 60; if output.len() >= MAX_OUTPUT_BEFORE_ERROR { @@ -1299,7 +1299,7 @@ fn run_code_single(id: &str, code: &str) -> (Vec, Option) } if !diagnostics.is_empty() { if !output.is_empty() { - output.push(OutputItem::String("".into())); + output.push(OutputItem::String(String::new())); } for diag in diagnostics { output.push(OutputItem::Report(diag.report())); @@ -1424,7 +1424,7 @@ pub fn progressive_strings(input: &str) -> Vec { curr_total.push('\n'); } if strings.is_empty() { - strings.push("".into()); + strings.push(String::new()); } strings.rotate_right(1); strings[0] = input.into(); diff --git a/parser/src/parse.rs b/parser/src/parse.rs index 62fe7bb8e..cdfed83c6 100644 --- a/parser/src/parse.rs +++ b/parser/src/parse.rs @@ -306,25 +306,22 @@ impl Parser<'_> { } let mut trailing_newline = false; loop { - match self.item(kind) { - Some(item) => { - trailing_newline = false; - items.push(item) + if let Some(item) = self.item(kind) { + trailing_newline = false; + items.push(item) + } else { + if self.exact(Newline).is_none() { + break; } - None => { - if self.exact(Newline).is_none() { - break; - } - trailing_newline = true; + trailing_newline = true; + self.spaces(); + let mut extra_newlines = false; + while self.exact(Newline).is_some() { + extra_newlines = true; self.spaces(); - let mut extra_newlines = false; - while self.exact(Newline).is_some() { - extra_newlines = true; - self.spaces(); - } - if extra_newlines { - items.push(Item::Words(Vec::new())); - } + } + if extra_newlines { + items.push(Item::Words(Vec::new())); } } } @@ -940,31 +937,28 @@ impl Parser<'_> { let range = self.real()?.span.byte_range(); let s = &self.input[range]; Some(if let Some((a, o)) = s.split_once('.') { - let a = match a.parse() { - Ok(a) => a, - Err(_) => { - self.errors - .push(self.prev_span().sp(ParseError::InvalidArgCount(a.into()))); - 1 - } + let a = if let Ok(a) = a.parse() { + a + } else { + self.errors + .push(self.prev_span().sp(ParseError::InvalidArgCount(a.into()))); + 1 }; - let o = match o.parse() { - Ok(o) => o, - Err(_) => { - self.errors - .push(self.prev_span().sp(ParseError::InvalidOutCount(o.into()))); - 1 - } + let o = if let Ok(o) = o.parse() { + o + } else { + self.errors + .push(self.prev_span().sp(ParseError::InvalidOutCount(o.into()))); + 1 }; (a, o) } else { - let a = match s.parse() { - Ok(a) => a, - Err(_) => { - self.errors - .push(self.prev_span().sp(ParseError::InvalidArgCount(s.into()))); - 1 - } + let a = if let Ok(a) = s.parse() { + a + } else { + self.errors + .push(self.prev_span().sp(ParseError::InvalidArgCount(s.into()))); + 1 }; (a, 1) }) @@ -1029,27 +1023,23 @@ impl Parser<'_> { // Collect items let mut items = Vec::new(); while self.exact(Underscore.into()).is_some() { - let item = match self.modified() { - Some(mut item) => { - if let Word::Spaces = item.value { - if items.is_empty() { - break; - } - self.errors.push(self.expected([Expectation::Term])); - item = match self.modified() { - Some(item) => item, - None => { - self.errors.push(self.expected([Expectation::Term])); - break; - } - }; + let item = if let Some(mut item) = self.modified() { + if let Word::Spaces = item.value { + if items.is_empty() { + break; } - item - } - None => { self.errors.push(self.expected([Expectation::Term])); - break; + item = if let Some(item) = self.modified() { + item + } else { + self.errors.push(self.expected([Expectation::Term])); + break; + }; } + item + } else { + self.errors.push(self.expected([Expectation::Term])); + break; }; items.push(item); } diff --git a/site/src/main.rs b/site/src/main.rs index 3f9de5b59..d8f958022 100644 --- a/site/src/main.rs +++ b/site/src/main.rs @@ -410,7 +410,7 @@ fn prim_html(prim: Primitive, glyph_only: bool, hide_docs: bool) -> String { let name = if !glyph_only && symbol != prim.name() { format!(" {}", prim.name()) } else { - "".to_string() + String::new() }; let href = format!("/docs/{}", prim.name()); let mut title = String::new(); diff --git a/site/src/markdown.rs b/site/src/markdown.rs index 1b0803926..3bb83f601 100644 --- a/site/src/markdown.rs +++ b/site/src/markdown.rs @@ -292,7 +292,7 @@ fn node_html<'a>(node: &'a AstNode<'a>) -> String { let symbol_class = format!("prim-glyph {}", prim_class(prim)); let symbol = prim.to_string(); let name = if symbol == prim.name() { - "".to_string() + String::new() } else { format!(" {}", prim.name()) }; diff --git a/site/src/other_tutorial.rs b/site/src/other_tutorial.rs index e4d0fa468..a20a904eb 100644 --- a/site/src/other_tutorial.rs +++ b/site/src/other_tutorial.rs @@ -22,10 +22,10 @@ pub enum OtherTutorialPage { } impl OtherTutorialPage { - pub fn path(&self) -> String { + pub fn path(self) -> String { format!("{self:?}").to_lowercase() } - pub fn view(&self) -> View { + pub fn view(self) -> View { match self { Self::Strings => title_markdown( "Strings", @@ -52,7 +52,7 @@ impl OtherTutorialPage { Self::EvenMoreStack => EvenMoreStack().into_view(), } } - pub fn title(&self) -> &'static str { + pub fn title(self) -> &'static str { match self { OtherTutorialPage::Strings => "Strings", OtherTutorialPage::FilesAndStreams => "Files and Streams", @@ -64,7 +64,7 @@ impl OtherTutorialPage { OtherTutorialPage::Ranges => "Ranges", } } - pub fn description(&self) -> Cow<'static, str> { + pub fn description(self) -> Cow<'static, str> { Cow::Borrowed(match self { OtherTutorialPage::Strings => "how to manipulate strings", OtherTutorialPage::FilesAndStreams => "how to read and write files and streams", diff --git a/site/src/tutorial.rs b/site/src/tutorial.rs index 7d44e5e5c..62f2f68e0 100644 --- a/site/src/tutorial.rs +++ b/site/src/tutorial.rs @@ -35,10 +35,10 @@ pub enum TutorialPage { } impl TutorialPage { - pub fn path(&self) -> String { + pub fn path(self) -> String { format!("{self:?}").to_lowercase() } - pub fn title(&self) -> &'static str { + pub fn title(self) -> &'static str { match self { Self::Introduction => "Introduction", Self::Basic => "Basic Stack Operations and Formatting", diff --git a/src/algorithm/dyadic/search.rs b/src/algorithm/dyadic/search.rs index 9033dd58f..2ac93383b 100644 --- a/src/algorithm/dyadic/search.rs +++ b/src/algorithm/dyadic/search.rs @@ -432,19 +432,16 @@ impl Array { .any(|(a, b)| a > b); if needle.rank() > haystack.rank() || any_dim_greater { // Fill - match env.scalar_fill() { - Ok(fill) => { - let target_shape = max_shape(&haystack.shape, &needle.shape); - local_searched = haystack.clone(); - local_searched.fill_to_shape(&target_shape, fill); - haystack = &local_searched; - } - Err(_) => { - let data = cowslice![0; haystack.element_count()]; - let mut arr = Array::new(haystack.shape.clone(), data); - arr.meta.flags.insert(ArrayFlags::BOOLEAN); - return Ok(arr); - } + if let Ok(fill) = env.scalar_fill() { + let target_shape = max_shape(&haystack.shape, &needle.shape); + local_searched = haystack.clone(); + local_searched.fill_to_shape(&target_shape, fill); + haystack = &local_searched; + } else { + let data = cowslice![0; haystack.element_count()]; + let mut arr = Array::new(haystack.shape.clone(), data); + arr.meta.flags.insert(ArrayFlags::BOOLEAN); + return Ok(arr); } } diff --git a/src/algorithm/dyadic/structure.rs b/src/algorithm/dyadic/structure.rs index ab8ecc690..53586dfa5 100644 --- a/src/algorithm/dyadic/structure.rs +++ b/src/algorithm/dyadic/structure.rs @@ -396,17 +396,16 @@ impl Value { val_as_arr!(from, |a| a.drop(&index, env).map(Into::into)) } pub(crate) fn undo_take(self, index: Self, into: Self, env: &Uiua) -> UiuaResult { - let index = match index.as_ints(env, None) { - Ok(indices) => indices, - Err(_) => { - let with_infs = index - .as_ints_or_infs(env, "Taken amount must be a list of integers or infinity")?; - let mut indices = Vec::with_capacity(with_infs.len()); - for (i, d) in with_infs.into_iter().zip(&into.shape) { - indices.push(i.unwrap_or(*d as isize)); - } - indices + let index = if let Ok(indices) = index.as_ints(env, None) { + indices + } else { + let with_infs = index + .as_ints_or_infs(env, "Taken amount must be a list of integers or infinity")?; + let mut indices = Vec::with_capacity(with_infs.len()); + for (i, d) in with_infs.into_iter().zip(&into.shape) { + indices.push(i.unwrap_or(*d as isize)); } + indices }; self.generic_bin_into( into, @@ -425,19 +424,16 @@ impl Value { ) } pub(crate) fn undo_drop(self, index: Self, into: Self, env: &Uiua) -> UiuaResult { - let index = match index.as_ints(env, None) { - Ok(indices) => indices, - Err(_) => { - let with_infs = index.as_ints_or_infs( - env, - "Dropped amount must be a list of integers or infinity", - )?; - let mut indices = Vec::with_capacity(with_infs.len()); - for (i, d) in with_infs.into_iter().zip(&into.shape) { - indices.push(i.unwrap_or(*d as isize)); - } - indices + let index = if let Ok(indices) = index.as_ints(env, None) { + indices + } else { + let with_infs = index + .as_ints_or_infs(env, "Dropped amount must be a list of integers or infinity")?; + let mut indices = Vec::with_capacity(with_infs.len()); + for (i, d) in with_infs.into_iter().zip(&into.shape) { + indices.push(i.unwrap_or(*d as isize)); } + indices }; self.generic_bin_into( into, diff --git a/src/algorithm/ga.rs b/src/algorithm/ga.rs index 7b32d5c20..ce792d076 100644 --- a/src/algorithm/ga.rs +++ b/src/algorithm/ga.rs @@ -898,7 +898,7 @@ impl Metrics { } metrics } - pub const fn get(&self, index: usize) -> i8 { + pub const fn get(self, index: usize) -> i8 { let bits = (self.0 >> (2 * index)) & 0b11; match bits { 0b00 => 1, diff --git a/src/compile/algebra.rs b/src/compile/algebra.rs index c4470c045..229016fce 100644 --- a/src/compile/algebra.rs +++ b/src/compile/algebra.rs @@ -472,13 +472,11 @@ impl<'a> AlgebraEnv<'a> { Complex => { let a = self.pop()?; let b = self.pop()?; - match (a.as_constant(), b.as_constant()) { - (Some(a), Some(b)) => self.stack.push((a * Complex::I + b).into()), - _ => { - let im = - (a * Expr::from(Complex::I)).ok_or(AlgebraError::TooComplex)?; - self.stack.push(b + im); - } + if let (Some(a), Some(b)) = (a.as_constant(), b.as_constant()) { + self.stack.push((a * Complex::I + b).into()) + } else { + let im = (a * Expr::from(Complex::I)).ok_or(AlgebraError::TooComplex)?; + self.stack.push(b + im); } self.any_complex = true; } diff --git a/src/compile/pre_eval.rs b/src/compile/pre_eval.rs index 51519940c..da0b0e7d6 100644 --- a/src/compile/pre_eval.rs +++ b/src/compile/pre_eval.rs @@ -29,7 +29,7 @@ const MAX_PRE_EVAL_RANK: usize = 4; impl PreEvalMode { #[allow(unused)] - fn matches_nodes(&self, nodes: &[Node], asm: &Assembly) -> bool { + fn matches_nodes(self, nodes: &[Node], asm: &Assembly) -> bool { if nodes.iter().all(|node| matches!(node, Node::Push(_))) { return false; } @@ -78,7 +78,7 @@ impl PreEvalMode { visited.truncate(len); matches } - recurse(*self, nodes, asm, &mut IndexSet::new()) + recurse(self, nodes, asm, &mut IndexSet::new()) } } diff --git a/src/ffi.rs b/src/ffi.rs index f231672db..cbd2987a0 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -72,17 +72,14 @@ impl Display for FfiType { impl Display for FfiArg { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "{out}{ty}{index}", - out = if self.out { "out " } else { "" }, - ty = self.ty, - index = if let Some(len_index) = self.len_index { - format!(":{len_index}") - } else { - "".to_string() - } - ) + if self.out { + write!(f, "out ")?; + } + write!(f, "{}", self.ty)?; + if let Some(len_index) = self.len_index { + write!(f, ":{len_index}")?; + } + Ok(()) } } @@ -137,7 +134,7 @@ impl FromStr for FfiType { // Struct if let Some(body) = input - .strip_prefix('{' ) + .strip_prefix('{') .and_then(|s| s.strip_suffix('}')) .map(|s| s.trim_end_matches(';')) { diff --git a/src/grid_fmt.rs b/src/grid_fmt.rs index 4871449c5..537961e30 100644 --- a/src/grid_fmt.rs +++ b/src/grid_fmt.rs @@ -1331,13 +1331,13 @@ impl Line { _ => &[Line::OpenDouble, Line::CloseDouble], } } - fn vert(&self) -> char { + fn vert(self) -> char { match self { Line::Single | Line::OpenSingle | Line::CloseSingle | Line::ForceSingle => '│', Line::Double | Line::OpenDouble | Line::CloseDouble | Line::ForceDouble => '║', } } - fn horiz(&self) -> char { + fn horiz(self) -> char { match self { Line::Single | Line::OpenSingle | Line::CloseSingle | Line::ForceSingle => '─', Line::Double | Line::OpenDouble | Line::CloseDouble | Line::ForceDouble => '═', @@ -1352,7 +1352,7 @@ impl Line { line => line, } } - fn intersect(&self, column: Self) -> char { + fn intersect(self, column: Self) -> char { use Line::*; match (self, column) { (Single, Single) | (ForceSingle, ForceSingle) => '┼', diff --git a/src/lsp.rs b/src/lsp.rs index 5f6938bb9..c96ffccee 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -1786,7 +1786,7 @@ mod server { params.text_document.uri.clone(), vec![TextEdit { range: uiua_span_to_lsp(&span.span, &doc.asm.inputs), - new_text: "".into(), + new_text: String::new(), }], )] .into(), diff --git a/src/run_prim.rs b/src/run_prim.rs index 71d81fd84..6547a93e8 100644 --- a/src/run_prim.rs +++ b/src/run_prim.rs @@ -337,7 +337,7 @@ pub fn run_prim_func(prim: &Primitive, env: &mut Uiua) -> UiuaResult { Primitive::ExeExt => env.push(std::env::consts::EXE_EXTENSION), Primitive::PathSep => env.push(std::path::MAIN_SEPARATOR), Primitive::NumProcs => env.push(num_cpus::get()), - Primitive::Sys(op) => run_sys_op(op, env)?, + Primitive::Sys(op) => run_sys_op(*op, env)?, prim => { return Err(env.error(if prim.modifier_args().is_some() { format!( @@ -515,7 +515,7 @@ pub fn run_prim_mod(prim: &Primitive, mut ops: Ops, env: &mut Uiua) -> UiuaResul let [f] = get_ops(ops, env)?; env.spawn(true, f)?; } - Primitive::Sys(op) => run_sys_op_mod(op, ops, env)?, + &Primitive::Sys(op) => run_sys_op_mod(op, ops, env)?, prim => { return Err(env.error(if prim.modifier_args().is_some() { format!( @@ -911,7 +911,7 @@ impl ImplPrimitive { env.push(right); env.push(left); } - ImplPrimitive::TryClose => _ = run_sys_op(&SysOp::Close, env), + ImplPrimitive::TryClose => _ = run_sys_op(SysOp::Close, env), ImplPrimitive::UndoInsert => { let key = env.pop(1)?; let _value = env.pop(2)?; diff --git a/src/sys/mod.rs b/src/sys/mod.rs index 1a97f329f..f61ceb7b4 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -629,7 +629,7 @@ impl IntoSysBackend for Arc { } } -pub(crate) fn run_sys_op(op: &SysOp, env: &mut Uiua) -> UiuaResult { +pub(crate) fn run_sys_op(op: SysOp, env: &mut Uiua) -> UiuaResult { match op { SysOp::Show => { let val = env.pop(1)?; @@ -1334,20 +1334,20 @@ pub(crate) fn run_sys_op(op: &SysOp, env: &mut Uiua) -> UiuaResult { format!( "{} was not handled as a modifier. \ This is a bug in the interpreter", - Primitive::Sys(*prim) + Primitive::Sys(prim) ) } else { format!( "{} was not handled as a function. \ This is a bug in the interpreter", - Primitive::Sys(*prim) + Primitive::Sys(prim) ) })) } } Ok(()) } -pub(crate) fn run_sys_op_mod(op: &SysOp, ops: Ops, env: &mut Uiua) -> UiuaResult { +pub(crate) fn run_sys_op_mod(op: SysOp, ops: Ops, env: &mut Uiua) -> UiuaResult { match op { SysOp::ReadLines => { let [f] = get_ops(ops, env)?; @@ -1438,13 +1438,13 @@ pub(crate) fn run_sys_op_mod(op: &SysOp, ops: Ops, env: &mut Uiua) -> UiuaResult format!( "{} was not handled as a modifier. \ This is a bug in the interpreter", - Primitive::Sys(*prim) + Primitive::Sys(prim) ) } else { format!( "{} was handled as a modifier. \ This is a bug in the interpreter", - Primitive::Sys(*prim) + Primitive::Sys(prim) ) })) } diff --git a/src/sys/native.rs b/src/sys/native.rs index d8fcbb523..0346ae5cd 100644 --- a/src/sys/native.rs +++ b/src/sys/native.rs @@ -679,9 +679,7 @@ impl SysBackend for NativeSys { } else { (None, None) }; - if std::env::var("TERM") - .unwrap_or("".to_owned()) - .contains("sixel") + if std::env::var("TERM").is_ok_and(|s| s.contains("sixel")) || std::env::var("UIUA_ENABLE_SIXEL").is_ok_and(|s| s == "1") { let img_rgba8 = image.to_rgba8(); From 8c62d8337a0423414fdef4e1e1e820c39be4d41b Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 19:59:54 +0300 Subject: [PATCH 13/21] lint: fix clippy::pedantic (15 entries) --- Cargo.toml | 3 - pad/editor/src/backend.rs | 97 +++++++++++++++---------------- parser/src/lex.rs | 2 +- parser/src/parse.rs | 10 ++-- parser/src/subscript.rs | 2 +- site/src/docs.rs | 29 +++++---- src/algorithm/dyadic/mod.rs | 5 +- src/algorithm/dyadic/search.rs | 15 +++-- src/algorithm/dyadic/structure.rs | 2 +- src/algorithm/loops.rs | 5 +- src/algorithm/map.rs | 2 +- src/algorithm/stencil.rs | 71 +++++++++++----------- src/algorithm/tuples.rs | 15 +++-- src/algorithm/zip.rs | 13 ++--- src/compile/binding.rs | 5 +- src/compile/mod.rs | 2 +- src/compile/modifier.rs | 2 +- src/ffi.rs | 5 +- src/lsp.rs | 4 +- src/main.rs | 21 ++++--- src/sys/native.rs | 5 +- src/window.rs | 2 +- 22 files changed, 148 insertions(+), 169 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6f0ec0737..b43049222 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,6 @@ dbg_macro = "warn" print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} -ptr_cast_constness = "allow" # 15 -redundant_else = "allow" # 15 -unnecessary_semicolon = "allow" # 15 manual_assert = "allow" # 16 inline_always = "allow" # 18 from_iter_instead_of_collect = "allow" # 20 diff --git a/pad/editor/src/backend.rs b/pad/editor/src/backend.rs index 5ab03f3eb..ec0e32b7a 100644 --- a/pad/editor/src/backend.rs +++ b/pad/editor/src/backend.rs @@ -514,58 +514,57 @@ impl SysBackend for WebBackend { cache_url(&url, tree_res); unmark_working(&original_url); return; - } else { - let tree = tree_res.unwrap(); - let tree: serde_json::Value = serde_json::from_str(&tree).unwrap(); - let tree = tree.get("tree").unwrap().as_array().unwrap(); - let paths = tree - .iter() - .filter_map(|entry| { - let path = entry.get("path")?.as_str()?; - if Path::new(path) - .extension() - .is_some_and(|ext| ext.eq_ignore_ascii_case("ua")) - { - Some(path.to_string()) - } else { - None - } - }) - .collect::>(); - - if !paths.contains("lib.ua") { - cache_url(&url, Err("lib.ua not found".into())); - unmark_working(&original_url); - return; - } - - let results = join_all(paths.iter().map(|path| { - let repo_owner = repo_owner.clone(); - let repo_name = repo_name.clone(); - async move { - let fetch_url = format!( - "https://raw.githubusercontent.com\ - /{repo_owner}/{repo_name}/main/{path}", - ); - let internal_path = Path::new("uiua-modules") - .join(repo_owner) - .join(repo_name) - .join(path.clone()); - - (path, internal_path, fetch(fetch_url.as_str()).await) + } + let tree = tree_res.unwrap(); + let tree: serde_json::Value = serde_json::from_str(&tree).unwrap(); + let tree = tree.get("tree").unwrap().as_array().unwrap(); + let paths = tree + .iter() + .filter_map(|entry| { + let path = entry.get("path")?.as_str()?; + if Path::new(path) + .extension() + .is_some_and(|ext| ext.eq_ignore_ascii_case("ua")) + { + Some(path.to_string()) + } else { + None } - })) - .await; + }) + .collect::>(); - for (original_path, internal_path, res) in results { - if original_path.eq("lib.ua") { - cache_url(&url, res.clone()); - } + if !paths.contains("lib.ua") { + cache_url(&url, Err("lib.ua not found".into())); + unmark_working(&original_url); + return; + } - if let Ok(text) = res { - let contents = text.as_bytes().to_vec(); - drop_file(internal_path.clone(), contents); - } + let results = join_all(paths.iter().map(|path| { + let repo_owner = repo_owner.clone(); + let repo_name = repo_name.clone(); + async move { + let fetch_url = format!( + "https://raw.githubusercontent.com\ + /{repo_owner}/{repo_name}/main/{path}", + ); + let internal_path = Path::new("uiua-modules") + .join(repo_owner) + .join(repo_name) + .join(path.clone()); + + (path, internal_path, fetch(fetch_url.as_str()).await) + } + })) + .await; + + for (original_path, internal_path, res) in results { + if original_path.eq("lib.ua") { + cache_url(&url, res.clone()); + } + + if let Ok(text) = res { + let contents = text.as_bytes().to_vec(); + drop_file(internal_path.clone(), contents); } } diff --git a/parser/src/lex.rs b/parser/src/lex.rs index d440c5536..5c556bb5a 100644 --- a/parser/src/lex.rs +++ b/parser/src/lex.rs @@ -1420,7 +1420,7 @@ impl<'a> Lexer<'a> { self.errors .push(self.end_span(start).sp(LexError::UnexpectedChar(c.into()))); } - }; + } } (self.tokens, self.errors) diff --git a/parser/src/parse.rs b/parser/src/parse.rs index cdfed83c6..b1c8700b8 100644 --- a/parser/src/parse.rs +++ b/parser/src/parse.rs @@ -685,7 +685,7 @@ impl Parser<'_> { Vec::new() }); init = Some(FieldInit { arrow_span, words }) - }; + } trailing_newline |= self.ignore_whitespace(); let mut bar_span = self.exact(Bar.into()); @@ -1309,9 +1309,8 @@ impl Parser<'_> { } span.merge_with(dspan); return Some(span.sp((n, s))); - } else { - self.index = reset; } + self.index = reset; } } // Let 1-letter string be identifiers @@ -1446,10 +1445,9 @@ impl Parser<'_> { if s == "¯" { self.index = reset; return None; - } else { - // Just the number - (coef.into(), s, span) } + // Just the number + (coef.into(), s, span) } else { self.index = reset; return None; diff --git a/parser/src/subscript.rs b/parser/src/subscript.rs index 39f81630b..301af6a9e 100644 --- a/parser/src/subscript.rs +++ b/parser/src/subscript.rs @@ -146,7 +146,7 @@ impl fmt::Display for Subscript { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.num.is_none() && self.side.is_none() { return write!(f, ","); - }; + } if let Some(num) = &self.num { num.fmt(f)?; } diff --git a/site/src/docs.rs b/site/src/docs.rs index b4545b047..e873f3278 100644 --- a/site/src/docs.rs +++ b/site/src/docs.rs @@ -363,23 +363,20 @@ impl Allowed { classes: [prim.class()].into(), prims, }; - } else { - for &part in &parts { - if let Some(prim) = prim_matching_part_exactly(part) { - prims.insert(prim); - continue; - } - let matches = all() - .filter(|p| p.name().to_lowercase().starts_with(part)) - .chain(all().filter(|p| { - p.ascii() - .is_some_and(|simple| part.contains(&simple.to_string())) - })) - .chain( - all().filter(|p| p.glyph().is_some_and(|unicode| part.contains(unicode))), - ); - prims.extend(matches); + } + for &part in &parts { + if let Some(prim) = prim_matching_part_exactly(part) { + prims.insert(prim); + continue; } + let matches = all() + .filter(|p| p.name().to_lowercase().starts_with(part)) + .chain(all().filter(|p| { + p.ascii() + .is_some_and(|simple| part.contains(&simple.to_string())) + })) + .chain(all().filter(|p| p.glyph().is_some_and(|unicode| part.contains(unicode)))); + prims.extend(matches); } let mut classes: HashSet = PrimClass::all().collect(); let system_classes: Vec = SysOpClass::all().map(PrimClass::Sys).collect(); diff --git a/src/algorithm/dyadic/mod.rs b/src/algorithm/dyadic/mod.rs index c34a1b151..570052fc1 100644 --- a/src/algorithm/dyadic/mod.rs +++ b/src/algorithm/dyadic/mod.rs @@ -1894,10 +1894,9 @@ impl Array { if n == f64::INFINITY { slice[i * num_digits + j] = n; break; - } else { - slice[i * num_digits + j] = n.rem_euclid(base); - n = n.div_euclid(base); } + slice[i * num_digits + j] = n.rem_euclid(base); + n = n.div_euclid(base); } } Ok(Array::new(new_shape, new_data)) diff --git a/src/algorithm/dyadic/search.rs b/src/algorithm/dyadic/search.rs index 2ac93383b..28ea5019f 100644 --- a/src/algorithm/dyadic/search.rs +++ b/src/algorithm/dyadic/search.rs @@ -311,14 +311,13 @@ impl Array { result_data.push(i as f64); cache.insert(elem_key, (i, false)); continue 'needle; - } else { - for j in i + 1..haystack.row_count() { - let of_key = ArrayCmpSlice(haystack.row_slice(j)); - if of_key == elem_key { - result_data.push(j as f64); - cache.insert(elem_key, (j, false)); - continue 'needle; - } + } + for j in i + 1..haystack.row_count() { + let of_key = ArrayCmpSlice(haystack.row_slice(j)); + if of_key == elem_key { + result_data.push(j as f64); + cache.insert(elem_key, (j, false)); + continue 'needle; } } } else { diff --git a/src/algorithm/dyadic/structure.rs b/src/algorithm/dyadic/structure.rs index 53586dfa5..86491298c 100644 --- a/src/algorithm/dyadic/structure.rs +++ b/src/algorithm/dyadic/structure.rs @@ -753,7 +753,7 @@ impl Array { for row in self.rows().take(end) { new_rows.push(row.drop(sub_index, env)?); } - }; + } if row_count == abs_dropping { let mut shape = self.shape; for (s, n) in shape.iter_mut().zip(once(&Err(true)).chain(sub_index)) { diff --git a/src/algorithm/loops.rs b/src/algorithm/loops.rs index 2d24d2004..9507f6302 100644 --- a/src/algorithm/loops.rs +++ b/src/algorithm/loops.rs @@ -205,10 +205,9 @@ fn repeat_impl(f: SigNode, inv: Option, n: f64, env: &mut Uiua) -> Uiua if converged { env.push(next); break; - } else { - env.push(next.clone()); - prev = next; } + env.push(next.clone()); + prev = next; convergence_count += 1; } } else { diff --git a/src/algorithm/map.rs b/src/algorithm/map.rs index 4ad3be298..b1e4d7428 100644 --- a/src/algorithm/map.rs +++ b/src/algorithm/map.rs @@ -277,7 +277,7 @@ impl Value { )) }, )?; - }; + } self.meta.map_keys = Some(keys); Ok(()) } diff --git a/src/algorithm/stencil.rs b/src/algorithm/stencil.rs index 677eafb50..24ac630bb 100644 --- a/src/algorithm/stencil.rs +++ b/src/algorithm/stencil.rs @@ -140,42 +140,41 @@ where } env.push(val); return Ok(()); - } else { - // General case - let row_len = arr.row_len(); - let win_count = arr - .row_count() - .saturating_sub(dim.size.saturating_sub(dim.stride)) - / dim.stride; - match action { - WindowAction::Id(mut data, f) => { - for i in 0..win_count { - data.extend_from_slice( - &arr.data[i * dim.stride * row_len..][..dim.size * row_len], - ); - } - let mut new_shape = arr.shape; - new_shape[0] = dim.size; - new_shape.prepend(win_count); - let mut val: Value = Array::new(new_shape, data).into(); - if let Some((f, d)) = f { - val = f(val, dims.len() + d, env)?; - } - env.push(val); - return Ok(()); + } + // General case + let row_len = arr.row_len(); + let win_count = arr + .row_count() + .saturating_sub(dim.size.saturating_sub(dim.stride)) + / dim.stride; + match action { + WindowAction::Id(mut data, f) => { + for i in 0..win_count { + data.extend_from_slice( + &arr.data[i * dim.stride * row_len..][..dim.size * row_len], + ); } - WindowAction::Box(mut boxes, _) => { - for i in 0..win_count { - boxes.push(Boxed( - arr.slice_rows(i * dim.stride, i * dim.stride + dim.size) - .into(), - )); - } - env.push(Array::from(boxes)); - return Ok(()); + let mut new_shape = arr.shape; + new_shape[0] = dim.size; + new_shape.prepend(win_count); + let mut val: Value = Array::new(new_shape, data).into(); + if let Some((f, d)) = f { + val = f(val, dims.len() + d, env)?; + } + env.push(val); + return Ok(()); + } + WindowAction::Box(mut boxes, _) => { + for i in 0..win_count { + boxes.push(Boxed( + arr.slice_rows(i * dim.stride, i * dim.stride + dim.size) + .into(), + )); } - WindowAction::Default(..) => {} + env.push(Array::from(boxes)); + return Ok(()); } + WindowAction::Default(..) => {} } } @@ -226,9 +225,8 @@ where if *o < d.size - 1 { *o += 1; continue 'window; - } else { - *o = 0; } + *o = 0; } break; } @@ -253,9 +251,8 @@ where if *c < maxs[i] - dims[i].stride as isize - dims[i].size as isize + 1 { *c += dims[i].stride as isize; continue 'windows; - } else { - *c = corner_starts[i]; } + *c = corner_starts[i]; } break; } diff --git a/src/algorithm/tuples.rs b/src/algorithm/tuples.rs index 84954b81c..205cefb8a 100644 --- a/src/algorithm/tuples.rs +++ b/src/algorithm/tuples.rs @@ -54,14 +54,13 @@ fn tuple1(f: SigNode, env: &mut Uiua) -> UiuaResult { xs.shape.prepend(0); if push_empty_rows_value(&f, [&xs], false, &mut per_meta, env) { return Ok(()); - } else { - let mut proxy = xs.proxy_row(env); - proxy.fix(); - env.push(proxy); - _ = env.exec_maintain_sig(f); - if has_output { - results.push(env.pop("tuples' function result")?); - } + } + let mut proxy = xs.proxy_row(env); + proxy.fix(); + env.push(proxy); + _ = env.exec_maintain_sig(f); + if has_output { + results.push(env.pop("tuples' function result")?); } } else { env.without_fill(|env| -> UiuaResult { diff --git a/src/algorithm/zip.rs b/src/algorithm/zip.rs index 455892328..829c699e8 100644 --- a/src/algorithm/zip.rs +++ b/src/algorithm/zip.rs @@ -228,9 +228,8 @@ fn f_mon_fast_fn_impl(nodes: &[Node], deep: bool, env: &Uiua) -> Option<(ValueMo } if start == nodes.len() { break; - } else { - return None; } + return None; } (func?, depth.unwrap_or(0)) } @@ -699,7 +698,7 @@ pub fn rows1(f: SigNode, mut xs: Value, depth: usize, inv: bool, env: &mut Uiua) new_rows[i].push(env.pop("rows' function result")?); } } - }; + } collect_outputs(new_rows, is_scalar, is_empty, per_meta, env) } @@ -778,7 +777,7 @@ fn rows2( new_rows[i].push(env.pop("rows's function result")?); } } - }; + } collect_outputs(new_rows, false, is_empty, per_meta, env) } (1, _) => { @@ -821,7 +820,7 @@ fn rows2( new_rows[i].push(env.pop("rows's function result")?); } } - }; + } collect_outputs(new_rows, false, is_empty, per_meta, env) } (a, b) => { @@ -882,7 +881,7 @@ fn rows2( new_rows[i].push(env.pop("rows's function result")?); } } - }; + } collect_outputs(new_rows, false, is_empty, per_meta, env) } } @@ -934,7 +933,7 @@ fn rowsn(f: SigNode, args: Vec, depth: usize, inv: bool, env: &mut Uiua) new_values[i].push(env.pop("rows's function result")?); } } - }; + } for new_values in new_values.into_iter().rev() { let mut rowsed = Value::from_row_values(new_values, env)?; if all_scalar { diff --git a/src/compile/binding.rs b/src/compile/binding.rs index 5471300e0..b6d520b9e 100644 --- a/src/compile/binding.rs +++ b/src/compile/binding.rs @@ -385,10 +385,9 @@ impl Compiler { declared_sig.value ), )); - } else { - node = self.force_sig(node, declared_sig.value, &declared_sig.span)?; - sig = declared_sig.value; } + node = self.force_sig(node, declared_sig.value, &declared_sig.span)?; + sig = declared_sig.value; } } diff --git a/src/compile/mod.rs b/src/compile/mod.rs index 435f4da92..cbee2f836 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -910,7 +910,7 @@ impl Compiler { cache.borrow_mut().insert(path.clone(), clone); }); } - }; + } } let module = self.imports.get(&path).unwrap(); if module.experimental { diff --git a/src/compile/modifier.rs b/src/compile/modifier.rs index 79e2b6feb..30b2877a7 100644 --- a/src/compile/modifier.rs +++ b/src/compile/modifier.rs @@ -271,7 +271,7 @@ impl Compiler { ), )) } - }; + } let set_inverses = SetInverses { un: cust.un.is_some(), anti: cust.anti.is_some(), diff --git a/src/ffi.rs b/src/ffi.rs index cbd2987a0..90f1a628e 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -130,7 +130,7 @@ impl FromStr for FfiType { _ => None, } { return Ok(ty); - }; + } // Struct if let Some(body) = input @@ -171,9 +171,8 @@ impl FromStr for FfiType { if depth != 0 { return Err(format!("Unmatched opening braces `{original}`")); - } else { - return Ok(Self::Struct(fields)); } + return Ok(Self::Struct(fields)); } Err(format!("Unknown C type `{original}`")) diff --git a/src/lsp.rs b/src/lsp.rs index c96ffccee..93dffc286 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -1248,7 +1248,7 @@ mod server { })) } ImportSrc::File(_) => {} - }; + } } } // Hovering an arg setter @@ -2009,7 +2009,7 @@ mod server { }))) } ImportSrc::Git(_) => {} - }; + } } } Ok(None) diff --git a/src/main.rs b/src/main.rs index f343208d6..d5019d10f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1081,18 +1081,17 @@ fn update(main: bool, check: bool, mut features: Vec) { if local >= remote { println!("Your version of Uiua ({local_version}) is the latest!"); return; - } else { - println!( - "{}\n", - format!( - "Update available: {local_version} → {remote_version}\n\ - Run `uiua update` to update\n\ - Changelog: https://github.com/uiua-lang/uiua/blob/main/changelog.md", - ) - .bright_white() - .bold() - ); } + println!( + "{}\n", + format!( + "Update available: {local_version} → {remote_version}\n\ + Run `uiua update` to update\n\ + Changelog: https://github.com/uiua-lang/uiua/blob/main/changelog.md", + ) + .bright_white() + .bold() + ); } if check { return; diff --git a/src/sys/native.rs b/src/sys/native.rs index 0346ae5cd..1a21142a2 100644 --- a/src/sys/native.rs +++ b/src/sys/native.rs @@ -122,10 +122,9 @@ impl WebcamChannel { if recv_tries > 100 { _ = camera.stop_stream(); break; - } else { - sleep(); - continue; } + sleep(); + continue; } recv_tries = 0; let res = camera diff --git a/src/window.rs b/src/window.rs index d3c91849a..c5ffc4a34 100644 --- a/src/window.rs +++ b/src/window.rs @@ -138,7 +138,7 @@ pub fn run_window() { Err(e) => { eprintln!("Failed to accept connection: {e}") } - }; + } } }); let icon = image::load_from_memory(include_bytes!("assets/uiua-logo-512.png")).unwrap(); From c83a758da6f0f3d543bcf2905a4a4dbf0a1e2682 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 20:24:53 +0300 Subject: [PATCH 14/21] lint: fix clippy::pedantic (16-20 entries) --- Cargo.toml | 4 +-- site/src/main.rs | 24 ++++++++------- site/src/markdown.rs | 8 ++--- site/src/primitive.rs | 26 +++++++++++----- src/algorithm/dyadic/structure.rs | 2 +- src/algorithm/map.rs | 2 +- src/algorithm/monadic/mod.rs | 13 ++++---- src/algorithm/stencil.rs | 10 +++---- src/array.rs | 14 +++++---- src/compile/data.rs | 8 ++++- src/compile/mod.rs | 17 +++++------ src/compile/modifier.rs | 2 +- src/compile/optimize.rs | 4 +-- src/ffi.rs | 10 +++---- src/lib.rs | 49 ++++++++++++++++--------------- src/run_prim.rs | 26 +++++++++++----- src/sys/native.rs | 6 ++-- src/tree.rs | 4 +-- src/value.rs | 9 ++++-- 19 files changed, 136 insertions(+), 102 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b43049222..69aa6c299 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,7 @@ dbg_macro = "warn" print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} -manual_assert = "allow" # 16 -inline_always = "allow" # 18 -from_iter_instead_of_collect = "allow" # 20 +inline_always = "allow" # TODO: benchmark inlines default_trait_access = "allow" # 23 format_push_string = "allow" # 27 missing_panics_doc = "allow" # 37 diff --git a/site/src/main.rs b/site/src/main.rs index d8f958022..138c92852 100644 --- a/site/src/main.rs +++ b/site/src/main.rs @@ -665,19 +665,21 @@ fn site() { (Err(_), true) => {} (Ok(mut comp), should_fail) => { if let Some(diag) = comp.take_diagnostics().into_iter().next() { - if !should_fail { - panic!( - "Test failed in {}\n{}\n{}", - path.display(), - code, - diag.report() - ); - } + assert!( + should_fail, + "Test failed in {}\n{}\n{}", + path.display(), + code, + diag.report() + ); continue; } - if should_fail { - panic!("Test should have failed in {}\n{}", path.display(), code); - } + assert!( + !should_fail, + "Test should have failed in {}\n{}", + path.display(), + code + ) } } } diff --git a/site/src/markdown.rs b/site/src/markdown.rs index 3bb83f601..9fa3f30b0 100644 --- a/site/src/markdown.rs +++ b/site/src/markdown.rs @@ -475,11 +475,9 @@ fn text_code_blocks() { Err(e) => Some(e.report()), }; if let Some(report) = failure_report { - if !should_fail { - panic!("\nBlock failed:\n{block}\n{report}") - } - } else if should_fail { - panic!("\nBlock should have failed:\n{block}") + assert!(should_fail, "\nBlock failed:\n{block}\n{report}"); + } else { + assert!(!should_fail, "\nBlock should have failed:\n{block}"); } } } diff --git a/site/src/primitive.rs b/site/src/primitive.rs index 6125f6f20..9965b66ac 100644 --- a/site/src/primitive.rs +++ b/site/src/primitive.rs @@ -433,17 +433,27 @@ fn prim_docs() { match Uiua::with_backend(WebBackend::default()).run_str(ex.input()) { Ok(mut comp) => { if let Some(diag) = comp.take_diagnostics().into_iter().next() { - if !ex.should_error() { - panic!("\nExample failed:\n{}\n{}", ex.input(), diag.report()); - } - } else if ex.should_error() { - panic!("Example should have failed: {}", ex.input()); + assert!( + ex.should_error(), + "\nExample failed:\n{}\n{}", + ex.input(), + diag.report() + ); + } else { + assert!( + !ex.should_error(), + "Example should have failed: {}", + ex.input() + ); } } Err(e) => { - if !ex.should_error() { - panic!("\nExample failed:\n{}\n{}", ex.input(), e.report()); - } + assert!( + ex.should_error(), + "\nExample failed:\n{}\n{}", + ex.input(), + e.report() + ); } } } diff --git a/src/algorithm/dyadic/structure.rs b/src/algorithm/dyadic/structure.rs index 86491298c..97b3633fc 100644 --- a/src/algorithm/dyadic/structure.rs +++ b/src/algorithm/dyadic/structure.rs @@ -1615,7 +1615,7 @@ impl Array { .map(|&i| normalize_index(i, indices.len())) .collect(); let outer_rank = indices_shape.last().copied().unwrap_or(1); - let mut outer_shape = Shape::from_iter(repeat_n(0, outer_rank)); + let mut outer_shape = repeat_n(0, outer_rank).collect::(); if !normalized_indices.is_empty() { for index in normalized_indices.chunks_exact(index_size) { for (d, &i) in outer_shape.iter_mut().zip(index) { diff --git a/src/algorithm/map.rs b/src/algorithm/map.rs index b1e4d7428..c8e8cf845 100644 --- a/src/algorithm/map.rs +++ b/src/algorithm/map.rs @@ -818,7 +818,7 @@ fn coerce_values( } if let Value::Box(b_arr) = &b { if b_arr.rank() == 0 && !matches!(a, Value::Box(_)) { - *a = Array::from_iter(a.rows().map(Boxed)).into(); + *a = a.rows().map(Boxed).collect::>().into(); return Ok(b); } } diff --git a/src/algorithm/monadic/mod.rs b/src/algorithm/monadic/mod.rs index 090e48f45..a6e8f6678 100644 --- a/src/algorithm/monadic/mod.rs +++ b/src/algorithm/monadic/mod.rs @@ -765,7 +765,7 @@ impl Value { if ishape.is_empty() { return Ok(Array::::new(0, CowSlice::new()).into()); } - let mut shape = Shape::from_iter(ishape.iter().map(|d| d.unsigned_abs())); + let mut shape = ishape.iter().map(|d| d.unsigned_abs()).collect::(); shape.push(shape.len()); let data = range(&ishape, start, env)?; let mut value: Value = match data { @@ -783,9 +783,9 @@ impl Value { env, "Shape should be a single integer or a list of integers", )?; - let shape = Shape::from_iter(ishape.iter().map(|n| n.unsigned_abs())); + let shape = ishape.iter().map(|n| n.unsigned_abs()).collect::(); let elems: usize = validate_size::(shape.iter().copied(), env)?; - let data = EcoVec::from_iter((0..elems).map(|i| i as f64)); + let data = (0..elems).map(|i| i as f64).collect::>(); let mut arr = Array::new(shape, data); let first_max = ishape.first().copied().unwrap_or(0); for (i, s) in ishape.into_iter().enumerate() { @@ -1298,7 +1298,7 @@ impl Array { return; } let subshape = Shape::from(&self.shape[depth..]); - let newshape = Shape::from_iter(subshape.iter().rev().copied()); + let newshape = subshape.iter().rev().copied().collect::(); let chunk_size = subshape.elements(); let data_slice = self.data.as_mut_slice(); let mut temp = data_slice[..chunk_size].to_vec(); @@ -2014,7 +2014,10 @@ impl Value { /// Convert a string value to a list of UTF-16 code units pub fn utf16(&self, env: &Uiua) -> UiuaResult { let s = self.as_string(env, "Argument to utf₁₆ must be a string")?; - Ok(Array::::from_iter(s.encode_utf16().map(|u| u as f64)).into()) + Ok(s.encode_utf16() + .map(|u| u as f64) + .collect::>() + .into()) } /// Convert a list of UTF-8 bytes to a string value pub fn unutf8(&self, env: &Uiua) -> UiuaResult { diff --git a/src/algorithm/stencil.rs b/src/algorithm/stencil.rs index 24ac630bb..73ffe48cc 100644 --- a/src/algorithm/stencil.rs +++ b/src/algorithm/stencil.rs @@ -86,11 +86,11 @@ where let total_len = *s + 2 * d.fill * d.stride; shape_prefix.push((total_len + d.stride).saturating_sub(d.size) / d.stride); } - let window_shape = Shape::from_iter( - dims.iter() - .map(|d| d.size) - .chain(arr.shape.iter().skip(dims.len()).copied()), - ); + let window_shape = dims + .iter() + .map(|d| d.size) + .chain(arr.shape.iter().skip(dims.len()).copied()) + .collect::(); if shape_prefix.contains(&0) { let mut shape = shape_prefix; shape.extend(window_shape); diff --git a/src/array.rs b/src/array.rs index 75dae36ab..c680857fc 100644 --- a/src/array.rs +++ b/src/array.rs @@ -500,9 +500,10 @@ impl Array { return row; } let row_count = self.row_count(); - if row >= row_count { - panic!("row index out of bounds: {row} >= {row_count}"); - } + assert!( + row < row_count, + "row index out of bounds: {row} >= {row_count}" + ); let row_len = self.row_len(); let start = row * row_len; let end = start + row_len; @@ -605,9 +606,10 @@ impl Array { return row; } let row_count: usize = self.shape[..=depth].iter().product(); - if row >= row_count { - panic!("row index out of bounds: {row} >= {row_count}"); - } + assert!( + row < row_count, + "row index out of bounds: {row} >= {row_count}" + ); let row_len: usize = self.shape[depth + 1..].iter().product(); let start = row * row_len; let end = start + row_len; diff --git a/src/compile/data.rs b/src/compile/data.rs index d4317d1ee..5ed28fb75 100644 --- a/src/compile/data.rs +++ b/src/compile/data.rs @@ -348,7 +348,13 @@ impl Compiler { self.compile_bind_const( name, local, - Some(Array::from_iter(fields.iter().map(|f| f.name.as_str())).into()), + Some( + fields + .iter() + .map(|f| f.name.as_str()) + .collect::>() + .into(), + ), span, BindingMeta { comment: Some(DocComment::from(comment.as_str())), diff --git a/src/compile/mod.rs b/src/compile/mod.rs index cbee2f836..132dd7346 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -1325,7 +1325,7 @@ impl Compiler { } self.code_meta.strands.insert(word.span.clone(), just_spans); // Flatten instrs - let inner = Node::from_iter(op_nodes.into_iter().map(|sn| sn.node)); + let inner = op_nodes.into_iter().map(|sn| sn.node).collect::(); // Normal strand @@ -1584,9 +1584,9 @@ impl Compiler { } let diff = (new_delta - delta).unsigned_abs(); let spandex = self.add_span(span.clone()); - let mut extra = Node::from_iter( - (0..diff).map(|i| Node::new_push(Boxed(Value::from(format!("dbg-{}", i + 1))))), - ); + let mut extra = (0..diff) + .map(|i| Node::new_push(Boxed(Value::from(format!("dbg-{}", i + 1))))) + .collect::(); for _ in 0..sig.outputs() { extra = Node::Mod(Primitive::Dip, eco_vec![extra.sig_node().unwrap()], spandex); } @@ -1613,8 +1613,9 @@ impl Compiler { } let diff = (delta - new_delta).unsigned_abs(); let spandex = self.add_span(span.clone()); - let mut pops = - Node::from_iter((0..diff).map(|_| Node::Prim(Primitive::Pop, spandex))); + let mut pops = (0..diff) + .map(|_| Node::Prim(Primitive::Pop, spandex)) + .collect::(); for _ in 0..new_sig.outputs() { pops = Node::Mod(Primitive::Dip, eco_vec![pops.sig_node().unwrap()], spandex); } @@ -2360,9 +2361,7 @@ impl Compiler { Join => match self.positive_subscript(n, Join, &span) { 0 => Node::new_push(Value::default()), 1 => Node::Prim(Identity, self.add_span(span)), - n => { - Node::from_iter(repeat_n(Node::Prim(Join, self.add_span(span)), n - 1)) - } + n => repeat_n(Node::Prim(Join, self.add_span(span)), n - 1).collect(), }, Box => Node::Array { len: self.positive_subscript(n, Box, &span), diff --git a/src/compile/modifier.rs b/src/compile/modifier.rs index 30b2877a7..62651284a 100644 --- a/src/compile/modifier.rs +++ b/src/compile/modifier.rs @@ -802,7 +802,7 @@ impl Compiler { let mut dups = if n == 0 { Node::Prim(Pop, span) } else { - Node::from_iter(repeat_n(Node::Prim(Dup, span), n - 1)) + repeat_n(Node::Prim(Dup, span), n - 1).collect() }; if side.side == SubSide::Right && n < sig.args() { dups = dups.sig_node().unwrap().dipped(sig.args() - n, span).node; diff --git a/src/compile/optimize.rs b/src/compile/optimize.rs index 6fc376e58..6940d6f1c 100644 --- a/src/compile/optimize.rs +++ b/src/compile/optimize.rs @@ -482,7 +482,7 @@ impl Optimization for ByToDup { } } } - let mut composed = Node::from_iter(nodes[i - back..i].iter().cloned()); + let mut composed = nodes[i - back..i].iter().cloned().collect::(); let mut dup = Prim(Dup, *span); if dip { dup = Mod(Dip, eco_vec![dup.sig_node().unwrap()], *span); @@ -519,7 +519,7 @@ impl Optimization for RowsFlipOpt { let [Prim(Flip, flip_span), rest @ ..] = f.node.as_slice() else { return None; }; - let args = eco_vec![Node::from_iter(rest.iter().cloned()).sig_node().ok()?]; + let args = eco_vec![rest.iter().cloned().collect::().sig_node().ok()?]; let node = Node::from_iter([Prim(Flip, *flip_span), Mod(Rows, args, *span)]); Some((1, node)) }) diff --git a/src/ffi.rs b/src/ffi.rs index 90f1a628e..a0b13bffa 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -334,7 +334,7 @@ mod enabled { let mut out_values = out_values; out_values.pop().unwrap() } else { - Array::from_iter([ret].into_iter().chain(out_values).map(Boxed)).into() + [ret].into_iter().chain(out_values).map(Boxed).collect::>().into() } }; @@ -466,13 +466,11 @@ mod enabled { FfiType::ULong => arr!(c_ulong), FfiType::ULongLong => arr!(c_ulonglong), _ => Ok(if ptr.ty.is_string() { - Value::from_iter( - (0..len) + (0..len) .map(|index| ptr.ty.unrepr(&repr[index * size..(index + 1) * size])) .collect::, String>>()? .into_iter() - .map(Boxed), - ) + .map(Boxed).collect() } else { Value::from_row_values_infallible( (0..len) @@ -760,7 +758,7 @@ mod enabled { let value = if fields.iter().all(FfiType::is_num) { Value::from_row_values_infallible(rows) } else { - Array::from_iter(rows.into_iter().map(Boxed)).into() + rows.into_iter().map(Boxed).collect::>().into() }; Ok(value) diff --git a/src/lib.rs b/src/lib.rs index 2bccccba0..325d3b6ab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -265,12 +265,12 @@ mod tests { panic!("Test failed in {}:\n{}", path.display(), diag.report()); } let (stack, under_stack) = env.take_stacks(); - if !stack.is_empty() { - panic!("{} had a non-empty stack", path.display()); - } - if !under_stack.is_empty() { - panic!("{} had a non-empty under stack", path.display()); - } + assert!(stack.is_empty(), "{} had a non-empty stack", path.display()); + assert!( + under_stack.is_empty(), + "{} had a non-empty under stack", + path.display() + ); // Make sure lsp spans doesn't panic _ = Spans::from_input(&code); @@ -320,14 +320,13 @@ mod tests { } Err(e) => { let message = e.to_string(); - if message.contains("interpreter") { - panic!( - "Test resulted in an interpreter bug in {}:\n{}\n{}", - path.display(), - e.report(), - section - ); - } + assert!( + !message.contains("interpreter"), + "Test resulted in an interpreter bug in {}:\n{}\n{}", + path.display(), + e.report(), + section + ) } } } @@ -358,17 +357,21 @@ mod tests { } } + #[expect(clippy::assertions_on_constants)] #[test] fn no_dbgs() { - if crate::compile::invert::DEBUG { - panic!("compile::invert::DEBUG is true"); - } - if crate::compile::optimize::DEBUG { - panic!("compile::optimize::DEBUG is true"); - } - if crate::compile::algebra::DEBUG { - panic!("compile::algebra::DEBUG is true"); - } + assert!( + !crate::compile::invert::DEBUG, + "compile::invert::DEBUG is true" + ); + assert!( + !crate::compile::optimize::DEBUG, + "compile::optimize::DEBUG is true" + ); + assert!( + !crate::compile::algebra::DEBUG, + "compile::algebra::DEBUG is true" + ) } #[test] diff --git a/src/run_prim.rs b/src/run_prim.rs index 6547a93e8..f78a37c95 100644 --- a/src/run_prim.rs +++ b/src/run_prim.rs @@ -2225,17 +2225,27 @@ mod tests { match env.run_str(&ex.input) { Ok(mut comp) => { if let Some(diag) = comp.take_diagnostics().into_iter().next() { - if !ex.should_error { - panic!("\nExample failed:\n{}\n{}", ex.input, diag.report()); - } - } else if ex.should_error { - panic!("Example should have failed: {}", ex.input); + assert!( + ex.should_error, + "\nExample failed:\n{}\n{}", + ex.input, + diag.report() + ); + } else { + assert!( + !ex.should_error, + "Example should have failed: {}", + ex.input + ); } } Err(e) => { - if !ex.should_error { - panic!("\nExample failed:\n{}\n{}", ex.input, e.report()); - } + assert!( + ex.should_error, + "\nExample failed:\n{}\n{}", + ex.input, + e.report() + ); } } } diff --git a/src/sys/native.rs b/src/sys/native.rs index 1a21142a2..f366854c3 100644 --- a/src/sys/native.rs +++ b/src/sys/native.rs @@ -927,8 +927,10 @@ impl SysBackend for NativeSys { #[cfg(feature = "tls")] fn tls_connect(&self, addr: &str) -> Result { let handle = NATIVE_SYS.new_handle(); - let root_store = - rustls::RootCertStore::from_iter(webpki_roots::TLS_SERVER_ROOTS.iter().cloned()); + let root_store = webpki_roots::TLS_SERVER_ROOTS + .iter() + .cloned() + .collect::(); let config = rustls::ClientConfig::builder() .with_root_certificates(root_store) .with_no_client_auth(); diff --git a/src/tree.rs b/src/tree.rs index 65b23e730..59b64466b 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -354,7 +354,7 @@ impl Node { where R: SliceIndex<[Node], Output = [Node]>, { - Self::from_iter(self.as_slice()[range].iter().cloned()) + self.as_slice()[range].iter().cloned().collect() } /// Get a mutable vector of the nodes in this node /// @@ -639,7 +639,7 @@ impl Node { impl From<&[Node]> for Node { fn from(nodes: &[Node]) -> Self { - Node::from_iter(nodes.iter().cloned()) + nodes.iter().cloned().collect() } } diff --git a/src/value.rs b/src/value.rs index 33f97d13f..7689628ab 100644 --- a/src/value.rs +++ b/src/value.rs @@ -1843,9 +1843,12 @@ impl Value { let meta = chars.meta.get_mut().map(take); let mut rows = Vec::new(); for row in chars.row_shaped_slices(Shape::from(*chars.shape.last().unwrap())) { - rows.push(Array::::from_iter( - row.data.iter().flat_map(|c| c.to_uppercase()), - )); + rows.push( + row.data + .iter() + .flat_map(|c| c.to_uppercase()) + .collect::>(), + ); } let mut arr = Array::from_row_arrays(rows, env)?; let last = arr.shape.pop().unwrap(); From a55ae20edb51cf967a3af4a1e44d534ff2c80441 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 20:54:47 +0300 Subject: [PATCH 15/21] lint: fix clippy::default_trait_access --- Cargo.toml | 1 - pad/editor/src/backend.rs | 6 +++--- pad/editor/src/lib.rs | 2 +- site/src/markdown.rs | 2 +- src/algorithm/ga.rs | 7 ++++--- src/algorithm/groups.rs | 5 +++-- src/algorithm/media.rs | 2 +- src/algorithm/pervade.rs | 3 ++- src/compile/binding.rs | 2 +- src/compile/invert/un.rs | 6 +++--- src/compile/invert/under.rs | 4 ++-- src/compile/mod.rs | 2 +- src/compile/modifier.rs | 2 +- src/main.rs | 10 +++++----- src/run.rs | 4 ++-- src/sys/native.rs | 2 +- src/window.rs | 5 +++-- 17 files changed, 34 insertions(+), 31 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 69aa6c299..a6e1cc782 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,6 @@ print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} inline_always = "allow" # TODO: benchmark inlines -default_trait_access = "allow" # 23 format_push_string = "allow" # 27 missing_panics_doc = "allow" # 37 used_underscore_binding = "allow" # 39 diff --git a/pad/editor/src/backend.rs b/pad/editor/src/backend.rs index ec0e32b7a..7d8ab3c86 100644 --- a/pad/editor/src/backend.rs +++ b/pad/editor/src/backend.rs @@ -70,7 +70,7 @@ pub fn delete_file(path: &PathBuf) { } thread_local! { - static BREAKPOINTS: RefCell> = Default::default(); + static BREAKPOINTS: RefCell> = RefCell::default(); } impl Default for WebBackend { @@ -434,8 +434,8 @@ impl SysBackend for WebBackend { } fn load_git_module(&self, original_url: &str, target: GitTarget) -> Result { thread_local! { - static CACHE: RefCell>> = Default::default(); - static WORKING: RefCell> = Default::default(); + static CACHE: RefCell>> = RefCell::default(); + static WORKING: RefCell> = RefCell::default(); } fn cache_url(url: &str, res: Result) { diff --git a/pad/editor/src/lib.rs b/pad/editor/src/lib.rs index bfdd94f8a..491fdf80f 100644 --- a/pad/editor/src/lib.rs +++ b/pad/editor/src/lib.rs @@ -131,7 +131,7 @@ pub fn Editor<'a>( let (fullscreen_enabled, set_fullscreen_enabled) = create_signal(false); let update_token_count = move |code: &str| { set_token_count.set( - lex(code, (), &mut Default::default()) + lex(code, (), &mut uiua::Inputs::default()) .0 .into_iter() .filter(|tok| { diff --git a/site/src/markdown.rs b/site/src/markdown.rs index 9fa3f30b0..59ab33a50 100644 --- a/site/src/markdown.rs +++ b/site/src/markdown.rs @@ -182,7 +182,7 @@ fn node_view<'a>(node: &'a AstNode<'a>) -> View { if block.literal.trim() == "LOGO" { view!().into_view() } else if (block.info.is_empty() || block.info.starts_with("uiua")) - && uiua::parse(&block.literal, (), &mut Default::default()) + && uiua::parse(&block.literal, (), &mut Inputs::default()) .1 .is_empty() { diff --git a/src/algorithm/ga.rs b/src/algorithm/ga.rs index ce792d076..aa8cb20a0 100644 --- a/src/algorithm/ga.rs +++ b/src/algorithm/ga.rs @@ -9,8 +9,9 @@ use ecow::{eco_vec, EcoVec}; use serde::*; use crate::{ - algorithm::pervade::derive_new_shape, grid_fmt::GridFmt, is_default, Array, Boxed, Primitive, - Shape, Uiua, UiuaResult, Value, + algorithm::pervade::derive_new_shape, + grid_fmt::{GridFmt, GridFmtParams}, + is_default, Array, Boxed, Primitive, Shape, Uiua, UiuaResult, Value, }; macro_rules! ga_op { @@ -1259,7 +1260,7 @@ pub fn unparse(spec: Spec, val: Value, env: &Uiua) -> UiuaResult { } let mask = mask_table[i]; if n.abs() != 1.0 || mask == 0 { - let n_grid = n.abs().fmt_grid(Default::default()); + let n_grid = n.abs().fmt_grid(GridFmtParams::default()); s.extend(n_grid.into_iter().next().unwrap()); } if mask == 0 { diff --git a/src/algorithm/groups.rs b/src/algorithm/groups.rs index 949321ac4..7fd5a65c5 100644 --- a/src/algorithm/groups.rs +++ b/src/algorithm/groups.rs @@ -7,7 +7,8 @@ use ecow::{eco_vec, EcoVec}; use crate::{ cowslice::CowSlice, get_ops, types::push_empty_rows_value, val_as_arr, Array, ArrayValue, - Boxed, Node, Ops, Primitive, ScalarNum, Shape, SigNode, Uiua, UiuaResult, Value, + Boxed, Node, Ops, PersistentMeta, Primitive, ScalarNum, Shape, SigNode, Uiua, UiuaResult, + Value, }; use super::multi_output; @@ -753,7 +754,7 @@ where .collect::>()?; if indices.shape == [0] - && push_empty_rows_value(&f, &values, false, &mut Default::default(), env) + && push_empty_rows_value(&f, &values, false, &mut PersistentMeta::default(), env) { return Ok(()); } diff --git a/src/algorithm/media.rs b/src/algorithm/media.rs index 1a663a8f9..95515a8da 100644 --- a/src/algorithm/media.rs +++ b/src/algorithm/media.rs @@ -740,7 +740,7 @@ pub fn gif_bytes_to_value(bytes: &[u8]) -> Result<(f64, Value), gif::DecodingErr let first_frame = decoder.read_next_frame()?.unwrap(); let gif_width = first_frame.width as usize; let gif_height = first_frame.height as usize; - let mut data: crate::cowslice::CowSlice = Default::default(); + let mut data = crate::cowslice::CowSlice::new(); let mut frame_count = 1; let mut delay_sum = first_frame.delay as f64 / 100.0; // Init frame data with the first frame diff --git a/src/algorithm/pervade.rs b/src/algorithm/pervade.rs index f8885dc47..c910d70e6 100644 --- a/src/algorithm/pervade.rs +++ b/src/algorithm/pervade.rs @@ -8,6 +8,7 @@ use std::{ use ecow::eco_vec; use crate::algorithm::validate_size; +use crate::cowslice::CowSlice; use crate::fill::FillValue; use crate::{algorithm::loops::flip, array::*, Uiua, UiuaError, UiuaResult, Value}; use crate::{Complex, Shape}; @@ -639,7 +640,7 @@ where if new_shape.contains(&0) { b.shape = new_shape; - b.data = Default::default(); + b.data = CowSlice::new(); } else if new_shape == b.shape { // The existing array can be used if a.shape == b.shape { diff --git a/src/compile/binding.rs b/src/compile/binding.rs index b6d520b9e..1a2a63c5b 100644 --- a/src/compile/binding.rs +++ b/src/compile/binding.rs @@ -476,7 +476,7 @@ impl Compiler { sig, explicit: binding.signature.is_some(), inline: false, - set_inverses: Default::default(), + set_inverses: SetInverses::default(), }, ); } diff --git a/src/compile/invert/un.rs b/src/compile/invert/un.rs index c0984c9ae..9af4f4acc 100644 --- a/src/compile/invert/un.rs +++ b/src/compile/invert/un.rs @@ -33,7 +33,7 @@ pub fn un_inverse(input: &[Node], asm: &Assembly) -> InversionResult { } thread_local! { - static CACHE: RefCell>> = Default::default(); + static CACHE: RefCell>> = RefCell::default(); } let mut hasher = DefaultHasher::new(); for node in input { @@ -95,7 +95,7 @@ fn anti_inverse(input: &[Node], asm: &Assembly, for_un: bool) -> InversionResult return generic(); } thread_local! { - static CACHE: RefCell>> = Default::default(); + static CACHE: RefCell>> = RefCell::default(); } let mut hasher = DefaultHasher::new(); for node in input { @@ -445,7 +445,7 @@ inverse!(BothPat, input, asm, Both, span, [f], { let inv = f.un_inverse(asm)?; Ok(( input, - ImplMod(UnBothImpl(Default::default()), eco_vec![inv], span), + ImplMod(UnBothImpl(Subscript::default()), eco_vec![inv], span), )) }); diff --git a/src/compile/invert/under.rs b/src/compile/invert/under.rs index e0dc014a6..a51d7d45d 100644 --- a/src/compile/invert/under.rs +++ b/src/compile/invert/under.rs @@ -39,7 +39,7 @@ fn under_inverse( type Key = (u64, Signature, bool); thread_local! { - static CACHE: RefCell>> = Default::default(); + static CACHE: RefCell>> = RefCell::default(); } let mut hasher = DefaultHasher::new(); for node in input { @@ -416,7 +416,7 @@ under!(BothPat, input, g_sig, inverse, asm, { (input, None) }; let (sub, args, span, input) = match input { - [Mod(Both, args, span), input @ ..] => (Default::default(), args, span, input), + [Mod(Both, args, span), input @ ..] => (Subscript::default(), args, span, input), [ImplMod(BothImpl(sub), args, span), input @ ..] => (*sub, args, span, input), _ => return generic(), }; diff --git a/src/compile/mod.rs b/src/compile/mod.rs index 132dd7346..2d362a0d4 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -2051,7 +2051,7 @@ impl Compiler { sig, explicit: func.signature.is_some(), inline: true, - set_inverses: Default::default(), + set_inverses: SetInverses::default(), }, ); } diff --git a/src/compile/modifier.rs b/src/compile/modifier.rs index 62651284a..3934a1d94 100644 --- a/src/compile/modifier.rs +++ b/src/compile/modifier.rs @@ -1491,7 +1491,7 @@ impl Compiler { let sig = self.sig_of(&root, &mac.func.span)?; let code_mac = CodeMacro { root: SigNode::new(sig, root), - names: Default::default(), + names: IndexMap::new(), }; self.code_macro(None, span, operands, code_mac)? } else { diff --git a/src/main.rs b/src/main.rs index d5019d10f..1710e092b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,9 +27,9 @@ use uiua::{ format::{format_file, format_str, FormatConfig, FormatConfigSource}, lex, lsp::BindingDocsKind, - parse, print_stack, Assembly, CodeSpan, Compiler, NativeSys, PreEvalMode, PrimClass, PrimDoc, - PrimDocFragment, PrimDocLine, Primitive, RunMode, SafeSys, SpanKind, Spans, Subscript, Token, - Uiua, UiuaError, UiuaErrorKind, UiuaResult, CONSTANTS, + parse, print_stack, Assembly, CodeSpan, Compiler, Inputs, NativeSys, PreEvalMode, PrimClass, + PrimDoc, PrimDocFragment, PrimDocLine, Primitive, RunMode, SafeSys, SpanKind, Spans, Subscript, + Token, Uiua, UiuaError, UiuaErrorKind, UiuaResult, CONSTANTS, }; static PRESSED_CTRL_C: AtomicBool = AtomicBool::new(false); @@ -231,7 +231,7 @@ fn main() { exit(1); } }; - let mut inputs = Default::default(); + let mut inputs = Inputs::default(); let (items, errors, _) = parse(&input, &path, &mut inputs); if !errors.is_empty() { eprintln!( @@ -1472,7 +1472,7 @@ fn find(path: Option, text: String, raw: bool) -> UiuaResult { } } Needle::Prim(prim) => { - let (tokens, ..) = lex(&contents, (), &mut Default::default()); + let (tokens, ..) = lex(&contents, (), &mut Inputs::default()); for tok in tokens { let Token::Glyph(prim2) = &tok.value else { continue; diff --git a/src/run.rs b/src/run.rs index 97cd81a23..2b92b4c48 100644 --- a/src/run.rs +++ b/src/run.rs @@ -140,8 +140,8 @@ struct ThisThread { impl Default for ThisThread { fn default() -> Self { Self { - parent: Default::default(), - children: Default::default(), + parent: None, + children: HashMap::new(), next_child_id: 1, } } diff --git a/src/sys/native.rs b/src/sys/native.rs index f366854c3..c584365ee 100644 --- a/src/sys/native.rs +++ b/src/sys/native.rs @@ -226,7 +226,7 @@ impl Default for GlobalNativeSys { audio_time_socket: parking_lot::Mutex::new(None), colored_errors: DashMap::new(), #[cfg(feature = "ffi")] - ffi: Default::default(), + ffi: crate::FfiState::default(), #[cfg(all(feature = "gif", feature = "invoke"))] gifs_child: parking_lot::Mutex::new(None), } diff --git a/src/window.rs b/src/window.rs index c5ffc4a34..525da0955 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1,4 +1,5 @@ use std::{ + collections::HashMap, env::current_exe, fs, io::{ErrorKind, Read, Write}, @@ -200,7 +201,7 @@ struct Cache { ppp: f32, image_scale: f32, #[cfg(feature = "audio")] - samples_map: std::collections::HashMap, + samples_map: HashMap, last_frame: Instant, errors: Vec, } @@ -273,7 +274,7 @@ impl App { ppp, image_scale: 1.0, #[cfg(feature = "audio")] - samples_map: Default::default(), + samples_map: HashMap::new(), last_frame: Instant::now(), errors: Vec::new(), }, From c9a9ca9cb9be6a38ee06bb1cfb240cabda933aa2 Mon Sep 17 00:00:00 2001 From: Tau Date: Wed, 16 Jul 2025 20:54:47 +0300 Subject: [PATCH 16/21] lint: fix clippy::format_push_string --- Cargo.toml | 1 - pad/editor/src/lib.rs | 3 ++- site/src/main.rs | 3 ++- site/src/markdown.rs | 6 ++++-- site/src/other.rs | 3 ++- site/src/primitive.rs | 25 ++++++++++++++----------- src/assembly.rs | 6 +++--- src/format.rs | 14 ++++++++------ src/grid_fmt.rs | 7 +++++-- src/lsp.rs | 41 +++++++++++++++++++++++------------------ 10 files changed, 63 insertions(+), 46 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a6e1cc782..2c4f52287 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,6 @@ print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} inline_always = "allow" # TODO: benchmark inlines -format_push_string = "allow" # 27 missing_panics_doc = "allow" # 37 used_underscore_binding = "allow" # 39 float_cmp = "allow" # 40 diff --git a/pad/editor/src/lib.rs b/pad/editor/src/lib.rs index 491fdf80f..f67a5aefb 100644 --- a/pad/editor/src/lib.rs +++ b/pad/editor/src/lib.rs @@ -3,6 +3,7 @@ pub mod utils; use std::{ cell::Cell, + fmt::Write, iter::{once, repeat_n}, mem::take, path::PathBuf, @@ -2275,7 +2276,7 @@ pub fn Prim( let href = format!("/docs/{}", prim.name()); let mut title = String::new(); if let Some(ascii) = prim.ascii() { - title.push_str(&format!("({ascii})")); + write!(title, "({ascii})").ok(); } if prim.glyph().is_some() && glyph_only { if !title.is_empty() { diff --git a/site/src/main.rs b/site/src/main.rs index 138c92852..20c3a9c8b 100644 --- a/site/src/main.rs +++ b/site/src/main.rs @@ -403,6 +403,7 @@ fn NotFound() -> impl IntoView { #[cfg(test)] fn prim_html(prim: Primitive, glyph_only: bool, hide_docs: bool) -> String { + use std::fmt::Write; use uiua::PrimDoc; let symbol_class = format!("prim-glyph {}", uiua_editor::prim_class(prim)); @@ -415,7 +416,7 @@ fn prim_html(prim: Primitive, glyph_only: bool, hide_docs: bool) -> String { let href = format!("/docs/{}", prim.name()); let mut title = String::new(); if let Some(ascii) = prim.ascii() { - title.push_str(&format!("({ascii})")); + write!(title, "({ascii})").ok(); } if prim.glyph().is_some() && glyph_only { if !title.is_empty() { diff --git a/site/src/markdown.rs b/site/src/markdown.rs index 59ab33a50..c6d490fc9 100644 --- a/site/src/markdown.rs +++ b/site/src/markdown.rs @@ -353,7 +353,7 @@ fn node_html<'a>(node: &'a AstNode<'a>) -> String { line.push('\n'); for formatted in formatted { for fline in formatted.lines() { - line.push_str(&format!("\n# {fline}")); + write!(line, "\n# {fline}").ok(); } } } else { @@ -372,7 +372,9 @@ fn node_html<'a>(node: &'a AstNode<'a>) -> String { { break; } - Err(e) => line.push_str(&format!("# {e}")), + Err(e) => { + write!(line, "# {e}").ok(); + } } } let text = lines.join("\n"); diff --git a/site/src/other.rs b/site/src/other.rs index 51a28efd8..65acfcbf3 100644 --- a/site/src/other.rs +++ b/site/src/other.rs @@ -1,5 +1,6 @@ use leptos::*; use leptos_meta::*; +use std::fmt::Write; use uiua::{ConstClass, Primitive, SysOp, CONSTANTS}; use uiua_editor::{lang, Editor}; @@ -459,7 +460,7 @@ pub fn Combinators() -> impl IntoView { if !line.starts_with('#') { for i in 0..inputs { let a = i * 3 + 1; - ex.push_str(&format!(" {}_{}_{}", a, a + 1, a + 2)); + write!(ex, " {}_{}_{}", a, a+1, a+2).ok(); } ex.push_str(" "); } diff --git a/site/src/primitive.rs b/site/src/primitive.rs index 9965b66ac..49a34c99e 100644 --- a/site/src/primitive.rs +++ b/site/src/primitive.rs @@ -1,5 +1,6 @@ use leptos::*; use leptos_router::*; +use std::fmt::Write; use uiua::{PrimClass, PrimDoc, PrimDocFragment, PrimDocLine, Primitive, SysOp}; use uiua_editor::Editor; @@ -49,11 +50,12 @@ pub fn PrimDocs(prim: Primitive) -> impl IntoView { sig.push_str("Constant"); } else if let Some(margs) = prim.modifier_args() { match margs { - 1 => sig.push_str("Monadic"), - 2 => sig.push_str("Dyadic"), - 3 => sig.push_str("Triadic"), - n => sig.push_str(&format!("{n}-function")), + 1 => write!(sig, "Monadic"), + 2 => write!(sig, "Dyadic"), + 3 => write!(sig, "Triadic"), + n => write!(sig, "{n}-function"), } + .ok(); if let Some(args) = prim.args() { sig.push(' '); sig.push_str(&args.to_string()); @@ -62,16 +64,17 @@ pub fn PrimDocs(prim: Primitive) -> impl IntoView { sig.push_str(" modifier"); } else { match prim.args() { - Some(0) => sig.push_str("Noadic"), - Some(1) => sig.push_str("Monadic"), - Some(2) => sig.push_str("Dyadic"), - Some(3) => sig.push_str("Triadic"), - Some(n) => sig.push_str(&format!("{n}-argument")), - None => sig.push_str("Variadic"), + Some(0) => write!(sig, "Noadic"), + Some(1) => write!(sig, "Monadic"), + Some(2) => write!(sig, "Dyadic"), + Some(3) => write!(sig, "Triadic"), + Some(n) => write!(sig, "{n}-argument"), + None => write!(sig, "Variadic"), } + .ok(); if let Some(outputs) = prim.outputs() { if outputs != 1 { - sig.push_str(&format!(" {outputs}-output")); + write!(sig, " {outputs}-output").ok(); } } else { sig.push_str(" variable-output"); diff --git a/src/assembly.rs b/src/assembly.rs index 084632136..64c69a6c6 100644 --- a/src/assembly.rs +++ b/src/assembly.rs @@ -1,5 +1,5 @@ use std::{ - fmt, + fmt::{self, Write}, hash::{DefaultHasher, Hash, Hasher}, ops::{Index, IndexMut}, path::PathBuf, @@ -263,7 +263,7 @@ impl Assembly { if map.len() == 1 { let key = map.keys().next().unwrap(); let value = map.values().next().unwrap(); - uasm.push_str(&format!("{key} {value}\n")); + writeln!(uasm, "{key} {value}").ok(); continue; } } @@ -293,7 +293,7 @@ impl Assembly { for entry in &self.inputs.files { let key = entry.key(); let value = entry.value(); - uasm.push_str(&format!("{}: {:?}\n", key.display(), value)); + writeln!(uasm, "{}: {:?}", key.display(), value).ok(); } if !self.inputs.strings.is_empty() { diff --git a/src/format.rs b/src/format.rs index e92c4fa5c..267885cf4 100644 --- a/src/format.rs +++ b/src/format.rs @@ -113,6 +113,7 @@ macro_rules! create_config { #[test] fn generate_format_cfg_docs() { + use std::fmt::Write; paste! { let mut s: String = r" # Uiua Formatter Configuration @@ -125,7 +126,8 @@ Example with default values: ```uiua ".into(); $( - s.push_str(&format!("{} ← {}\n", stringify!([<$name:camel>]), default_to_uiua!($default))); + write!(s, "{} ← {}\n", stringify!([<$name:camel>]), default_to_uiua!($default)).ok() + ; )* s.push_str(r"``` The following configuration options are available: @@ -133,11 +135,11 @@ The following configuration options are available: "); $( - s.push_str(&format!("### {}\n", stringify!([<$name:camel>]))); - s.push_str(&format!("Type: {}\n\n", param_type!($ty))); - s.push_str(&format!("Default: `{}`\n\n", default_to_uiua!($default))); - $(s.push_str(&format!("{}\n", $doc.trim()));)* - s.push_str("\n---\n\n"); + writeln!(s, "### {}", stringify!([<$name:camel>])).ok(); + writeln!(s, "Type: {}\n", param_type!($ty)).ok(); + writeln!(s, "Default: `{}`\n", default_to_uiua!($default)).ok(); + $(writeln!(s, "{}", $doc.trim()).ok();)* + writeln!(s, "\n---\n").ok(); )* fs::write("site/text/format_config.md", s).unwrap(); diff --git a/src/grid_fmt.rs b/src/grid_fmt.rs index 537961e30..606727de3 100644 --- a/src/grid_fmt.rs +++ b/src/grid_fmt.rs @@ -3,6 +3,7 @@ use std::{ collections::HashMap, f64::consts::{E, PI, TAU}, + fmt::Write, iter::{once, repeat_n}, mem::take, }; @@ -274,10 +275,12 @@ impl GridFmt for f64 { round_sig_dec(mean, 4).grid_string(false) ); if nan_count > 0 { - s.push_str(&format!( + write!( + s, " ({nan_count} NaN{})", if nan_count > 1 { "s" } else { "" } - )); + ) + .ok(); } s } diff --git a/src/lsp.rs b/src/lsp.rs index 93dffc286..b323f7f04 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -845,7 +845,7 @@ pub use server::run_language_server; #[cfg(feature = "lsp")] mod server { - use std::{char::decode_utf16, env::current_dir, path::Path, sync::Arc}; + use std::{char::decode_utf16, env::current_dir, fmt::Write, path::Path, sync::Arc}; use dashmap::DashMap; use tower_lsp::{ @@ -1127,7 +1127,7 @@ mod server { span.as_str(&doc.asm.inputs, |s| value.push_str(s)); match docs.kind { BindingDocsKind::Function { sig, .. } => { - value.push_str(&format!(" {sig}")); + write!(value, " {sig}").ok(); } _ => {} } @@ -1148,7 +1148,7 @@ mod server { } value.push_str("\n```"); if let Some(escape) = &docs.escape { - value.push_str(&format!("\n`{escape}`")); + write!(value, "\n`{escape}`").ok(); } match docs.kind { BindingDocsKind::Function { @@ -2435,20 +2435,21 @@ mod server { fn doc_frag_markdown(md: &mut String, frag: &PrimDocFragment) { match frag { - PrimDocFragment::Text(text) => md.push_str(text), - PrimDocFragment::Code(text) => md.push_str(&format!("`{text}`")), - PrimDocFragment::Emphasis(text) => md.push_str(&format!("*{text}*")), - PrimDocFragment::Strong(text) => md.push_str(&format!("**{text}**")), - PrimDocFragment::Link { text, url } => md.push_str(&format!("[{text}]({url})")), + PrimDocFragment::Text(text) => write!(md, "{text}"), + PrimDocFragment::Code(text) => write!(md, "`{text}`"), + PrimDocFragment::Emphasis(text) => write!(md, "*{text}*"), + PrimDocFragment::Strong(text) => write!(md, "**{text}**"), + PrimDocFragment::Link { text, url } => write!(md, "[{text}]({url})"), PrimDocFragment::Primitive { prim, named } => { let text = if *named { format!("`{}`", prim.format()) } else { prim.to_string() }; - md.push_str(&format!("[{text}](https://uiua.org/docs/{})", prim.name())) + write!(md, "[{}](https://uiua.org/docs/{})", text, prim.name()) } } + .ok(); } fn full_prim_doc_markdown(prim: Primitive) -> String { @@ -2459,12 +2460,12 @@ mod server { for frag in &doc.short { doc_frag_markdown(&mut value, frag); } - value.push_str("\n\n"); - value.push_str(&format!( - "[Documentation](https://uiua.org/docs/{})", + write!( + value, + "\n\n[Documentation](https://uiua.org/docs/{})\n\n", prim.name() - )); - value.push_str("\n\n"); + ) + .ok(); for line in &doc.lines { match line { PrimDocLine::Text(frags) => { @@ -2474,7 +2475,8 @@ mod server { value.push('\n'); } PrimDocLine::Example(ex) => { - value.push_str(&format!( + write!( + value, "\ ```uiua {} @@ -2482,14 +2484,17 @@ mod server { > ``` ", ex.input() - )); + ) + .ok(); match ex.output_strings() { Ok(lines) => { for line in lines.iter().flat_map(|l| l.lines()) { - value.push_str(&format!("> {line}\n")); + writeln!(value, "> {line}").ok(); } } - Err(err) => value.push_str(&format!("> Error: {err}\n")), + Err(err) => { + writeln!(value, "> Error: {err}").ok(); + } } value.push_str("> ```\n\n"); } From 6d9e8336ec330bb9e97a7d724eb6ee13a9c675e1 Mon Sep 17 00:00:00 2001 From: Tau Date: Thu, 17 Jul 2025 22:16:52 +0300 Subject: [PATCH 17/21] lint: fix clippy::used_underscore_binding --- Cargo.toml | 3 +- src/algorithm/encode.rs | 12 ++--- src/algorithm/reduce.rs | 4 +- src/array.rs | 10 ++-- src/run.rs | 4 +- src/sys/mod.rs | 4 +- src/sys/native.rs | 30 ++++++------ src/value.rs | 106 ++++++++++++++++++++-------------------- 8 files changed, 86 insertions(+), 87 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2c4f52287..62d5834e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,8 +18,7 @@ print_stdout = "warn" non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} inline_always = "allow" # TODO: benchmark inlines -missing_panics_doc = "allow" # 37 -used_underscore_binding = "allow" # 39 +missing_panics_doc = "allow" # TODO float_cmp = "allow" # 40 map_unwrap_or = "allow" # 59 return_self_not_must_use = "allow" # 61 diff --git a/src/algorithm/encode.rs b/src/algorithm/encode.rs index e589cf950..bbac0062e 100644 --- a/src/algorithm/encode.rs +++ b/src/algorithm/encode.rs @@ -71,7 +71,7 @@ impl Value { let json_value: serde_json::Value = json5::from_str(json).map_err(|e| env.error(e))?; Self::from_json_value(json_value, env) } - pub(crate) fn from_json_value(json_value: serde_json::Value, _env: &Uiua) -> UiuaResult { + pub(crate) fn from_json_value(json_value: serde_json::Value, env: &Uiua) -> UiuaResult { Ok(match json_value { serde_json::Value::Null => f64::NAN.into(), serde_json::Value::Bool(b) => b.into(), @@ -90,7 +90,7 @@ impl Value { serde_json::Value::Array(arr) => { let mut rows = Vec::with_capacity(arr.len()); for value in arr { - let mut value = Value::from_json_value(value, _env)?; + let mut value = Value::from_json_value(value, env)?; if value.meta.map_keys.is_some() { value = Boxed(value).into(); } @@ -112,7 +112,7 @@ impl Value { let mut values = Vec::with_capacity(map.len()); for (k, v) in map { keys.push(Boxed(k.into())); - let mut value = Value::from_json_value(v, _env)?; + let mut value = Value::from_json_value(v, env)?; if value.meta.map_keys.is_some() { value = Boxed(value).into(); } @@ -125,7 +125,7 @@ impl Value { } else { Array::from(values.into_iter().map(Boxed).collect::>()).into() }; - values.map(keys.into(), _env)?; + values.map(keys.into(), env)?; values } }) @@ -275,7 +275,7 @@ impl Value { }) } } - pub(crate) fn from_xlsx(_xlsx: &[u8], env: &mut Uiua) -> UiuaResult { + pub(crate) fn from_xlsx(xlsx: &[u8], env: &mut Uiua) -> UiuaResult { #[cfg(not(feature = "calamine"))] return Err(env.error("XLSX decoding is not enabled in this environment")); #[cfg(feature = "calamine")] @@ -283,7 +283,7 @@ impl Value { use calamine::*; let mut workbook: Xlsx<_> = - open_workbook_from_rs(std::io::Cursor::new(_xlsx)).map_err(|e| env.error(e))?; + open_workbook_from_rs(std::io::Cursor::new(xlsx)).map_err(|e| env.error(e))?; let sheet_names = workbook.sheet_names(); let fill = env .value_fill() diff --git a/src/algorithm/reduce.rs b/src/algorithm/reduce.rs index 0fd357c72..62662ed7e 100644 --- a/src/algorithm/reduce.rs +++ b/src/algorithm/reduce.rs @@ -60,7 +60,7 @@ pub(crate) fn reduce_impl(f: SigNode, depth: usize, env: &mut Uiua) -> UiuaResul return generic_reduce(f, Value::Complex(nums), depth, env); } } - (Some((prim, _flipped)), Value::Byte(bytes)) => { + (Some((prim, flipped)), Value::Byte(bytes)) => { let fill = env.scalar_fill::().ok().map(|fv| fv.value); if fill.is_none() && env.value_fill().is_some() { return generic_reduce(f, Value::Byte(bytes), depth, env); @@ -71,7 +71,7 @@ pub(crate) fn reduce_impl(f: SigNode, depth: usize, env: &mut Uiua) -> UiuaResul .into() } #[cfg(feature = "opt")] - Primitive::Sub if _flipped => fast_reduce_different( + Primitive::Sub if flipped => fast_reduce_different( bytes, 0.0, fill, diff --git a/src/array.rs b/src/array.rs index c680857fc..fb0ff7d81 100644 --- a/src/array.rs +++ b/src/array.rs @@ -401,17 +401,17 @@ where #[track_caller] #[inline(always)] -pub(crate) fn validate_shape(_shape: &[usize], _len: usize) { +pub(crate) fn validate_shape(shape: &[usize], len: usize) { #[cfg(debug_assertions)] { - let elems = if _shape.contains(&0) { + let elems = if shape.contains(&0) { 0 } else { - _shape.iter().product() + shape.iter().product() }; assert_eq!( - elems, _len, - "shape {_shape:?} does not match data length {_len}" + elems, len, + "shape {shape:?} does not match data length {len}" ) } } diff --git a/src/run.rs b/src/run.rs index 2b92b4c48..a73e245f7 100644 --- a/src/run.rs +++ b/src/run.rs @@ -1500,7 +1500,7 @@ impl Uiua { } } /// Spawn a thread - pub(crate) fn spawn(&mut self, _pool: bool, f: SigNode) -> UiuaResult { + pub(crate) fn spawn(&mut self, pool: bool, f: SigNode) -> UiuaResult { if !self.rt.backend.allow_thread_spawning() { return Err(self.error("Thread spawning is not allowed in this environment")); } @@ -1555,7 +1555,7 @@ impl Uiua { #[cfg(not(target_arch = "wasm32"))] let recv = { let (send, recv) = crossbeam_channel::unbounded(); - if _pool { + if pool { let max_threads = std::thread::available_parallelism() .map(|p| p.get()) .unwrap_or(1); diff --git a/src/sys/mod.rs b/src/sys/mod.rs index f61ceb7b4..bfa6c9553 100644 --- a/src/sys/mod.rs +++ b/src/sys/mod.rs @@ -1233,11 +1233,11 @@ pub(crate) fn run_sys_op(op: SysOp, env: &mut Uiua) -> UiuaResult { } SysOp::WebcamCapture => { let index = env.pop(1)?.as_nat(env, "Webcam index must be an integer")?; - let _image = (env.rt.backend) + let image = (env.rt.backend) .webcam_capture(index) .map_err(|e| env.error(e))?; #[cfg(feature = "image")] - env.push(crate::media::rgb_image_to_array(_image)); + env.push(crate::media::rgb_image_to_array(image)); #[cfg(not(feature = "image"))] return Err(env.error("Webcam capture is not supported in this environment")); } diff --git a/src/sys/native.rs b/src/sys/native.rs index c584365ee..067ca0637 100644 --- a/src/sys/native.rs +++ b/src/sys/native.rs @@ -158,15 +158,15 @@ enum TslConnection { } impl Read for &TlsSocket { - fn read(&mut self, _buf: &mut [u8]) -> std::io::Result { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { #[cfg(feature = "tls")] { match &mut *self.conn.lock() { TslConnection::Client(conn) => { - rustls::Stream::new(conn, &mut &self.stream).read(_buf) + rustls::Stream::new(conn, &mut &self.stream).read(buf) } TslConnection::Server(conn) => { - rustls::Stream::new(conn, &mut &self.stream).read(_buf) + rustls::Stream::new(conn, &mut &self.stream).read(buf) } } } @@ -176,15 +176,15 @@ impl Read for &TlsSocket { } impl Write for &TlsSocket { - fn write(&mut self, _buf: &[u8]) -> std::io::Result { + fn write(&mut self, buf: &[u8]) -> std::io::Result { #[cfg(feature = "tls")] { match &mut *self.conn.lock() { TslConnection::Client(conn) => { - rustls::Stream::new(conn, &mut &self.stream).write(_buf) + rustls::Stream::new(conn, &mut &self.stream).write(buf) } TslConnection::Server(conn) => { - rustls::Stream::new(conn, &mut &self.stream).write(_buf) + rustls::Stream::new(conn, &mut &self.stream).write(buf) } } } @@ -663,8 +663,8 @@ impl SysBackend for NativeSys { } #[allow(clippy::print_stdout)] #[cfg(all(feature = "terminal_image", feature = "image"))] - fn show_image(&self, image: image::DynamicImage, _label: Option<&str>) -> Result<(), String> { - let (_width, _height) = if let Some((w, h)) = terminal_size() { + fn show_image(&self, image: image::DynamicImage, label: Option<&str>) -> Result<(), String> { + let (width, height) = if let Some((w, h)) = terminal_size() { let (tw, th) = (w as u32, h.saturating_sub(1) as u32); let (iw, ih) = (image.width(), (image.height() / 2).max(1)); let scaled_to_height = (iw * th / ih.max(1), th); @@ -701,15 +701,15 @@ impl SysBackend for NativeSys { return crate::window::Request::Show(crate::media::SmartOutput::Png( crate::media::image_to_bytes(&image, image::ImageFormat::Png) .map_err(|e| e.to_string())?, - _label.map(Into::into), + label.map(Into::into), )) .send(); } viuer::print( &image, &viuer::Config { - width: _width, - height: _height, + width, + height, absolute_offset: false, transparent: true, ..Default::default() @@ -720,12 +720,12 @@ impl SysBackend for NativeSys { } } #[cfg(all(feature = "gif", feature = "invoke"))] - fn show_gif(&self, gif_bytes: Vec, _label: Option<&str>) -> Result<(), String> { + fn show_gif(&self, gif_bytes: Vec, label: Option<&str>) -> Result<(), String> { #[cfg(feature = "window")] if crate::window::use_window() { return crate::window::Request::Show(crate::media::SmartOutput::Gif( gif_bytes, - _label.map(Into::into), + label.map(Into::into), )) .send(); } @@ -774,13 +774,13 @@ impl SysBackend for NativeSys { .map_err(|e| e.to_string()) } #[cfg(feature = "audio")] - fn play_audio(&self, wav_bytes: Vec, _label: Option<&str>) -> Result<(), String> { + fn play_audio(&self, wav_bytes: Vec, label: Option<&str>) -> Result<(), String> { use hodaun::*; #[cfg(feature = "window")] if crate::window::use_window() { return crate::window::Request::Show(crate::media::SmartOutput::Wav( wav_bytes, - _label.map(Into::into), + label.map(Into::into), )) .send(); } diff --git a/src/value.rs b/src/value.rs index 7689628ab..f9773d5fe 100644 --- a/src/value.rs +++ b/src/value.rs @@ -451,27 +451,27 @@ impl Value { pub(crate) fn generic_bin_into( self, other: Self, - n: impl FnOnce(Array, Array) -> Result, - _b: impl FnOnce(Array, Array) -> Result, - _co: impl FnOnce(Array, Array) -> Result, - ch: impl FnOnce(Array, Array) -> Result, - f: impl FnOnce(Array, Array) -> Result, + num: impl FnOnce(Array, Array) -> Result, + byte: impl FnOnce(Array, Array) -> Result, + comp: impl FnOnce(Array, Array) -> Result, + char: impl FnOnce(Array, Array) -> Result, + bx: impl FnOnce(Array, Array) -> Result, err: impl FnOnce(Self, Self) -> E, ) -> Result { match (self, other) { - (Self::Num(a), Self::Num(b)) => n(a, b), - (Self::Byte(a), Self::Byte(b)) => _b(a, b), - (Self::Byte(a), Self::Num(b)) => n(a.convert(), b), - (Self::Num(a), Self::Byte(b)) => n(a, b.convert()), - (Self::Complex(a), Self::Complex(b)) => _co(a, b), - (Self::Complex(a), Self::Num(b)) => _co(a, b.convert()), - (Self::Num(a), Self::Complex(b)) => _co(a.convert(), b), - (Self::Complex(a), Self::Byte(b)) => _co(a, b.convert()), - (Self::Byte(a), Self::Complex(b)) => _co(a.convert(), b), - (Self::Char(a), Self::Char(b)) => ch(a, b), - (Self::Box(a), Self::Box(b)) => f(a, b), - (Self::Box(a), b) => f(a, b.coerce_to_boxes()), - (a, Self::Box(b)) => f(a.coerce_to_boxes(), b), + (Self::Num(a), Self::Num(b)) => num(a, b), + (Self::Byte(a), Self::Byte(b)) => byte(a, b), + (Self::Byte(a), Self::Num(b)) => num(a.convert(), b), + (Self::Num(a), Self::Byte(b)) => num(a, b.convert()), + (Self::Complex(a), Self::Complex(b)) => comp(a, b), + (Self::Complex(a), Self::Num(b)) => comp(a, b.convert()), + (Self::Num(a), Self::Complex(b)) => comp(a.convert(), b), + (Self::Complex(a), Self::Byte(b)) => comp(a, b.convert()), + (Self::Byte(a), Self::Complex(b)) => comp(a.convert(), b), + (Self::Char(a), Self::Char(b)) => char(a, b), + (Self::Box(a), Self::Box(b)) => bx(a, b), + (Self::Box(a), b) => bx(a, b.coerce_to_boxes()), + (a, Self::Box(b)) => bx(a.coerce_to_boxes(), b), (a, b) => Err(err(a, b)), } } @@ -479,27 +479,27 @@ impl Value { pub(crate) fn generic_bin_ref( &self, other: &Self, - n: impl FnOnce(&Array, &Array) -> Result, - _b: impl FnOnce(&Array, &Array) -> Result, - _co: impl FnOnce(&Array, &Array) -> Result, - ch: impl FnOnce(&Array, &Array) -> Result, - f: impl FnOnce(&Array, &Array) -> Result, + num: impl FnOnce(&Array, &Array) -> Result, + byte: impl FnOnce(&Array, &Array) -> Result, + comp: impl FnOnce(&Array, &Array) -> Result, + char: impl FnOnce(&Array, &Array) -> Result, + bx: impl FnOnce(&Array, &Array) -> Result, err: impl FnOnce(&Self, &Self) -> E, ) -> Result { match (self, other) { - (Self::Num(a), Self::Num(b)) => n(a, b), - (Self::Byte(a), Self::Byte(b)) => _b(a, b), - (Self::Byte(a), Self::Num(b)) => n(&a.convert_ref(), b), - (Self::Num(a), Self::Byte(b)) => n(a, &b.convert_ref()), - (Self::Complex(a), Self::Complex(b)) => _co(a, b), - (Self::Complex(a), Self::Num(b)) => _co(a, &b.convert_ref()), - (Self::Num(a), Self::Complex(b)) => _co(&a.convert_ref(), b), - (Self::Complex(a), Self::Byte(b)) => _co(a, &b.convert_ref()), - (Self::Byte(a), Self::Complex(b)) => _co(&a.convert_ref(), b), - (Self::Char(a), Self::Char(b)) => ch(a, b), - (Self::Box(a), Self::Box(b)) => f(a, b), - (Self::Box(a), b) => f(a, &b.coerce_as_boxes()), - (a, Self::Box(b)) => f(&a.coerce_as_boxes(), b), + (Self::Num(a), Self::Num(b)) => num(a, b), + (Self::Byte(a), Self::Byte(b)) => byte(a, b), + (Self::Byte(a), Self::Num(b)) => num(&a.convert_ref(), b), + (Self::Num(a), Self::Byte(b)) => num(a, &b.convert_ref()), + (Self::Complex(a), Self::Complex(b)) => comp(a, b), + (Self::Complex(a), Self::Num(b)) => comp(a, &b.convert_ref()), + (Self::Num(a), Self::Complex(b)) => comp(&a.convert_ref(), b), + (Self::Complex(a), Self::Byte(b)) => comp(a, &b.convert_ref()), + (Self::Byte(a), Self::Complex(b)) => comp(&a.convert_ref(), b), + (Self::Char(a), Self::Char(b)) => char(a, b), + (Self::Box(a), Self::Box(b)) => bx(a, b), + (Self::Box(a), b) => bx(a, &b.coerce_as_boxes()), + (a, Self::Box(b)) => bx(&a.coerce_as_boxes(), b), (a, b) => Err(err(a, b)), } } @@ -507,43 +507,43 @@ impl Value { pub(crate) fn generic_bin_mut( &mut self, other: Self, - n: impl FnOnce(&mut Array, Array) -> Result, - _b: impl FnOnce(&mut Array, Array) -> Result, - _co: impl FnOnce(&mut Array, Array) -> Result, - ch: impl FnOnce(&mut Array, Array) -> Result, - f: impl FnOnce(&mut Array, Array) -> Result, + num: impl FnOnce(&mut Array, Array) -> Result, + byte: impl FnOnce(&mut Array, Array) -> Result, + comp: impl FnOnce(&mut Array, Array) -> Result, + char: impl FnOnce(&mut Array, Array) -> Result, + bx: impl FnOnce(&mut Array, Array) -> Result, err: impl FnOnce(&Self, &Self) -> E, ) -> Result { match (&mut *self, other) { - (Self::Num(a), Self::Num(b)) => n(a, b), - (Self::Byte(a), Self::Byte(b)) => _b(a, b), + (Self::Num(a), Self::Num(b)) => num(a, b), + (Self::Byte(a), Self::Byte(b)) => byte(a, b), (Self::Byte(a), Self::Num(b)) => { let mut a_num = a.convert_ref(); - let res = n(&mut a_num, b); + let res = num(&mut a_num, b); *self = a_num.into(); res } - (Self::Num(a), Self::Byte(b)) => n(a, b.convert_ref()), - (Self::Complex(a), Self::Complex(b)) => _co(a, b), - (Self::Complex(a), Self::Num(b)) => _co(a, b.convert_ref()), + (Self::Num(a), Self::Byte(b)) => num(a, b.convert_ref()), + (Self::Complex(a), Self::Complex(b)) => comp(a, b), + (Self::Complex(a), Self::Num(b)) => comp(a, b.convert_ref()), (Self::Num(a), Self::Complex(b)) => { let mut a_comp = a.convert_ref(); - let res = _co(&mut a_comp, b); + let res = comp(&mut a_comp, b); *self = a_comp.into(); res } - (Self::Complex(a), Self::Byte(b)) => _co(a, b.convert_ref()), + (Self::Complex(a), Self::Byte(b)) => comp(a, b.convert_ref()), (Self::Byte(a), Self::Complex(b)) => { let mut a_comp = a.convert_ref(); - let res = _co(&mut a_comp, b); + let res = comp(&mut a_comp, b); *self = a_comp.into(); res } - (Self::Char(a), Self::Char(b)) => ch(a, b), - (Self::Box(a), b) => f(a, b.coerce_to_boxes()), + (Self::Char(a), Self::Char(b)) => char(a, b), + (Self::Box(a), b) => bx(a, b.coerce_to_boxes()), (a, Self::Box(b)) => { let mut a_box = take(a).coerce_to_boxes(); - let res = f(&mut a_box, b); + let res = bx(&mut a_box, b); *self = a_box.into(); res } From ee6c1629ad2c33726915fde992a9f6a43577a8c5 Mon Sep 17 00:00:00 2001 From: Tau Date: Thu, 17 Jul 2025 22:16:52 +0300 Subject: [PATCH 18/21] chore: update lint counts --- Cargo.toml | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 62d5834e4..f832be05c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,26 +19,26 @@ non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} inline_always = "allow" # TODO: benchmark inlines missing_panics_doc = "allow" # TODO -float_cmp = "allow" # 40 -map_unwrap_or = "allow" # 59 -return_self_not_must_use = "allow" # 61 +ptr_as_ptr = "allow" # 3 +similar_names = "allow" # 26 +float_cmp = "allow" # 42 +map_unwrap_or = "allow" # 56 +return_self_not_must_use = "allow" # 63 needless_pass_by_value = "allow" # 70 -items_after_statements = "allow" # 74 -redundant_closure_for_method_calls = "allow" # 75 -ptr_as_ptr = "allow" # 83 -similar_names = "allow" # 93 +redundant_closure_for_method_calls = "allow" # 76 +items_after_statements = "allow" # 81 enum_glob_use = "allow" # 96 -cast_possible_wrap = "allow" # 105 -too_many_lines = "allow" # 106 -wildcard_imports = "allow" # 134 -cast_precision_loss = "allow" # 172 -match_same_arms = "allow" # 176 -cast_sign_loss = "allow" # 190 -missing_errors_doc = "allow" # 224 -semicolon_if_nothing_returned = "allow" # 263 -must_use_candidate = "allow" # 301 -cast_possible_truncation = "allow" # 349 -cast_lossless = "allow" # 355 +cast_possible_wrap = "allow" # 102 +too_many_lines = "allow" # 105 +wildcard_imports = "allow" # 133 +cast_sign_loss = "allow" # 165 +cast_precision_loss = "allow" # 167 +match_same_arms = "allow" # 173 +missing_errors_doc = "allow" # 232 +semicolon_if_nothing_returned = "allow" # 259 +must_use_candidate = "allow" # 302 +cast_lossless = "allow" # 317 +cast_possible_truncation = "allow" # 340 [workspace.dependencies] base64 = "0.22.0" From 5e134d03d3d4140a2540dfb4c21f42c6d60516ef Mon Sep 17 00:00:00 2001 From: Tau Date: Thu, 7 Aug 2025 04:27:04 +0300 Subject: [PATCH 19/21] lint: fix clippy::ptr_as_ptr --- Cargo.toml | 1 - src/ffi.rs | 18 ++++++++++++------ src/value.rs | 4 ++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f832be05c..b84062218 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ non_std_lazy_statics = "warn" pedantic = {level = "warn", priority = -1} inline_always = "allow" # TODO: benchmark inlines missing_panics_doc = "allow" # TODO -ptr_as_ptr = "allow" # 3 similar_names = "allow" # 26 float_cmp = "allow" # 42 map_unwrap_or = "allow" # 56 diff --git a/src/ffi.rs b/src/ffi.rs index a0b13bffa..3d382b6fc 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -334,7 +334,12 @@ mod enabled { let mut out_values = out_values; out_values.pop().unwrap() } else { - [ret].into_iter().chain(out_values).map(Boxed).collect::>().into() + [ret] + .into_iter() + .chain(out_values) + .map(Boxed) + .collect::>() + .into() } }; @@ -420,7 +425,7 @@ mod enabled { libffi::raw::ffi_call( cif.as_raw_ptr(), Some(*fun.as_safe_fun()), - result.as_mut_ptr() as *mut c_void, + result.as_mut_ptr().cast(), args.as_ptr() as *mut *mut c_void, ); result @@ -467,10 +472,11 @@ mod enabled { FfiType::ULongLong => arr!(c_ulonglong), _ => Ok(if ptr.ty.is_string() { (0..len) - .map(|index| ptr.ty.unrepr(&repr[index * size..(index + 1) * size])) - .collect::, String>>()? - .into_iter() - .map(Boxed).collect() + .map(|index| ptr.ty.unrepr(&repr[index * size..(index + 1) * size])) + .collect::, String>>()? + .into_iter() + .map(Boxed) + .collect() } else { Value::from_row_values_infallible( (0..len) diff --git a/src/value.rs b/src/value.rs index f9773d5fe..89686cb7b 100644 --- a/src/value.rs +++ b/src/value.rs @@ -364,14 +364,14 @@ impl Deref for Value { type Target = ValueRepr; fn deref(&self) -> &Self::Target { // Safety: The layout of `Value` should always match that of `Value` - unsafe { &*(std::ptr::from_ref(self) as *const ValueRepr) } + unsafe { &*std::ptr::from_ref(self).cast() } } } impl DerefMut for Value { fn deref_mut(&mut self) -> &mut Self::Target { // Safety: The layout of `Value` should always match that of `Value` - unsafe { &mut *(std::ptr::from_mut(self) as *mut ValueRepr) } + unsafe { &mut *std::ptr::from_mut(self).cast() } } } From 146b9c13a8192bd906fb79c5eebe36adb6deffcb Mon Sep 17 00:00:00 2001 From: Tau Date: Thu, 7 Aug 2025 04:31:51 +0300 Subject: [PATCH 20/21] lint: fix clippy::map_unwrap_or --- Cargo.toml | 1 - pad/editor/src/utils.rs | 2 +- parser/src/ast.rs | 25 +++++++------------ site/src/blog.rs | 4 +--- site/src/docs.rs | 8 +++---- site/src/markdown.rs | 37 ++++++++++++---------------- site/src/tutorial.rs | 16 ++++++------- src/algorithm/dyadic/mod.rs | 5 +--- src/algorithm/dyadic/search.rs | 11 ++++----- src/algorithm/dyadic/structure.rs | 9 ++----- src/algorithm/encode.rs | 4 +--- src/algorithm/groups.rs | 3 +-- src/algorithm/monadic/mod.rs | 6 ++--- src/algorithm/path.rs | 5 ++-- src/algorithm/reduce.rs | 27 +++++++++++---------- src/check.rs | 2 +- src/compile/binding.rs | 14 ++++++----- src/compile/data.rs | 2 +- src/compile/mod.rs | 11 ++++----- src/compile/modifier.rs | 6 +---- src/format.rs | 16 +++++-------- src/lsp.rs | 6 ++--- src/main.rs | 2 +- src/run.rs | 4 +--- src/run_prim.rs | 2 +- src/sys/native.rs | 3 +-- src/value.rs | 40 +++++++++++++++---------------- 27 files changed, 114 insertions(+), 157 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b84062218..b82ac5e05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,6 @@ inline_always = "allow" # TODO: benchmark inlines missing_panics_doc = "allow" # TODO similar_names = "allow" # 26 float_cmp = "allow" # 42 -map_unwrap_or = "allow" # 56 return_self_not_must_use = "allow" # 63 needless_pass_by_value = "allow" # 70 redundant_closure_for_method_calls = "allow" # 76 diff --git a/pad/editor/src/utils.rs b/pad/editor/src/utils.rs index ea613815f..2f76f5868 100644 --- a/pad/editor/src/utils.rs +++ b/pad/editor/src/utils.rs @@ -126,7 +126,7 @@ impl State { return; }; let code = get_code(&self.code_id); - let before = self.past.last().map(|r| r.after).unwrap_or(cursor); + let before = self.past.last().map_or(cursor, |r| r.after); let new_curr = Record { code: code.clone(), before, diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 9c508c1e2..779cddc74 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -165,12 +165,8 @@ pub struct ImportLine { impl Import { /// The full span of the import pub fn span(&self) -> CodeSpan { - let first = (self.name.as_ref()) - .map(|n| n.span.clone()) - .unwrap_or_else(|| self.path.span.clone()); - let last = (self.items().last()) - .map(|i| i.span.clone()) - .unwrap_or_else(|| self.path.span.clone()); + let first = (self.name.as_ref()).map_or_else(|| self.path.span.clone(), |n| n.span.clone()); + let last = (self.items().last()).map_or_else(|| self.path.span.clone(), |i| i.span.clone()); first.merge(last) } /// The imported items @@ -249,16 +245,14 @@ pub struct FieldInit { impl DataDef { /// Get the span of this data definition pub fn span(&self) -> CodeSpan { - let end = self - .fields - .as_ref() - .map(|fields| fields.span()) - .unwrap_or_else(|| { + let end = self.fields.as_ref().map_or_else( + || { self.name .as_ref() - .map(|name| name.span.clone()) - .unwrap_or_else(|| self.init_span.clone()) - }); + .map_or_else(|| self.init_span.clone(), |name| name.span.clone()) + }, + |fields| fields.span(), + ); let mut span = (self.init_span.clone()).merge(end); if let Some(words) = &self.func { if let Some(word) = words.last() { @@ -295,8 +289,7 @@ impl DataField { self.init.as_ref().map(|d| { d.words .last() - .map(|w| w.span.clone()) - .unwrap_or_else(|| d.arrow_span.clone()) + .map_or_else(|| d.arrow_span.clone(), |w| w.span.clone()) }) }) else { return self.name.span.clone(); diff --git a/site/src/blog.rs b/site/src/blog.rs index 04bc8453b..3bfe8a632 100644 --- a/site/src/blog.rs +++ b/site/src/blog.rs @@ -17,9 +17,7 @@ struct BlogParam(String); impl IntoParam for BlogParam { fn into_param(value: Option<&str>, _: &str) -> Result { let s = value.unwrap_or_default(); - let name = urlencoding::decode(s) - .map(Into::into) - .unwrap_or_else(|_| s.into()); + let name = urlencoding::decode(s).map_or_else(|_| s.into(), Into::into); Ok(BlogParam(name)) } } diff --git a/site/src/docs.rs b/site/src/docs.rs index e873f3278..be281e237 100644 --- a/site/src/docs.rs +++ b/site/src/docs.rs @@ -198,10 +198,10 @@ fn DocsHome(#[prop(optional)] search: String) -> impl IntoView { } }; let update_title = move || { - current_prim - .get() - .map(|p| format!("{} - {} Docs", lang(), p.name())) - .unwrap_or_else(|| format!("{} Docs", lang())) + current_prim.get().map_or_else( + || format!("{} Docs", lang()), + |p| format!("{} - {} Docs", lang(), p.name()), + ) }; set_timeout( diff --git a/site/src/markdown.rs b/site/src/markdown.rs index c6d490fc9..bc2bdebbc 100644 --- a/site/src/markdown.rs +++ b/site/src/markdown.rs @@ -153,16 +153,13 @@ fn node_view<'a>(node: &'a AstNode<'a>) -> View { } NodeValue::Link(link) => { let text = leaf_text(node).unwrap_or_default(); - let name = text - .rsplit_once(' ') - .map(|(a, b)| { - if a.chars().count() > b.chars().count() { - a - } else { - b - } - }) - .unwrap_or(&text); + let name = text.rsplit_once(' ').map_or(text.as_str(), |(a, b)| { + if a.chars().count() > b.chars().count() { + a + } else { + b + } + }); if let Some(prim) = Primitive::from_name(name).or_else(|| Primitive::from_name(&text)) { view!().into_view() } else { @@ -278,16 +275,13 @@ fn node_html<'a>(node: &'a AstNode<'a>) -> String { } NodeValue::Link(link) => { let text = leaf_text(node).unwrap_or_default(); - let name = text - .rsplit_once(' ') - .map(|(a, b)| { - if a.chars().count() > b.chars().count() { - a - } else { - b - } - }) - .unwrap_or(&text); + let name = text.rsplit_once(' ').map_or(text.as_str(), |(a, b)| { + if a.chars().count() > b.chars().count() { + a + } else { + b + } + }); if let Some(prim) = Primitive::from_name(name).or_else(|| Primitive::from_name(&text)) { let symbol_class = format!("prim-glyph {}", prim_class(prim)); let symbol = prim.to_string(); @@ -332,8 +326,7 @@ fn node_html<'a>(node: &'a AstNode<'a>) -> String { .map(|s| { s.chars() .position(|c| c == '#') - .map(|i| i + 1) - .unwrap_or_else(|| s.chars().count() + 2) + .map_or_else(|| s.chars().count() + 2, |i| i + 1) }) .max() .unwrap_or(0); diff --git a/site/src/tutorial.rs b/site/src/tutorial.rs index 62f2f68e0..0cf923e46 100644 --- a/site/src/tutorial.rs +++ b/site/src/tutorial.rs @@ -153,19 +153,19 @@ impl IntoParam for TutorialPage { fn TutorialNav(page: TutorialPage) -> impl IntoView { let next = move || { page.next() - .map(|p| { - view!( ) - .into_view() + .map_or_else( + || view!(
).into_view(), + |p| { + view!(
"Next: "{p.title()}" 〉"
).into_view() }) - .unwrap_or_else(|| view!(
).into_view()) }; let previous = move || { page.previous() - .map(|p| { - view!(
"〈 Previous: "{p.title()}
) - .into_view() + .map_or_else( + || view!(
).into_view(), + |p| { + view!(
"〈 Previous: "{p.title()}
).into_view() }) - .unwrap_or_else(|| view!(
).into_view()) }; view! { diff --git a/src/algorithm/dyadic/mod.rs b/src/algorithm/dyadic/mod.rs index 570052fc1..6736b4ee3 100644 --- a/src/algorithm/dyadic/mod.rs +++ b/src/algorithm/dyadic/mod.rs @@ -1926,10 +1926,7 @@ impl Array { let slice = data.make_mut(); let mut bases = bases.to_vec(); let count = row_len.saturating_sub(bases.len()); - bases.extend(repeat_n( - fill.as_ref().map(|fv| fv.value).unwrap_or(1.0), - count, - )); + bases.extend(repeat_n(fill.as_ref().map_or(1.0, |fv| fv.value), count)); if fill.is_some_and(|fv| fv.is_left()) { bases.rotate_right(count); } diff --git a/src/algorithm/dyadic/search.rs b/src/algorithm/dyadic/search.rs index 28ea5019f..ad2395973 100644 --- a/src/algorithm/dyadic/search.rs +++ b/src/algorithm/dyadic/search.rs @@ -182,8 +182,7 @@ impl Array { for elem in needle.row_slices() { let index = (haystack.row_slices()) .position(|row| ArrayCmpSlice(row) == ArrayCmpSlice(elem)) - .map(|i| i as f64) - .unwrap_or(default); + .map_or(default, |i| i as f64); result_data.push(index); } } else { @@ -254,8 +253,7 @@ impl Array { r.len() == needle.data.len() && r.iter().zip(&needle.data).all(|(a, b)| a.array_eq(b)) }) - .map(|i| i as f64) - .unwrap_or(default)) + .map_or(default, |i| i as f64)) .into() } } else { @@ -290,7 +288,7 @@ impl Array { let mut cache = HashMap::with_capacity(needle.row_count()); 'needle: for elem in needle.row_slices() { let elem_key = ArrayCmpSlice(elem); - let start_index = cache.get(&elem_key).map(|&i| i + 1).unwrap_or(0); + let start_index = cache.get(&elem_key).map_or(0, |&i| i + 1); for i in start_index..haystack.row_count() { let of_key = ArrayCmpSlice(haystack.row_slice(i)); if of_key == elem_key { @@ -365,8 +363,7 @@ impl Array { r.len() == needle.data.len() && r.iter().zip(&needle.data).all(|(a, b)| a.array_eq(b)) }) - .map(|i| i as f64) - .unwrap_or(default)) + .map_or(default, |i| i as f64)) .into() } else { let mut rows = Vec::with_capacity(haystack.row_count()); diff --git a/src/algorithm/dyadic/structure.rs b/src/algorithm/dyadic/structure.rs index 97b3633fc..13408cfd2 100644 --- a/src/algorithm/dyadic/structure.rs +++ b/src/algorithm/dyadic/structure.rs @@ -894,8 +894,7 @@ impl Array { fn anti_drop(mut self, mut index: &[isize], env: &Uiua) -> UiuaResult { let fill = env .array_fill::() - .map(|fv| fv.value) - .unwrap_or_else(|_| T::proxy().into()); + .map_or_else(|_| T::proxy().into(), |fv| fv.value); if self.shape.len() < index.len() { return Err(env.error(format!( "Index array specifies {} axes, \ @@ -1526,11 +1525,7 @@ impl Array { .iter() .map(|&i| normalize_index(i, indices.len())) .collect(); - let row_count = normalized_indices - .iter() - .max() - .map(|&max| max + 1) - .unwrap_or(0); + let row_count = normalized_indices.iter().max().map_or(0, |&max| max + 1); // Check indices totality let indices_are_total = indices_are_total(indices, row_count); // Get fill if not total diff --git a/src/algorithm/encode.rs b/src/algorithm/encode.rs index bbac0062e..869a96f2f 100644 --- a/src/algorithm/encode.rs +++ b/src/algorithm/encode.rs @@ -27,9 +27,7 @@ impl Value { } else if n.fract() == 0.0 && n.abs() < i64::MAX as f64 { serde_json::Value::Number((n as i64).into()) } else { - serde_json::Number::from_f64(n) - .map(Into::into) - .unwrap_or(serde_json::Value::Null) + serde_json::Number::from_f64(n).map_or(serde_json::Value::Null, Into::into) } } Value::Byte(bytes) if bytes.rank() == 0 => { diff --git a/src/algorithm/groups.rs b/src/algorithm/groups.rs index 7fd5a65c5..0fb5506ea 100644 --- a/src/algorithm/groups.rs +++ b/src/algorithm/groups.rs @@ -123,8 +123,7 @@ where let prev_end = haystack[curr..] .windows(delim_slice.len()) .position(|win| win.iter().zip(delim_slice).all(|(a, b)| a.array_eq(b))) - .map(|i| curr + i) - .unwrap_or(haystack.len()); + .map_or(haystack.len(), |i| curr + i); let next_start = prev_end + delim_slice.len(); if curr == prev_end && !keep_empty { curr = next_start; diff --git a/src/algorithm/monadic/mod.rs b/src/algorithm/monadic/mod.rs index a6e8f6678..b7f3fcc1e 100644 --- a/src/algorithm/monadic/mod.rs +++ b/src/algorithm/monadic/mod.rs @@ -304,9 +304,7 @@ impl Value { let skip = if max_dec == 0 { 0 } else { - dot_pos - .map(|i| max_dec - (n.len() - i - 1)) - .unwrap_or(max_dec + 1) + dot_pos.map_or(max_dec + 1, |i| max_dec - (n.len() - i - 1)) }; for (s, c) in s.iter_mut().rev().skip(skip).zip(n.chars().rev()) { *s = c; @@ -1900,7 +1898,7 @@ impl Value { .iter() .zip(indices.iter().skip(1)) .all(|(&a, &b)| a <= b); - let mut size = indices.iter().max().map(|&i| i + 1).unwrap_or(0); + let mut size = indices.iter().max().map_or(0, |&i| i + 1); if let Some(&min) = min_size.first() { size = size.max(min); } diff --git a/src/algorithm/path.rs b/src/algorithm/path.rs index 546947a21..264490126 100644 --- a/src/algorithm/path.rs +++ b/src/algorithm/path.rs @@ -86,8 +86,7 @@ fn path_impl( let nei_sig = neighbors.sig; let heu_sig = heuristic .as_ref() - .map(|h| h.sig) - .unwrap_or_else(|| Signature::new(0, 1)); + .map_or_else(|| Signature::new(0, 1), |h| h.sig); let isg_sig = is_goal.sig; for (name, sig, req_out) in &[ ("neighbors", nei_sig, [1, 2].as_slice()), @@ -345,7 +344,7 @@ fn path_impl( let mut new_paths = Vec::new(); currs.retain_mut(|path| { let parents = came_from.get(path.last().unwrap()); - match parents.map(|p| p.len()).unwrap_or(0) { + match parents.map_or(0, |p| p.len()) { 0 => { these_paths.push(take(path)); false diff --git a/src/algorithm/reduce.rs b/src/algorithm/reduce.rs index 62662ed7e..0e4e6121c 100644 --- a/src/algorithm/reduce.rs +++ b/src/algorithm/reduce.rs @@ -113,16 +113,14 @@ pub(crate) fn reduce_impl(f: SigNode, depth: usize, env: &mut Uiua) -> UiuaResul if bytes.rank() == 1 { if bytes.meta.is_sorted_up() { env.push( - (bytes.data.first().copied().map(f64::from)) - .unwrap_or(f64::INFINITY) + (bytes.data.first().copied().map_or(f64::INFINITY, f64::from)) .min(fill.unwrap_or(f64::INFINITY)), ); return Ok(()); } if bytes.meta.is_sorted_down() { env.push( - (bytes.data.last().copied().map(f64::from)) - .unwrap_or(f64::INFINITY) + (bytes.data.last().copied().map_or(f64::INFINITY, f64::from)) .min(fill.unwrap_or(f64::INFINITY)), ); return Ok(()); @@ -147,17 +145,23 @@ pub(crate) fn reduce_impl(f: SigNode, depth: usize, env: &mut Uiua) -> UiuaResul if bytes.rank() == 1 { if bytes.meta.is_sorted_up() { env.push( - (bytes.data.last().copied().map(f64::from)) - .unwrap_or(f64::NEG_INFINITY) - .max(fill.unwrap_or(f64::NEG_INFINITY)), + (bytes + .data + .last() + .copied() + .map_or(f64::NEG_INFINITY, f64::from)) + .max(fill.unwrap_or(f64::NEG_INFINITY)), ); return Ok(()); } if bytes.meta.is_sorted_down() { env.push( - (bytes.data.first().copied().map(f64::from)) - .unwrap_or(f64::NEG_INFINITY) - .max(fill.unwrap_or(f64::NEG_INFINITY)), + (bytes + .data + .first() + .copied() + .map_or(f64::NEG_INFINITY, f64::from)) + .max(fill.unwrap_or(f64::NEG_INFINITY)), ); return Ok(()); } @@ -879,8 +883,7 @@ fn generic_scan(f: SigNode, xs: Value, env: &mut Uiua) -> UiuaResult { if xs.row_count() == 0 { env.push( env.value_fill() - .map(|fv| fv.value.clone()) - .unwrap_or_else(|| (xs.first_dim_zero())), + .map_or_else(|| (xs.first_dim_zero()), |fv| fv.value.clone()), ); return Ok(()); } diff --git a/src/check.rs b/src/check.rs index e1140ea13..0f9b955ef 100644 --- a/src/check.rs +++ b/src/check.rs @@ -494,7 +494,7 @@ impl VirtualEnv { } BothImpl(sub) | UnBothImpl(sub) => { let [f] = get_args(args)?; - let reused = sub.side.map(|side| side.n.unwrap_or(1)).unwrap_or(0); + let reused = sub.side.map_or(0, |side| side.n.unwrap_or(1)); let n = sub.num.unwrap_or(2) as usize; let unique = f.args().saturating_sub(reused) * n; let sig = Signature::new(unique + reused, n * f.outputs()) diff --git a/src/compile/binding.rs b/src/compile/binding.rs index 1a2a63c5b..e9e050887 100644 --- a/src/compile/binding.rs +++ b/src/compile/binding.rs @@ -294,12 +294,14 @@ impl Compiler { }; let words_span = (binding.words.first()) .zip(binding.words.last()) - .map(|(f, l)| f.span.clone().merge(l.span.clone())) - .unwrap_or_else(|| { - let mut span = binding.arrow_span; - span.start = span.end; - span - }); + .map_or_else( + || { + let mut span = binding.arrow_span; + span.start = span.end; + span + }, + |(f, l)| f.span.clone().merge(l.span.clone()), + ); // Compile the body let in_function = self diff --git a/src/compile/data.rs b/src/compile/data.rs index 5ed28fb75..c3311d48c 100644 --- a/src/compile/data.rs +++ b/src/compile/data.rs @@ -365,7 +365,7 @@ impl Compiler { // Make constructor let constructor_args: usize = fields .iter() - .map(|f| f.init.as_ref().map(|sn| sn.sig.args()).unwrap_or(1)) + .map(|f| f.init.as_ref().map_or(1, |sn| sn.sig.args())) .sum(); let mut node = if has_fields { let mut field_nodes = EcoVec::with_capacity(fields.len()); diff --git a/src/compile/mod.rs b/src/compile/mod.rs index 2d362a0d4..da14a3639 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -2650,8 +2650,7 @@ impl Compiler { let take = self .scopes() .position(|sc| matches!(sc.kind, ScopeKind::File(_))) - .map(|i| i + 1) - .unwrap_or(usize::MAX); + .map_or(usize::MAX, |i| i + 1); self.scopes() .take(take) .any(|sc| sc.experimental || sc.experimental_error) @@ -3025,10 +3024,10 @@ fn line_sig(line: &[Sp]) -> Option> { while rest.last().is_some_and(|w| matches!(w.value, Word::Spaces)) { rest = &rest[..rest.len() - 1]; } - let span = (rest.first()) - .zip(rest.last()) - .map(|(f, l)| f.span.clone().merge(l.span.clone())) - .unwrap_or_else(|| last.span.clone()); + let span = (rest.first()).zip(rest.last()).map_or_else( + || last.span.clone(), + |(f, l)| f.span.clone().merge(l.span.clone()), + ); span.sp(sig) }), _ => None, diff --git a/src/compile/modifier.rs b/src/compile/modifier.rs index 3934a1d94..38c921c9a 100644 --- a/src/compile/modifier.rs +++ b/src/compile/modifier.rs @@ -1390,11 +1390,7 @@ impl Compiler { Node::Mod(Fold, eco_vec![sn], span) } prim @ (Spawn | Pool) => { - let recurses_before = self - .current_bindings - .last() - .map(|curr| curr.recurses) - .unwrap_or(0); + let recurses_before = self.current_bindings.last().map_or(0, |curr| curr.recurses); let (sn, span) = self.monadic_modifier_op(modified)?; if let Some(curr) = self.current_bindings.last() { if curr.recurses > recurses_before { diff --git a/src/format.rs b/src/format.rs index 267885cf4..6d8755b35 100644 --- a/src/format.rs +++ b/src/format.rs @@ -839,8 +839,10 @@ impl Formatter<'_> { .iter() .find_map(|l| l.first()) .zip(lines.iter().rev().find_map(|l| l.last())) - .map(|(s, e)| s.span.clone().merge(e.span.clone())) - .unwrap_or_else(|| span.clone()); + .map_or_else( + || span.clone(), + |(s, e)| s.span.clone().merge(e.span.clone()), + ); lines.push(Vec::new()); self.format_words( &[span.sp(Word::Func(Func { @@ -956,20 +958,14 @@ impl Formatter<'_> { } fn format_ref(&mut self, r: &Ref) { self.pre_space( - (r.path.first()) - .map(|comp| comp.module.value.as_str()) - .unwrap_or(r.name.value.as_str()), + (r.path.first()).map_or(r.name.value.as_str(), |comp| comp.module.value.as_str()), ); self.format_ref_path(&r.path, false); self.push(&r.name.span, &r.name.value); } fn format_ref_path(&mut self, comps: &[RefComponent], incomplete: bool) { if incomplete { - self.pre_space( - (comps.first()) - .map(|comp| comp.module.value.as_str()) - .unwrap_or(""), - ); + self.pre_space((comps.first()).map_or("", |comp| comp.module.value.as_str())); } for comp in comps { self.push(&comp.module.span, &comp.module.value); diff --git a/src/lsp.rs b/src/lsp.rs index b323f7f04..0d6f8f21b 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -879,8 +879,7 @@ mod server { let path = path .to_string_lossy() .strip_prefix("\\\\?\\") - .map(PathBuf::from) - .unwrap_or_else(|| path.to_path_buf()); + .map_or_else(|| path.to_path_buf(), PathBuf::from); let path = current_dir() .ok() .and_then(|curr| pathdiff::diff_paths(&path, curr)) @@ -1385,8 +1384,7 @@ mod server { range: uiua_span_to_lsp(&sp.span, &doc.asm.inputs), new_text: prim .glyph() - .map(|c| c.to_string()) - .unwrap_or_else(|| prim.name().to_string()), + .map_or_else(|| prim.name().to_string(), |c| c.to_string()), })), insert_text_mode: if prim.glyph().is_none() { // Insert a space before the completion if the token is not a glyph diff --git a/src/main.rs b/src/main.rs index 1710e092b..e1b4960cb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1374,7 +1374,7 @@ fn check(path: Option) -> UiuaResult { let paths = uiua_files(path.as_deref(), None)?; let path_count = paths.len(); let mut successes = 0; - let width = terminal_size().map(|(w, _)| w.0 as usize).unwrap_or(60); + let width = terminal_size().map_or(60, |(w, _)| w.0 as usize); for (i, path) in paths.into_iter().enumerate() { let message_length = format!("Checking {} ({}/{})", path.display(), i + 1, path_count) .chars() diff --git a/src/run.rs b/src/run.rs index a73e245f7..2f8243168 100644 --- a/src/run.rs +++ b/src/run.rs @@ -974,9 +974,7 @@ impl Uiua { } pub(crate) fn span_index(&self) -> usize { self.rt.call_stack.last().map_or(0, |frame| { - (frame.spans.last()) - .map(|(i, _)| *i) - .unwrap_or(frame.call_span) + (frame.spans.last()).map_or(frame.call_span, |(i, _)| *i) }) } /// Get the span of the current function call diff --git a/src/run_prim.rs b/src/run_prim.rs index f78a37c95..f878fed1f 100644 --- a/src/run_prim.rs +++ b/src/run_prim.rs @@ -1359,7 +1359,7 @@ impl ImplPrimitive { .map(|v| &v.shape) .max_by_key(|sh| sh.len()) .cloned(); - let max_rank = max_shape.as_ref().map(|sh| sh.len()).unwrap_or(0); + let max_rank = max_shape.as_ref().map_or(0, |sh| sh.len()); for mut val in vals { val.deshape_sub(n + 1, 0, val.rank() == max_rank, env)?; env.push(val); diff --git a/src/sys/native.rs b/src/sys/native.rs index 067ca0637..c8a922f05 100644 --- a/src/sys/native.rs +++ b/src/sys/native.rs @@ -804,8 +804,7 @@ impl SysBackend for NativeSys { .and_then(|device| { hodaun::cpal::traits::DeviceTrait::default_output_config(&device).ok() }) - .map(|config| config.sample_rate().0) - .unwrap_or(44100) + .map_or(44100, |config| config.sample_rate().0) } #[cfg(feature = "audio")] fn stream_audio(&self, f: crate::AudioStreamFn) -> Result<(), String> { diff --git a/src/value.rs b/src/value.rs index 89686cb7b..0ac5ad634 100644 --- a/src/value.rs +++ b/src/value.rs @@ -228,20 +228,25 @@ impl Value { } pub(crate) fn proxy_scalar(&self, env: &Uiua) -> Self { match self { - Self::Num(_) => (env.scalar_fill().map(|fv| fv.value)) - .unwrap_or_else(|_| f64::proxy()) + Self::Num(_) => env + .scalar_fill() + .map_or_else(|_| f64::proxy(), |fv| fv.value) .into(), - Self::Byte(_) => (env.scalar_fill().map(|fv| fv.value)) - .unwrap_or_else(|_| u8::proxy()) + Self::Byte(_) => env + .scalar_fill() + .map_or_else(|_| u8::proxy(), |fv| fv.value) .into(), - Self::Complex(_) => (env.scalar_fill().map(|fv| fv.value)) - .unwrap_or_else(|_| Complex::proxy()) + Self::Complex(_) => env + .scalar_fill() + .map_or_else(|_| Complex::proxy(), |fv| fv.value) .into(), - Self::Char(_) => (env.scalar_fill().map(|fv| fv.value)) - .unwrap_or_else(|_| char::proxy()) + Self::Char(_) => env + .scalar_fill() + .map_or_else(|_| char::proxy(), |fv| fv.value) .into(), - Self::Box(_) => (env.scalar_fill().map(|fv| fv.value)) - .unwrap_or_else(|_| Boxed::proxy()) + Self::Box(_) => env + .scalar_fill() + .map_or_else(|_| Boxed::proxy(), |fv| fv.value) .into(), } } @@ -256,8 +261,7 @@ impl Value { shape, CowSlice::from_elem( env.scalar_fill() - .map(|fv| fv.value) - .unwrap_or_else(|_| f64::proxy()), + .map_or_else(|_| f64::proxy(), |fv| fv.value), elem_count, ), ) @@ -266,8 +270,7 @@ impl Value { shape, CowSlice::from_elem( env.scalar_fill() - .map(|fv| fv.value) - .unwrap_or_else(|_| u8::proxy()), + .map_or_else(|_| u8::proxy(), |fv| fv.value), elem_count, ), ) @@ -276,8 +279,7 @@ impl Value { shape, CowSlice::from_elem( env.scalar_fill() - .map(|fv| fv.value) - .unwrap_or_else(|_| Complex::proxy()), + .map_or_else(|_| Complex::proxy(), |fv| fv.value), elem_count, ), ) @@ -286,8 +288,7 @@ impl Value { shape, CowSlice::from_elem( env.scalar_fill() - .map(|fv| fv.value) - .unwrap_or_else(|_| char::proxy()), + .map_or_else(|_| char::proxy(), |fv| fv.value), elem_count, ), ) @@ -296,8 +297,7 @@ impl Value { shape, CowSlice::from_elem( env.scalar_fill() - .map(|fv| fv.value) - .unwrap_or_else(|_| Boxed::proxy()), + .map_or_else(|_| Boxed::proxy(), |fv| fv.value), elem_count, ), ) From 36ad8cb98f79f2deab12a00b348e42fbbd04950d Mon Sep 17 00:00:00 2001 From: Tau Date: Thu, 7 Aug 2025 04:55:37 +0300 Subject: [PATCH 21/21] lint: fix clippy::return_self_not_must_use --- Cargo.toml | 1 - parser/src/ast.rs | 2 ++ parser/src/complex.rs | 19 +++++++++++++++++++ parser/src/error.rs | 1 + parser/src/lex.rs | 5 +++++ parser/src/signature.rs | 5 +++++ src/algorithm/dyadic/combine.rs | 4 ++++ src/algorithm/monadic/mod.rs | 2 ++ src/array.rs | 3 +++ src/compile/mod.rs | 1 + src/format.rs | 1 + src/run.rs | 7 +++++++ src/shape.rs | 3 +++ src/tree.rs | 4 ++++ src/value.rs | 6 ++++++ 15 files changed, 63 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b82ac5e05..63b15be1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,6 @@ inline_always = "allow" # TODO: benchmark inlines missing_panics_doc = "allow" # TODO similar_names = "allow" # 26 float_cmp = "allow" # 42 -return_self_not_must_use = "allow" # 63 needless_pass_by_value = "allow" # 70 redundant_closure_for_method_calls = "allow" # 76 items_after_statements = "allow" # 81 diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 779cddc74..fe7b1dcf4 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -857,6 +857,7 @@ impl From> for NumWord { impl NumWord { /// Map the number + #[must_use] pub fn map(self, real: impl FnOnce(f64) -> R, complex: impl FnOnce(Complex) -> C) -> Self where C: Into, @@ -869,6 +870,7 @@ impl NumWord { } } /// Map the number with another + #[must_use] pub fn map_with( self, other: Self, diff --git a/parser/src/complex.rs b/parser/src/complex.rs index 781df9725..0ba60e33d 100644 --- a/parser/src/complex.rs +++ b/parser/src/complex.rs @@ -48,6 +48,7 @@ impl Complex { Self { re, im } } /// Get the minimum of the real and imaginary parts of two complex numbers, ignoring NaN + #[must_use] pub fn min(self, rhs: impl Into) -> Self { let rhs = rhs.into(); Self { @@ -56,6 +57,7 @@ impl Complex { } } /// Get the maximum of the real and imaginary parts of two complex numbers, ignoring NaN + #[must_use] pub fn max(self, rhs: impl Into) -> Self { let rhs = rhs.into(); Self { @@ -64,6 +66,7 @@ impl Complex { } } /// Get the floor of the real and imaginary parts of a complex number + #[must_use] pub fn floor(self) -> Self { Self { re: self.re.floor(), @@ -71,6 +74,7 @@ impl Complex { } } /// Get the ceiling of the real and imaginary parts of a complex number + #[must_use] pub fn ceil(self) -> Self { Self { re: self.re.ceil(), @@ -78,6 +82,7 @@ impl Complex { } } /// Round the real and imaginary parts of a complex number + #[must_use] pub fn round(self) -> Self { Self { re: self.re.round(), @@ -90,12 +95,14 @@ impl Complex { (self.re * self.re + self.im * self.im).sqrt() } /// Get the arctangent of a complex number + #[must_use] pub fn atan2(self, x: impl Into) -> Complex { let y = self; let x = x.into(); -Complex::I * ((x + Complex::I * y) / (y * y + x * x).sqrt()).ln() } /// Normalize a complex number + #[must_use] pub fn normalize(self) -> Self { let len = self.abs(); if len == 0.0 { @@ -117,6 +124,7 @@ impl Complex { r * Self::new(theta.cos(), theta.sin()) } /// Raise a complex number to a complex power + #[must_use] pub fn powc(self, power: impl Into) -> Self { let power = power.into(); if power.im == 0.0 { @@ -126,6 +134,7 @@ impl Complex { ((r.ln() + Self::I * theta) * power).exp() } /// Raise a complex number to a real power + #[must_use] pub fn powf(self, power: f64) -> Self { if power == 0.0 { return Self::ONE; @@ -137,20 +146,24 @@ impl Complex { Self::from_polar(r.powf(power), theta * power) } /// Calculate the exponential of a complex number + #[must_use] pub fn exp(self) -> Self { Self::from_polar(E.powf(self.re), self.im) } /// Calculate the natural logarithm of a complex number + #[must_use] pub fn ln(self) -> Self { let (r, theta) = self.to_polar(); Self::new(r.ln(), theta) } /// Calculate the logarithm of a complex number + #[must_use] pub fn log(self, base: impl Into) -> Self { let base = base.into(); Self::new(self.abs().ln(), self.arg()) / (Self::new(base.abs().ln(), base.arg())) } /// Calculate the square root of a complex number + #[must_use] pub fn sqrt(self) -> Self { if self.im == 0.0 { return if self.re >= 0.0 { @@ -163,6 +176,7 @@ impl Complex { Self::from_polar(r.sqrt(), theta / 2.0) } /// Calculate the sine of a complex number + #[must_use] pub fn sin(self) -> Self { Self::new( self.re.sin() * self.im.cosh(), @@ -170,6 +184,7 @@ impl Complex { ) } /// Calculate the cosine of a complex number + #[must_use] pub fn cos(self) -> Self { Self::new( self.re.cos() * self.im.cosh(), @@ -177,10 +192,12 @@ impl Complex { ) } /// Calculate the arc sine of a complex number + #[must_use] pub fn asin(self) -> Self { -Self::I * ((Self::ONE - self * self).sqrt() + Self::I * self).ln() } /// Calculate the arc cosine of a complex number + #[must_use] pub fn acos(self) -> Self { -Self::I * (Self::I * (Self::ONE - self * self).sqrt() + self).ln() } @@ -197,6 +214,7 @@ impl Complex { } } /// Multiply by another complex number, with 0 × ∞ = 0 + #[must_use] pub fn safe_mul(self, rhs: impl Into) -> Self { let rhs = rhs.into(); Self { @@ -204,6 +222,7 @@ impl Complex { im: safe_mul(self.re, rhs.im) + safe_mul(self.im, rhs.re), } } + #[must_use] pub fn recip(self) -> Self { Self::ONE / self } diff --git a/parser/src/error.rs b/parser/src/error.rs index 4914f90e9..db3bd4333 100644 --- a/parser/src/error.rs +++ b/parser/src/error.rs @@ -139,6 +139,7 @@ impl Report { /// Change whether to color the report with ANSI escape codes when converting it to a string /// /// Defaults to `true` + #[must_use] pub fn color(mut self, color: bool) -> Self { self.color = color; self diff --git a/parser/src/lex.rs b/parser/src/lex.rs index 5c556bb5a..c56261e99 100644 --- a/parser/src/lex.rs +++ b/parser/src/lex.rs @@ -168,6 +168,7 @@ impl Span { Sp { value, span: self } } /// Merge two spans + #[must_use] pub fn merge(self, other: Self) -> Self { match (self, other) { (Span::Code(a), Span::Code(b)) => Span::Code(a.merge(b)), @@ -396,6 +397,7 @@ impl CodeSpan { self.end.char_pos.saturating_sub(self.start.char_pos) } /// Merge two spans + #[must_use] pub fn merge(mut self, end: Self) -> Self { self.merge_with(end); self @@ -406,6 +408,7 @@ impl CodeSpan { self.end = self.end.max(end.end); } /// Get the span between this span and another after it + #[must_use] pub fn end_to(self, other: &Self) -> Self { CodeSpan { start: self.end, @@ -458,6 +461,7 @@ impl CodeSpan { inputs.try_get_with(&self.src, |input| f(&input[self.byte_range()])) } /// Get just the span of the first character + #[must_use] pub fn just_start(&self, inputs: &Inputs) -> Self { let start = self.start; let mut end = self.start; @@ -473,6 +477,7 @@ impl CodeSpan { } } /// Get just the span of the last character + #[must_use] pub fn just_end(&self, inputs: &Inputs) -> Self { let end = self.end; let mut start = self.end; diff --git a/parser/src/signature.rs b/parser/src/signature.rs index 70dc8542a..c707e38d6 100644 --- a/parser/src/signature.rs +++ b/parser/src/signature.rs @@ -39,6 +39,7 @@ impl Signature { } } /// Set the number of arguments and outputs of the under stack + #[must_use] pub fn with_under(self, under_args: usize, under_outputs: usize) -> Self { Self { args: self.args, @@ -108,6 +109,7 @@ impl Signature { self.is_compatible_with(other) && self.args <= other.args } /// Get the signature that has the maximum of the arguments and outputs of this signature and another + #[must_use] pub fn max_with(self, other: Self) -> Self { Self::new( self.args().max(other.args()), @@ -119,6 +121,7 @@ impl Signature { ) } /// Compose signatures as if a function with signature `other` was called before a function with signature `self` + #[must_use] pub fn compose(self, other: Self) -> Self { let args = other.args() + self.args().saturating_sub(other.outputs()); let outputs = self.outputs() + other.outputs().saturating_sub(self.args()); @@ -129,6 +132,7 @@ impl Signature { Self::new(args, outputs).with_under(under_args, under_outputs) } /// Get the un-inverse of this signature + #[must_use] pub fn inverse(self) -> Self { Self::new(self.outputs(), self.args()) } @@ -140,6 +144,7 @@ impl Signature { Some(Signature::new(self.outputs() + 1, self.args() - 1)) } /// The signature on the under stack + #[must_use] pub fn under(self) -> Signature { Signature::new(self.under_args(), self.under_outputs()) } diff --git a/src/algorithm/dyadic/combine.rs b/src/algorithm/dyadic/combine.rs index df7bb413c..7e73ebbdf 100644 --- a/src/algorithm/dyadic/combine.rs +++ b/src/algorithm/dyadic/combine.rs @@ -113,6 +113,7 @@ impl Value { /// /// # Panics /// Panics if the arrays have incompatible shapes + #[must_use] pub fn join_infallible(self, other: Self, allow_ext: bool) -> Self { self.join_impl(other, allow_ext, &()).unwrap() } @@ -233,6 +234,7 @@ impl Array { /// /// # Panics /// Panics if the arrays have incompatible shapes + #[must_use] pub fn join_infallible(self, other: Self, allow_ext: bool) -> Self { self.join_impl(other, allow_ext, &()).unwrap() } @@ -767,6 +769,7 @@ impl Value { /// /// # Panics /// Panics if the values have incompatible shapes + #[must_use] pub fn couple_infallible(mut self, other: Self, allow_ext: bool) -> Self { self.couple_impl(other, allow_ext, &()).unwrap(); self @@ -833,6 +836,7 @@ impl Array { /// /// # Panics /// Panics if the arrays have incompatible shapes + #[must_use] pub fn couple_infallible(mut self, other: Self, allow_ext: bool) -> Self { self.couple_impl(other, allow_ext, &()).unwrap(); self diff --git a/src/algorithm/monadic/mod.rs b/src/algorithm/monadic/mod.rs index b7f3fcc1e..826cc6ef8 100644 --- a/src/algorithm/monadic/mod.rs +++ b/src/algorithm/monadic/mod.rs @@ -1317,6 +1317,7 @@ impl Array { impl Value { /// `classify` the rows of the value + #[must_use] pub fn classify(&self) -> Self { if self.rank() == 0 { return 0.into(); @@ -1344,6 +1345,7 @@ impl Value { val_as_arr!(self, |a| a.deduplicate(env)) } /// Mask the `unique` rows of the value + #[must_use] pub fn unique(&self) -> Self { val_as_arr!(self, Array::unique).into() } diff --git a/src/array.rs b/src/array.rs index fb0ff7d81..b0a3909bb 100644 --- a/src/array.rs +++ b/src/array.rs @@ -321,6 +321,7 @@ pub struct PersistentMeta { impl PersistentMeta { /// XOR this metadata with another + #[must_use] pub fn xor(self, other: Self) -> Self { Self { label: self.label.xor(other.label), @@ -492,6 +493,7 @@ impl Array { } /// Get a row array #[track_caller] + #[must_use] pub fn row(&self, row: usize) -> Self { if self.rank() == 0 { let mut row = self.clone(); @@ -633,6 +635,7 @@ impl Array { /// - `start` must be <= `end` /// - `start` must be < `self.row_count()` /// - `end` must be <= `self.row_count()` + #[must_use] pub fn slice_rows(&self, start: usize, end: usize) -> Self { assert!(start <= end); assert!(start < self.row_count()); diff --git a/src/compile/mod.rs b/src/compile/mod.rs index da14a3639..e5b1fead7 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -307,6 +307,7 @@ impl Compiler { } } /// Set the compiler's assembly + #[must_use] pub fn with_assembly(self, asm: Assembly) -> Self { Self { asm, ..self } } diff --git a/src/format.rs b/src/format.rs index 6d8755b35..977e7f45f 100644 --- a/src/format.rs +++ b/src/format.rs @@ -192,6 +192,7 @@ The following configuration options are available: impl FormatConfig { $( #[allow(missing_docs)] + #[must_use] pub fn [](self, $name: $ty) -> Self { Self { $name, diff --git a/src/run.rs b/src/run.rs index 2f8243168..a26120cff 100644 --- a/src/run.rs +++ b/src/run.rs @@ -285,16 +285,19 @@ impl Uiua { take(&mut self.asm) } /// Set whether to emit the time taken to execute each instruction + #[must_use] pub fn time_instrs(mut self, time_instrs: bool) -> Self { self.rt.time_instrs = time_instrs; self } /// Limit the execution duration + #[must_use] pub fn with_execution_limit(mut self, limit: Duration) -> Self { self.rt.execution_limit = Some(limit.as_secs_f64()); self } /// Limit the execution duration + #[must_use] pub fn maybe_with_execution_limit(mut self, limit: Option) -> Self { self.rt.execution_limit = limit.map(|limit| limit.as_secs_f64()); self @@ -302,12 +305,14 @@ impl Uiua { /// Set the recursion limit /// /// Default is 100 for release builds and 20 for debug builds + #[must_use] pub fn with_recursion_limit(mut self, limit: usize) -> Self { self.rt.recursion_limit = limit; self } /// Set the interrupted hook #[cfg(not(target_arch = "wasm32"))] + #[must_use] pub fn with_interrupt_hook(mut self, hook: impl Fn() -> bool + Send + Sync + 'static) -> Self { self.rt.interrupted = Some(Arc::new(hook)); self @@ -319,6 +324,7 @@ impl Uiua { self } /// Set the command line arguments + #[must_use] pub fn with_args(mut self, args: Vec) -> Self { self.rt.cli_arguments = args; self @@ -328,6 +334,7 @@ impl Uiua { self.rt.cli_arguments.as_slice() } /// Set the path of the file that is being executed + #[must_use] pub fn with_file_path(mut self, file_path: impl Into) -> Self { self.rt.cli_file_path = file_path.into(); self diff --git a/src/shape.rs b/src/shape.rs index bf110c921..3e6a94d48 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -76,6 +76,7 @@ impl Shape { self.dims.iter().skip(1).product() } /// Get the row shape + #[must_use] pub fn row(&self) -> Shape { let mut shape = self.clone(); shape.make_row(); @@ -86,6 +87,7 @@ impl Shape { &self.dims[self.len().min(1)..] } /// Construct a subshape + #[must_use] pub fn subshape(&self, range: R) -> Shape where [usize]: Index, @@ -153,6 +155,7 @@ impl Shape { self.dims.extend_from_slice(dims); } /// Split the shape at the given index + #[must_use] pub fn split_off(&mut self, at: usize) -> Self { let (_, b) = self.dims.split_at(at); let second = Shape::from(b); diff --git a/src/tree.rs b/src/tree.rs index 59b64466b..272f44f10 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -125,6 +125,7 @@ impl SigNode { } } /// Call this node on N sets of arguments + #[must_use] pub fn on_all(self, n: usize, span: usize) -> SigNode { let sig = self.sig; let mut sig = sig.with_under(sig.under_args() * n, sig.under_outputs() * n); @@ -166,6 +167,7 @@ impl SigNode { SigNode::new(sig, node) } /// Dip before calling this node + #[must_use] pub fn dipped(self, depth: usize, span: usize) -> SigNode { let mut sig = self.sig; sig.update_args_outputs(|a, o| (a + depth, o + depth)); @@ -350,6 +352,7 @@ impl Node { } } /// Slice the node to get a subnode + #[must_use] pub fn slice(&self, range: R) -> Self where R: SliceIndex<[Node], Output = [Node]>, @@ -401,6 +404,7 @@ impl Node { } /// Split the node at the given index #[track_caller] + #[must_use] pub fn split_off(&mut self, index: usize) -> Self { if let Node::Run(nodes) = self { let removed = EcoVec::from(&nodes[index..]); diff --git a/src/value.rs b/src/value.rs index 0ac5ad634..f8098bfb4 100644 --- a/src/value.rs +++ b/src/value.rs @@ -429,6 +429,7 @@ impl Value { } /// Get the row at the given index #[track_caller] + #[must_use] pub fn row(&self, i: usize) -> Self { val_as_arr!(self, |arr| arr.row(i).into()) } @@ -1311,6 +1312,7 @@ impl Value { } } /// Remove all top-level layers of boxing + #[must_use] pub fn unpacked(self) -> Self { match self { Self::Box(arr) => match arr.into_unboxed() { @@ -1330,6 +1332,7 @@ impl Value { } } /// Apply a function to the highest-level unboxed value + #[must_use] pub fn map_boxed(self, f: impl FnOnce(Self) -> Self) -> Self { match self { Value::Box(boxed) => match boxed.into_scalar() { @@ -1358,6 +1361,7 @@ impl Value { } } /// Remove a single layer of boxing + #[must_use] pub fn unboxed(self) -> Self { match self { Value::Box(boxed) => match boxed.into_scalar() { @@ -1368,6 +1372,7 @@ impl Value { } } /// Remove a single layer of boxing if the condition is met + #[must_use] pub fn unboxed_if(self, unbox: bool) -> Self { if unbox { self.unboxed() @@ -1376,6 +1381,7 @@ impl Value { } } /// Box the value if the condition is met + #[must_use] pub fn boxed_if(self, do_box: bool) -> Self { if do_box { Boxed(self).into()