Pitfalls of Safe Rust
Casting and the as Operator
- Many see
as(especially for narrowing integer conversions) as a remaining “footgun” in otherwise safety‑oriented Rust. - Desired alternatives:
- Convenient checked casts (
try_into-style, but with lighter syntax), - Separate, visually loud syntax for lossy/modulo casts.
- Convenient checked casts (
- Others argue
asis pragmatically necessary, especially for deliberate truncation, and that the real issue is making safe conversions less verbose. - There is mention of lints and a slow push to de‑emphasize
as, but some conversions (e.g., integer→float) still lack clear safe APIs.
Overflow and Numeric Correctness
- Strong disagreement over how serious integer overflow is:
- Some claim overflows are rare and not worth pervasive checked arithmetic.
- Others, citing formal verification experience, say overflows are extremely common bugs and often security‑relevant.
- Rust’s choice: checks in debug builds, explicit APIs (
checked_*,saturating_*,Wrapping,Saturatingtypes) for release. - Debate over defaults: some want checked arithmetic and panics by default in release; others prioritize performance and point to compiler flags for enabling checks.
- Refinement/liquid types (e.g., Flux) are discussed as a promising direction to statically rule out overflows and out‑of‑bounds accesses.
What “Safe Rust” Means
- One camp: “safe Rust” is specifically “memory‑safe Rust” (no UB from safe code), matching official docs and the
unsafekeyword. - Another camp informally broadens “safe” to “if it compiles, it probably works,” bundling memory safety with stronger typing and APIs.
- This mismatch fuels confusion and accusations of “false advertising,” especially when contrasted with C++.
Rust vs C++, Go, and Others
- Several comments compare Rust’s guarantees with C++:
- C++ smart pointers/containers help, but UB remains easy (null deref, unchecked
operator[], iterator invalidation, optional/variant misuse). - Rust’s borrow checker,
Option, and trait system make many C++-style bugs impossible or much harder.
- C++ smart pointers/containers help, but UB remains easy (null deref, unchecked
- Go is suggested by some as better for robust services; others counter that Go lacks null safety and Rust’s strong typing, and Rust can more systematically prevent data races.
Other Pitfalls and APIs
- Path handling:
Path::joindiscarding the prefix when given an absolute path is seen as a footgun; some want a distinct “prefix if relative” API. - Memory leaks via
Rc/Arccycles are noted, but others argue they’re relatively hard to create accidentally due to ownership, immutability, and type structure. - Misuse of
mem::size_of_val(&T)(measuring the reference, not the pointee) is flagged as a subtle but serious trap in low‑level code.