rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.33k stars 12.58k forks source link

unsized generic field not allowed in repr(packed) struct #49903

Open z33ky opened 6 years ago

z33ky commented 6 years ago

For some reason, using a generic T: ?Sized does not work in a repr(packed) struct, while a non-generic unsized type is OK.

#[repr(packed)]
struct Bar([u8]); // ok

#[repr(packed)]
struct Foo<T: ?Sized>(T): // err

An non-packed is also OK: struct Foo<T: ?Sized>(T); // ok

The full error:

error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
  |
5 | struct Foo<T: ?Sized>(T); // err
  |                       ^^ `T` does not have a constant size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `T`
  = help: consider adding a `where T: std::marker::Sized` bound
  = note: only the last field of a struct may have a dynamically sized type

This may be related to #47068?

Meta

$ rust --version --verbose
rustc 1.25.0 (84203cac6 2018-03-25)
binary: rustc
commit-hash: 84203cac67e65ca8640b8392348411098c856985
commit-date: 2018-03-25
host: x86_64-unknown-linux-gnu
release: 1.25.0
LLVM version: 6.0
rectang commented 1 year ago

The full error has changed in recent years, and now contains a note which suggests a partial workaround:

  = note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run

Thus prompted, I discovered that wrapping the DST field in ManuallyDrop allows compilation to complete successfully:

  #[repr(packed)]
- struct Foo<T: ?Sized>(T): // err
+ struct Foo<T: ?Sized>(std::mem::ManuallyDrop<T>); // no err