ZST semver footgun
⚓ Rust 📅 2025-11-21 👤 surdeus 👁️ 9I recently got quite stuck on a bug in my project which boils down to this example:
use std::any::Any;
#[derive(Debug)]
pub struct Foo(pub u32);
fn boxit<T: 'static>(x: T) -> Box<dyn Any> {
Box::new(x)
}
fn unboxit<T: 'static>(b: Box<dyn Any>) -> T {
*b.downcast::<T>().unwrap()
}
fn main() {
let b = boxit(Foo);
let x: Foo = unboxit(b);
println!("{x:?}");
}
The footgun here is that once Foo was a ZST type and the program worked, but then someone added a field to it, and while the code kept compiling the semantics changed. Suddenly Foo in boxit(Foo) was a function fn() -> Foo and main panicked.
What is the right strategy to avoid this problem?
6 posts - 5 participants
🏷️ Rust_feed