Rust 1.47 removes the length ceiling from many array traits
Standard-library array implementations now use internal const-generics support across arbitrary lengths. That does not stabilize const generics for user code or remove every array limitation.
An array with 34 elements should not lose debug formatting merely because its length exceeds a library implementation list. Rust previously imposed that ceiling on several standard traits. The element type could support the operation, yet an array longer than 32 elements could fail a trait bound. Rust 1.47 removes that restriction from many standard-library array implementations.
The release announcement explains the underlying constraint. Array length is part of the type, but stable Rust cannot yet let user code be generic over arbitrary integer values. Standard-library implementations had therefore supported an enumerated set of lengths. Internal const-generics support is now sufficient to remove many of those length checks without stabilizing the language feature generally.
I like Rust's ability to encode fixed structure in a type. The old implementation ceiling made that structure inconvenient at an arbitrary boundary. Removing it lets more code keep an array representation without changing the representation merely to obtain ordinary trait behavior.
The number belongs to the type
The types [u8; 32] and [u8; 34] differ even though their elements have the same type. Implementing a trait for every array length needs a way to express the length as a parameter. Without that facility, a library must generate separate implementations or use another representation at its public boundary.
The standard library's selected ceiling was 32. The announcement demonstrates the consequence with an array of 34 integers and a debug print. Rust 1.46 reports the missing length-bound implementation. Rust 1.47 prints the array.
fn main() {
let values = [0_u8; 34];
println!("{:?}", values);
}
The change does not add a runtime branch that checks whether the array is small enough. It changes which trait implementations the compiler can select for the type. Element-level trait requirements still apply. An arbitrary length does not make an element type implement Debug when it did not do so before.
Internal generics support changes stable library behavior
The array implementation patch removes LengthAtMost32 restrictions from several implementations. Its first change updates AsRef, AsMut, Borrow, and BorrowMut. Later changes remove the guard in other array-related implementations and delete the temporary length marker.
The implementation can describe an array using an internal constant parameter. Stable callers benefit from the resulting standard traits even though they cannot yet write equivalent generic implementations for their own traits. This is a deliberate separation between what the standard library may use internally and what the stable language exposes to everyone.
That separation is important for interpreting the release. A successful debug print of a large array does not demonstrate that a stable crate can now define every array-length-generic abstraction. The announcement explicitly says const generics have not stabilized and gives no estimated stabilization date.
Libraries with their own traits therefore retain a different limitation from the standard library. They may need existing workarounds until the language feature becomes available to them. Standard-library progress removes one common obstacle without establishing that all generic array design is now possible on stable.
Default retains its separate limit
The patch's documentation makes an important exception. Arrays of any size gain the listed traits when their element types permit them, but Default remains implemented for lengths zero through 32. A broad statement that every array trait now works at every length would be wrong.
The distinction follows from separate implementations and their requirements. Removing a common guard from one set of traits does not automatically supply every construction operation. The documentation continues to describe the generated Default implementations separately.
The patch also describes iteration through references to arrays. This should not be confused with a new stable by-value IntoIterator implementation for arrays themselves. The context of the implemented receiver type matters. Code relying on method resolution must distinguish an array from a borrowed array even when the syntax looks similar.
The changes extend some allocation-related conversions too. The patch removes length restrictions from conversions involving arrays and boxed slices, and from checked conversions of reference-counted slices to reference-counted arrays. Those operations retain their own semantics. A checked conversion still needs to establish that the source has the destination length.
I regard these qualifications as part of the useful explanation. The release removes a specific artificial ceiling. It does not make array construction, ownership, and conversion interchangeable operations.
Tests cross the former boundary
The patch replaces tests expecting missing implementations at length 33 with tests expecting those implementations to exist. That length is directly outside the old range. It verifies the intended boundary change without requiring an enormous array.
One follow-up corrects tests that accidentally still used length 32. A test at the old maximum would not establish that the restriction had been removed. The correction makes the new assertion exercise the behavior the patch intends to add.
This is a useful testing detail because general-looking code can still test only the previously supported case. Choosing a value just beyond the old boundary demonstrates that the implementation no longer relies on the enumerated range. The test needs to cross the boundary in its actual instantiated type.
The updated documentation also removes obsolete size qualifications from examples of iterating over borrowed arrays. That keeps the explanation aligned with the selected receiver type and the newly available implementations, while preserving the separate text for operations that still have a length restriction.
Other tooling changes have different scopes
Rust 1.47 also restores shorter panic backtraces after a regression. The default view removes internal noise, while RUST_BACKTRACE=full remains available for the complete trace. This improves the presentation of an existing diagnostic rather than changing panic behavior.
The release adds -C control-flow-guard for Windows and upgrades the default backend to LLVM 11. The announcement says other platforms ignore the guard flag. Those toolchain changes should retain their platform and implementation qualifications, just as the array change retains its trait-specific exceptions.
The array improvement itself is visible through ordinary stable operations. Existing fixed-size values can satisfy many standard trait bounds beyond 32 elements, provided their elements meet the necessary conditions. The compiler's internal support supplies those implementations while user-defined const generics and the remaining Default ceiling stay separate questions.