Forbid unsafe code #91

Closed
opened 2026-06-13 06:21:14 +00:00 by Quaternions · 1 comment

The pedantic lints were bastardized. Refactor the android code to use safe bindings and forbid any unsafe code as originally intended by #90.

The pedantic lints were bastardized. Refactor the android code to use safe bindings and forbid any unsafe code as originally intended by #90.
Owner

Fixed in 9299176 (branch refactor/strip-card_game-redundancies, PR #88).

You were right that #90 was a bastardization — deny + three scattered
#![allow(unsafe_code)] across solitaire_data and solitaire_engine poked
unsafe holes into otherwise-pure logic crates. Rather than just relocate the
unsafe, I reduced it:

  • New safe solitaire_data::android_jni bridge owns the cached JavaVM +
    activity GlobalRef and exposes with_env / with_activity_env. Keystore,
    clipboard and safe-area now go through it and never touch a raw handle.
  • The three unsafe { JByteArray::from_raw(x.into_raw()) } casts in the
    keystore became the safe JByteArray::from(JObject) conversion jni 0.21
    already provides.
  • All three #![allow(unsafe_code)] are gone; solitaire_data and
    solitaire_engine are now unsafe-free.
  • Workspace is unsafe_code = "forbid".

One unavoidable exception: solitaire_app. As the cdylib it must export the
#[unsafe(no_mangle)] android_main and reconstruct the raw JavaVM / activity
once there (a no_mangle symbol can't live in a dependency rlib). It opts to
its own deny-level lints with two scoped #[allow(unsafe_code)]. That single
entry point is the only unsafe left in the tree — 7 sites across three crates
down to 3 at the OS boundary in one crate.

Verified with host clippy --workspace --all-targets -- -D warnings and an
aarch64-linux-android clippy build of solitaire_app (transitively engine +
data). If you consider the cdylib entry an acceptable exception, this is ready
to close.

Fixed in 9299176 (branch `refactor/strip-card_game-redundancies`, PR #88). You were right that #90 was a bastardization — `deny` + three scattered `#![allow(unsafe_code)]` across `solitaire_data` and `solitaire_engine` poked unsafe holes into otherwise-pure logic crates. Rather than just relocate the unsafe, I reduced it: - New safe `solitaire_data::android_jni` bridge owns the cached `JavaVM` + activity `GlobalRef` and exposes `with_env` / `with_activity_env`. Keystore, clipboard and safe-area now go through it and never touch a raw handle. - The three `unsafe { JByteArray::from_raw(x.into_raw()) }` casts in the keystore became the safe `JByteArray::from(JObject)` conversion jni 0.21 already provides. - All three `#![allow(unsafe_code)]` are gone; `solitaire_data` and `solitaire_engine` are now unsafe-free. - Workspace is `unsafe_code = "forbid"`. One unavoidable exception: `solitaire_app`. As the cdylib it must export the `#[unsafe(no_mangle)] android_main` and reconstruct the raw `JavaVM` / activity once there (a `no_mangle` symbol can't live in a dependency rlib). It opts to its own `deny`-level lints with two scoped `#[allow(unsafe_code)]`. That single entry point is the only `unsafe` left in the tree — 7 sites across three crates down to 3 at the OS boundary in one crate. Verified with host `clippy --workspace --all-targets -- -D warnings` and an `aarch64-linux-android` clippy build of `solitaire_app` (transitively engine + data). If you consider the cdylib entry an acceptable exception, this is ready to close.
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: funman300/Ferrous-Solitaire#91