Skip to content

Confusing error reported for trait impls on DST with the last field being Sized  #83097

Closed

Description

@BoxyUwU

Given the following code: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=d9a00dc0e329f0ea73b037f3af9f26db

use std::marker::PhantomData;

trait Trait {}

struct Unsized([u8], ());
struct Foo<T: ?Sized>(PhantomData<T>);

impl<T> Trait for Foo<T> {}
impl Trait for Foo<Unsized> {}

The current output is:

error[E0119]: conflicting implementations of trait `Trait` for type `Foo<Unsized>`:
 --> src/main.rs:9:1
  |
8 | impl<T> Trait for Foo<T> {}
  | ------------------------ first implementation here
9 | impl Trait for Foo<Unsized> {}
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo<Unsized>`

Ideally the output should look like:

error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
 --> src/lib.rs:1:16
  |
5 | struct Unsized([u8], ());
  |                ^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `[u8]`
  = 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: borrowed types always have a statically known size
  |
5 | struct Unsized(&[u8], ());
  |                ^
help: the `Box` type always has a statically known size and allocates its contents in the heap
  |
5 | struct Unsized(Box<[u8]>, ());
  |                ^^^^    ^

error: aborting due to previous error

Note: this error is particularly confusing because the trait impls *dont* overlap after fixing the field ordering error

cc @estebank

Activity

  1. added
    A-diagnosticsArea: Messages for errors, warnings, and lints
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Mar 13, 2021
  2. eddyb commented on Mar 13, 2021

    @eddyb
    Contributor

    FWIW I don't think we can avoid the trait impl overlap false positive error, without introducing cyclic dependencies.

    cc @nikomatsakis but my understanding is that to prove Unsized: Sized, only the last field of Unsized has to be considered, and this may be used sometimes before Unsized's definition was checked (as in this case, during coherence-checking).

    However, the fact that we get "conflicting implementations" errors and no other errors suggests to me that we stop compilation early, which is something that I know has been slowly rectified.

    So my opinion is that for now we likely can't do better than "keep going and emit both errors", which should be simple enough to try - tho I am a bit worried its effects on tests' expected output (more errors/warnings from later on), and it's possible the trait system might get a bit wonky if there are overlapping impls - do they all apply and cause ambiguity errors down the line?

  3. changed the title [-]Incorrect error reported for trait impls on DST with the last field being Sized [/-] [+]Confusing error reported for trait impls on DST with the last field being Sized [/+] on Mar 13, 2021
  4. added
    D-confusingDiagnostics: Confusing error or lint that should be reworked.
    D-incorrectDiagnostics: A diagnostic that is giving misleading or incorrect information.
    on Mar 16, 2021
  5. kadiwa4 commented on Mar 26, 2024

    @kadiwa4
    Contributor

    Fixed since 1.78.0:

    error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
     --> src/lib.rs:5:16
      |
    5 | struct Unsized([u8], ());
      |                ^^^^ doesn't have a size known at compile-time
      |
      = help: the trait `Sized` is not implemented for `[u8]`
      = 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: borrowed types always have a statically known size
      |
    5 | struct Unsized(&[u8], ());
      |                +
    help: the `Box` type always has a statically known size and allocates its contents in the heap
      |
    5 | struct Unsized(Box<[u8]>, ());
      |                ++++    +
    
    error[E0119]: conflicting implementations of trait `Trait` for type `Foo<Unsized>`
     --> src/lib.rs:9:1
      |
    8 | impl<T> Trait for Foo<T> {}
      | ------------------------ first implementation here
    9 | impl Trait for Foo<Unsized> {}
      | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo<Unsized>`
    
    Some errors have detailed explanations: E0119, E0277.
    For more information about an error, try `rustc --explain E0119`.
    

    The "conflicting implementations" error still appears, but I thinks that's fine, especially because rustc suggests that you should turn the [u8] field into a sized one (&[u8] or Box<[u8]>). So at least the diagnostics are consistent with each other.

    @rustbot label: +E-needs-test

  6. added
    E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.
    on Mar 26, 2024
  7. zakrad commented on Aug 6, 2026

    @zakrad
    Contributor

    @rustbot claim

  8. added 2 commits that reference this issue on Aug 8, 2026
    ecd4222
    7416d7a
  9. added a commit that references this issue on Aug 8, 2026
    9ab1c6c
  10. added a commit that references this issue on Aug 9, 2026
    5ff9361
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsD-confusingDiagnostics: Confusing error or lint that should be reworked.D-incorrectDiagnostics: A diagnostic that is giving misleading or incorrect information.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions