gccrs#4767: Improve box
Link: Rust-GCC/gccrs#4767
Note
This is important
Objective
This PR introduces full DST support for Box, allowing it to correctly handle unsized types like trait objects and slices. Crucially, it also implements the compiler-level auto-deref mechanism for Box.
Changes Made
Wired up the compiler’s auto-dereference logic to recognize Box<T> similarly to how it recognizes standard references (&T). This ensures that method dispatch, array indexing, and tuple field accesses are transparently forwarded to the underlying data pointer inside the box.
Why is this needed for alloc?
While Box<T> is defined as a standard struct in the alloc crate, it requires compiler magic to be ergonomic. When a developer writes my_box.method() or my_box[0], the compiler must automatically dereference the pointer.
Test Case
Box dispatch from dyn:
trait Animal {
fn get_age(self: Box<Self>) -> i32;
}
struct Dog {
age: i32,
}
impl Animal for Dog {
fn get_age(self: Box<Self>) -> i32 {
self.age
}
}
fn foo () -> i32 {
let dog = Dog { age: 42 };
let _ = dog.age;
let coerced_box: Box<dyn Animal> = Box::new(dog);
let result = coerced_box.get_age();
// ^^^^^^^^^^^^^^^^^^^^^ auto-deref for method call
if result == 42 {
0
} else {
1
}
}
fn main() {
if foo() == 0 {
println!("ok.");
}
}
Box dispatch:
struct X { data: i32 }
trait A {
fn a(&self) -> i32;
}
impl A for X {
fn a(&self) -> i32 {
self.data
}
}
fn foo() -> i32 {
let x = X { data: 44 };
let y = X { data: 22 };
let z : [i32; 3] = [1, 2, 3];
let w : (i32, i32) = (10, 20);
let a : Box<dyn A> = Box::new(x);
let b : Box<X> = Box::new(y);
let c : Box<[i32; 3]> = Box::new(z);
let d : Box<(i32, i32)> = Box::new(w);
let e : Box<[i32]> = Box::new(z);
a.a() - 2 * b.data // 44 - 2 * 22
// ^^^^^ ^^^^^^ ─> field access
// └─> method dispatch(dyn)
+
c[0] + c[1] - c[2] // 1 + 2 - 3
// ^^^^ ─ ^^^^ ─ ^^^^ ─> array index access
+
2 * d.0 - d.1 // 2 * 10 - 20
// ^^^ ─ ^^^ ─> tuple field access
+
e[0] + e[1] - e[2] // 1 + 2 - 3
// ^^^^ ─ ^^^^ ─ ^^^^ ─> slice index access with trait Index
}
fn main() {
if foo() == 0 {
println!("ok.");
}
}