Repository: rust
Issue: Better Error for struct's with a field, that is DST, which is not the last
Labels: A-diagnostics,A-DSTs,T-compiler,A-suggestion-diagnostics,D-newcomer-roadblock

### Code

```Rust
pub struct ReadHalf<T: ?Sized> {
    inner: Arc<Inner<T>>,
}

pub struct WriteHalf<T: ?Sized> {
    inner: Arc<Inner<T>>,
}

struct Inner<T: ?Sized> {
    locked: AtomicBool,
    stream: UnsafeCell<T>,
    is_write_vectored: bool,
}
```


### Current output

```sh
/etc/profiles/per-user/timon/bin/cargo build --color=always --message-format=json-diagnostic-rendered-ansi --all --all-targets
```

```
error[E0277]: the size for values of type `T` cannot be known at compilation time
    --> tokio/src/io/split.rs:58:13
     |
56   | struct Inner<T: ?Sized> {
     |              - this type parameter needs to be `Sized`
57   |     locked: AtomicBool,
58   |     stream: UnsafeCell<T>,
     |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
     |
note: required because it appears within the type `UnsafeCell<T>`
    --> /home/timon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/cell.rs:1987:12
     |
1987 | pub struct UnsafeCell<T: ?Sized> {
     |            ^^^^^^^^^^
     = note: only the last field of a struct may have a dynamically sized type
     = help: change the field's type to have a statically known size
help: consider removing the `?Sized` bound to make the type parameter `Sized`
     |
56   - struct Inner<T: ?Sized> {
56   + struct Inner<T> {
     |
help: borrowed types always have a statically known size
     |
58   |     stream: &UnsafeCell<T>,
     |             +
help: the `Box` type always has a statically known size and allocates its contents in the heap
     |
58   |     stream: Box<UnsafeCell<T>>,
     |             ++++             +

error[E0277]: the size for values of type `T` cannot be known at compilation time
    --> tokio/src/io/split.rs:58:13
     |
56   | struct Inner<T: ?Sized> {
     |              - this type parameter needs to be `Sized`
57   |     locked: AtomicBool,
58   |     stream: UnsafeCell<T>,
     |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
     |
note: required because it appears within the type `UnsafeCell<T>`
    --> /home/timon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/cell.rs:1987:12
     |
1987 | pub struct UnsafeCell<T: ?Sized> {
     |            ^^^^^^^^^^
     = note: only the last field of a struct may have a dynamically sized type
     = help: change the field's type to have a statically known size
help: consider removing the `?Sized` bound to make the type parameter `Sized`
     |
56   - struct Inner<T: ?Sized> {
56   + struct Inner<T> {
     |
help: borrowed types always have a statically known size
     |
58   |     stream: &UnsafeCell<T>,
     |             +
help: the `Box` type always has a statically known size and allocates its contents in the heap
     |
58   |     stream: Box<UnsafeCell<T>>,
     |             ++++             +

error: aborting due to previous error
```


### Desired output

```sh
/etc/profiles/per-user/timon/bin/cargo build --color=always --message-format=json-diagnostic-rendered-ansi --all --all-targets
```

```diff
  error[E0277]: the size for values of type `T` cannot be known at compilation time
      --> tokio/src/io/split.rs:58:13
       |
  56   | struct Inner<T: ?Sized> {
       |              - this type parameter needs to be `Sized`
  57   |     locked: AtomicBool,
  58   |     stream: UnsafeCell<T>,
       |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
       |
  note: required because it appears within the type `UnsafeCell<T>`
      --> /home/timon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/cell.rs:1987:12
       |
  1987 | pub struct UnsafeCell<T: ?Sized> {
       |            ^^^^^^^^^^
     = note: only the last field of a struct may have a dynamically sized type
-    = help: change the field's type to have a statically known size
+ help: if you want to make the type `Inner` dynamically sized,
+       consider moving the field `stream` to the end of the struct
+ 56   | struct Inner<T: ?Sized> {
+      |              - this type parameter needs to be `Sized`
+ 57   |     locked: AtomicBool,
+ 58   -     stream: UnsafeCell<T>,
+ 58   +     is_write_vectored: bool,
+ 59   +     stream: UnsafeCell<T>,
+ 59   -     is_write_vectored: bool,
+ note: if you want to keep the type `Inner` as a sized type, consider one of the following suggestions
  help: consider removing the `?Sized` bound to make the type parameter `Sized`
       |
  56   - struct Inner<T: ?Sized> {
  56   + struct Inner<T> {
       |
  help: borrowed types always have a statically known size
       |
  58   |     stream: &UnsafeCell<T>,
       |             +
  help: the `Box` type always has a statically known size and allocates its contents in the heap
       |
  58   |     stream: Box<UnsafeCell<T>>,
       |             ++++             +
  
  error: aborting due to previous error
```


### Rationale and extra context

I was kind of confused on how to make a struct DST at first, since the error-message only suggested to make the struct sized again.