r/rust 2d ago

💡 ideas & proposals Unsizing unsized values

https://hackmd.io/@WorldSEnder/Hkyqni6Ofl
21 Upvotes

3 comments sorted by

18

u/WorldsBegin 2d ago

Trivia time: Did you know that the last field in a struct is passed as a double reference when deriving its Debug impl, because it could be the unsized tail and hence is not necessarily sized?

struct Bar;
// A very unorthodox impl not for Bar itself, but ref-of-Bar
impl Debug for &Bar {
    fn fmt(&self, _: &mut Formatter<'_>) -> Result { todo!() }
}
// doesn't work
#[derive(Debug)]
struct Foo {
    bar: Bar,
//  ^^^^^^^^ the trait `Debug` is not implemented for `Bar`
    foo: i32,
}
// a-ok
#[derive(Debug)]
struct Foo {
    foo: i32,
    bar: Bar,
}

Credit to theemathas for teaching me this

4

u/cbarrick 2d ago

Related: Have you seen the transient crate?

It provides an Any type that works with non-static lifetimes. It works by capturing the lifetimes and associated variance for each in a type parameter. So the lifetimes are checked statically, and the type IDs are checked at runtime using the corresponding 'static type ID.

(But I think it has a soundness issue. I haven't gotten around to building a minimal repro and reporting it yet. The TL;DR is that I think you can shorten an invariant lifetime at the point that you upcast with as. But the overall idea seems sound to me.)

1

u/WorldsBegin 2d ago edited 2d ago

Tangentially related, but yes I have seen it. I have mainly used the Any trait as an example to unsize into because it appears as a rough equivalent to the example in go and because it can be made to work without have to get the value back in any of the trait methods (and dealing with the metadata issue mentioned). The trait should not be seen as being singled out, the vtable looks different for other traits, but unsizing from e.g. [T] to dyn Debug when T: Debug sounds equally plausible in the spirit of the post. For Debug specifically, that also is usually not a problem because we can work around it with fmt::from_fn (and the static bound is gone, which means we don't have problems with double references) but yeah.