Skip to content

Make E0277 on Sized its own error code with more focused explanation #130359

Open
@kpreid

Description

@kpreid

Code

// inspired by https://github.com/rust-lang/rust/issues/130326
fn main() {
    let mut a = String::new();
    let b = String::new();
    *a = *b;
}

fn other_fn(x: str) {
    _ = x;
}

Current output

error[E0277]: the size for values of type `str` cannot be known at compilation time
 --> src/main.rs:4:5
  |
4 |     *a = *b;
  |     ^^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `str`
  = note: the left-hand-side of an assignment must have a statically known size

error[E0277]: the size for values of type `str` cannot be known at compilation time
 --> src/main.rs:7:13
  |
7 | fn other_fn(x: str) {
  |             ^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `str`
help: function arguments must have a statically known size, borrowed types always have a known size
  |
7 | fn other_fn(x: &str) {
  |                +

Desired output

error[E0SOME_DEDICATED_ERROR_CODE]: cannot assign a value of type `str` because it does not have a size known at compile time
 --> src/main.rs:4:5
  |
4 |     *a = *b;
  |     ^^ doesn't have a size known at compile time
  |
  = note: the assignment operator can only be used with values of a statically known size, which implement `Sized`
  = note: the trait `Sized` is not implemented for `str`
  = help: consider assigning to a `String` or `&str` instead of `str`

error[E0SOME_DEDICATED_ERROR_CODE]: a value of type `str` cannot be a function argument because it does not have a size known at compile time
 --> src/main.rs:7:13
  |
7 | fn other_fn(x: str) {
  |             ^ doesn't have a size known at compile-time
  |
  = note: function arguments must have a statically known size; they must implement `Sized`
  = note: the trait `Sized` is not implemented for `str`
help: consider passing the argument by reference:
  |
7 | fn other_fn(x: &str) {
  |                +

Rationale and extra context

Beginners are frequently confused by this error; I believe this most often results in asking the question “how do I implement Sized”. As I see it, there are several problems with the error text:

  • E0277 is the general “trait not implemented” error code. But teaching users about trait implementations in general is not helpful here, because users cannot implement Sized. (It might be relevant if the type in question is a generic parameter, in which case adding a bound would be useful.) And, it would be a good time to introduce the specific idea of dynamically sized types.
  • The specific problem in the first case, that an assignment must be of a Sized type, is left down at the fourth part of the message; until they get there, the user cannot see what the error has to do with what they are trying to do.
  • The existing message for the assignment doesn't give actionable advice, but could, by mentioning the common Sized containers for !Sized types.
  • The existing message for the function declaration, “help: function arguments must…”, is making a suggestion, but it isn't phrased to make it clear it's making a suggestion

Rust Version

Stable 1.81.0 (playground)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-error-codesArea: Explanation of an error code (--explain)D-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-libsRelevant to the library 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