-
-
Notifications
You must be signed in to change notification settings - Fork 14.3k
Closed
Description
Sample code: https://play.rust-lang.org/?gist=b9b0fad33060c74095a0&version=nightly
Short sample code that fails to compile:
let a = [0;5];
let x = a[0u8];I'm working on a native Rust implementation of the Google Brotli compression algorithm (https://github.com/peter-bertok/brotli), which has a lot of low-level bit/byte twiddling and came across this issue.
- Array indexing using arbitrary integral types works in literally every other mainstream language I can think of. Many other languages allow non-integral types as well, such as their equivalent of
repr(C)enums. - Many unnecessary explicit type casts are required in certain types of code (binary format parsing, native interop, etc...)
- An implicit cast from small unsigned integral types is never harmful. That is:
u8,u16, andu32. - Casts from other types can be handled with a new warning or the existing error, with an explicit cast required to ensure the developer understands that truncation/wrapping is possible.
- Alternatively, the bounds checking in Rust can be relied upon to provide protection. E.g.: indexing with a negative value should always cause a panic. In fact, this can be made SAFER than an explicit cast. Think of the scenario where a large negative signed number is explicitly cast by the programmer to
usize, like they have to do now. This would wrap to a small positive number, which is a valid index. If the rust compiler provides an implementation forIndexed<>with signed types, it can insert a check for negative numbers, improving safety substantially. Currently, this compiles and runs without a panic:
let offs: i64 = -18446744073709551611;
let a = [0;50];
let x = a[offs as usize];- This issue also causes the compiler to infer the
usizetype unexpectedly, which is confusing to developers. Goes against the rule of least surprise. This fails to compile unexpectedly:
let offs: u32 = 1; // explicit integral type. Could be a function parameter, struct member, etc...
let mut i = 0; // due to slice indexing, this is inferred to be `usize`
let a = [0;5]; // any slice of any type, doesn't matter
let x = a[i];
// This results in: "the trait `core::ops::Add<u32>` is not implemented for the type `usize`"
let y = a[i+offs]; Proposal
- Implement the
IndexedandIndexedMuttraits foru8,u16, andu32for slice and Vec types with identical behaviour to theusizeversion. - Implement the
IndexedandIndexedMuttraits forisize,i8,i16, andi32for slice and Vec types with new behaviour that panics on negative values, not just out-of-bounds positive values. - The
i64andu64implementations are problematic on 32-bit builds. How these are treated is up for debate.
kornelski, skiwi2, initbar, PSeitz, Timmmm and 2 moreAxlLind and slluk
Metadata
Metadata
Assignees
Labels
No labels