chore: add pedantic workspace lints (#90)

Add [workspace.lints.rust] and wire each member crate up with
[lints] workspace = true:

  unsafe_code = "deny"        (forbid would break the Android JNI build)
  single_use_lifetimes = "warn"
  trivial_casts = "warn"
  unused_lifetimes = "warn"
  unused_qualifications = "warn"
  variant_size_differences = "warn"
  unexpected_cfgs = "warn"

unsafe_code is "deny" rather than the issue's "forbid" so the three
Android JNI FFI modules (android_keystore, android_clipboard, safe_area)
can opt back in with a scoped #![allow(unsafe_code)] — forbid cannot be
locally overridden. Pure crates carry no unsafe and stay clean.

Clean up the warnings the new lints surface:
- 150ish unused_qualifications removed via `cargo fix` (purely syntactic
  redundant-path-prefix removals).
- table_plugin: the TABLE_COLOUR import was #[cfg(test)]-gated while the
  camera clear-colour used the fully-qualified path; unqualifying it left
  a non-test build with no import. Made the import unconditional instead.
- assets/sources: the `as &[u8]` casts in embed_*_svg! coerce each
  fixed-size &[u8; N] to a uniform slice so the tuples fit the
  &[(&str, &[u8])] arrays — load-bearing, so scoped #[allow(trivial_casts)].

Workspace clippy -D warnings and the full test suite pass. Android build
not compiled here (needs the NDK; built separately per CLAUDE.md §15) —
the deny + scoped-allow keeps the JNI unsafe blocks legal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-12 13:05:28 -07:00
parent 9bbb57134f
commit ceb9c950a1
48 changed files with 191 additions and 130 deletions
+3
View File
@@ -9,3 +9,6 @@ serde = { workspace = true }
uuid = { workspace = true }
chrono = { workspace = true }
thiserror = { workspace = true }
[lints]
workspace = true
+7 -7
View File
@@ -755,14 +755,14 @@ mod tests {
fn progress_total_xp_takes_max() {
let mut local = default_payload();
local.progress.total_xp = 1500;
local.progress.level = crate::progress::level_for_xp(1500);
local.progress.level = level_for_xp(1500);
let mut remote = default_payload();
remote.progress.total_xp = 2500;
remote.progress.level = crate::progress::level_for_xp(2500);
remote.progress.level = level_for_xp(2500);
let (merged, _) = merge(&local, &remote);
assert_eq!(merged.progress.total_xp, 2500);
assert_eq!(merged.progress.level, crate::progress::level_for_xp(2500));
assert_eq!(merged.progress.level, level_for_xp(2500));
}
#[test]
@@ -815,7 +815,7 @@ mod tests {
let (merged, _) = merge(&local, &remote);
assert_eq!(merged.progress.total_xp, 5500);
assert_eq!(merged.progress.level, crate::progress::level_for_xp(5500));
assert_eq!(merged.progress.level, level_for_xp(5500));
}
// -----------------------------------------------------------------------
@@ -1051,11 +1051,11 @@ mod tests {
// drop the oldest 50 so the cap is preserved.
let start = nd(2024, 1, 1);
let local_dates: Vec<NaiveDate> = (0..DAILY_CHALLENGE_HISTORY_CAP as i64)
.map(|i| start + chrono::Duration::days(i))
.map(|i| start + Duration::days(i))
.collect();
let remote_dates: Vec<NaiveDate> = (DAILY_CHALLENGE_HISTORY_CAP as i64
..DAILY_CHALLENGE_HISTORY_CAP as i64 + 50)
.map(|i| start + chrono::Duration::days(i))
.map(|i| start + Duration::days(i))
.collect();
let mut local = default_payload();
@@ -1073,7 +1073,7 @@ mod tests {
// is therefore start + 50 days.
assert_eq!(
merged.progress.daily_challenge_history.first().copied(),
Some(start + chrono::Duration::days(50))
Some(start + Duration::days(50))
);
// Most recent retained is the last remote date.
assert_eq!(