Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<Default>::default() makes the compiler very mad at me #51077

Open
scottmcm opened this issue May 26, 2018 · 11 comments
Open

<Default>::default() makes the compiler very mad at me #51077

scottmcm opened this issue May 26, 2018 · 11 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-frontend Area: Compiler frontend (errors, parsing and HIR) A-traits Area: Trait system C-feature-request Category: A feature request, i.e: not implemented / a PR. D-verbose Diagnostics: Too much output caused by a single piece of incorrect code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics

Comments

@scottmcm
Copy link
Member

Suppose I learned

If I combine those two things together and try

let x: u32 = <Default>::default();

Then I get this spew of errors:

error[E0277]: the trait bound `std::default::Default: std::default::Default` is not satisfied
 --> src/main.rs:2:18
  |
2 |     let x: u32 = <Default>::default();
  |                  ^^^^^^^^^^^^^^^^^^ the trait `std::default::Default` is not implemented for `std::default::Default`
  |
  = note: required by `std::default::Default::default`

error[E0038]: the trait `std::default::Default` cannot be made into an object
 --> src/main.rs:2:19
  |
2 |     let x: u32 = <Default>::default();
  |                   ^^^^^^^ the trait `std::default::Default` cannot be made into an object
  |
  = note: the trait cannot require that `Self : Sized`

error[E0308]: mismatched types
 --> src/main.rs:2:18
  |
2 |     let x: u32 = <Default>::default();
  |                  ^^^^^^^^^^^^^^^^^^^^ expected u32, found trait std::default::Default
  |
  = note: expected type `u32`
             found type `std::default::Default`

error[E0038]: the trait `std::default::Default` cannot be made into an object
 --> src/main.rs:2:18
  |
2 |     let x: u32 = <Default>::default();
  |                  ^^^^^^^^^^^^^^^^^^^^ the trait `std::default::Default` cannot be made into an object
  |
  = note: the trait cannot require that `Self : Sized`

error: aborting due to 4 previous errors

Some errors occurred: E0038, E0277, E0308.
For more information about an error, try `rustc --explain E0038`.

I don't know what I'm concretely asking for here (please retitle better), so here are some thoughts:

  • The second error is the valuable one here
  • "found trait std::default::Default" should perhaps be "found trait object std::default::Default"?
  • Maybe this all will just work in Rust 2021 when <Default> can mean Default, not dyn Default>...
@Centril Centril added A-frontend Area: Compiler frontend (errors, parsing and HIR) A-diagnostics Area: Messages for errors, warnings, and lints C-feature-request Category: A feature request, i.e: not implemented / a PR. WG-diagnostics Working group: Diagnostics labels May 26, 2018
@eddyb
Copy link
Member

eddyb commented May 26, 2018

This can't work, as <T>::name syntax requires T to be a type, so at best in the future it will complain about Default not having dyn before it. Also, we should print the type as dyn Default.

That is, Foo::bar means two different things depending on whether Foo is a type or a trait:

  • if Foo is a type, it means <Foo>::bar which may further mean <Foo as Trait>::bar
  • if Foo is a trait, it means <_ as Foo>::Bar, which is different from </*dyn*/ Foo>::bar

@Centril
Copy link
Contributor

Centril commented May 26, 2018

@eddyb I think what Scott is saying is that you could also have a new rule in 2021 that given <Foo>::name, if Foo is a trait, it means <_ as Foo>::name.

That said, the first error message above is pretty darn confusing and we should do something about it now.

@eddyb
Copy link
Member

eddyb commented May 26, 2018

@Centril I disagree on the grounds of <T>::name being "type-qualified path syntax" and putting a trait path in the slot for T muddling those waters, but I can see how it would work grammar-wise.

@Centril
Copy link
Contributor

Centril commented May 26, 2018

@eddyb sure; whether that's desirable is entirely separate from the technical feasibility :) I'm not sure where I stand on desirability at this point.

@scottmcm
Copy link
Member Author

scottmcm commented Jun 3, 2018

This can't work, as ::name syntax requires T to be a type

Yes, I agree. I did figure out that was what was happening, but it's not incredibly obvious, so I wanted to file something about it. (For example, it's not obvious to me why it must be a type specifically, rather than something in the type namespace. My mental model had been that it just flipped the parser into type-namespace-mode, so no turbofish needed, etc, but apparently that's insufficient.)

@eddyb
Copy link
Member

eddyb commented Jun 4, 2018

@scottmcm It doesn't do anything to paths, instead it fully contains some arbitrary type.
The primary intention was to use it types that are not paths, e.g. <*const _>::is_null.
That is, the extra <...> permit containing the entire type syntax directly with no other special-cases.

@steveklabnik
Copy link
Member

Trying this today gives a slightly better, but still not great error:

   Compiling playground v0.0.1 (/playground)
warning: trait objects without an explicit `dyn` are deprecated
 --> src/main.rs:4:15
  |
4 | let x: u32 = <Default>::default();
  |               ^^^^^^^ help: use `dyn`: `dyn Default`
  |
  = note: #[warn(bare_trait_objects)] on by default

error[E0277]: the size for values of type `dyn std::default::Default` cannot be known at compilation time
 --> src/main.rs:4:14
  |
4 | let x: u32 = <Default>::default();
  |              ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `dyn std::default::Default`
  = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
  = note: required by `std::default::Default::default`

error[E0038]: the trait `std::default::Default` cannot be made into an object
 --> src/main.rs:4:15
  |
4 | let x: u32 = <Default>::default();
  |               ^^^^^^^ the trait `std::default::Default` cannot be made into an object
  |
  = note: the trait cannot require that `Self : Sized`

error[E0308]: mismatched types
 --> src/main.rs:4:14
  |
4 | let x: u32 = <Default>::default();
  |              ^^^^^^^^^^^^^^^^^^^^ expected u32, found trait std::default::Default
  |
  = note: expected type `u32`
             found type `dyn std::default::Default`

error[E0038]: the trait `std::default::Default` cannot be made into an object
 --> src/main.rs:4:14
  |
4 | let x: u32 = <Default>::default();
  |              ^^^^^^^^^^^^^^^^^^^^ the trait `std::default::Default` cannot be made into an object
  |
  = note: the trait cannot require that `Self : Sized`

error: aborting due to 4 previous errors

@eddyb
Copy link
Member

eddyb commented Sep 28, 2019

At the very least, this part is still misleading: expected u32, found trait std::default::Default.
I think the only part that improved is:

  = note: expected type `u32`
             found type `dyn std::default::Default`

@estebank estebank added D-verbose Diagnostics: Too much output caused by a single piece of incorrect code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-traits Area: Trait system labels Jan 22, 2020
@estebank
Copy link
Contributor

Current output:

error[E0038]: the trait `Default` cannot be made into an object
 --> src/main.rs:2:19
  |
2 |     let x: u32 = <dyn Default>::default();
  |                   ^^^^^^^^^^^ `Default` cannot be made into an object
  |
  = note: the trait cannot be made into an object because it requires `Self: Sized`
  = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

error[E0277]: the size for values of type `dyn Default` cannot be known at compilation time
   --> src/main.rs:2:19
    |
2   |     let x: u32 = <dyn Default>::default();
    |                   ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `dyn Default`
note: required by a bound in `default`
   --> /playground/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/default.rs:106:20
    |
106 | pub trait Default: Sized {
    |                    ^^^^^ required by this bound in `Default::default`
...
138 |     fn default() -> Self;
    |        ------- required by a bound in this associated function

error[E0308]: mismatched types
 --> src/main.rs:2:18
  |
2 |     let x: u32 = <dyn Default>::default();
  |            ---   ^^^^^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `dyn Default`
  |            |
  |            expected due to this
  |
  = note:      expected type `u32`
          found trait object `dyn Default`
  = help: `u32` implements `Default` so you could change the expected type to `Box<dyn Default>`

error[E0038]: the trait `Default` cannot be made into an object
 --> src/main.rs:2:18
  |
2 |     let x: u32 = <dyn Default>::default();
  |                  ^^^^^^^^^^^^^^^^^^^^^^^^ `Default` cannot be made into an object
  |
  = note: the trait cannot be made into an object because it requires `Self: Sized`
  = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

error[E0277]: the size for values of type `dyn Default` cannot be known at compilation time
 --> src/main.rs:2:18
  |
2 |     let x: u32 = <dyn Default>::default();
  |                  ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `dyn Default`
  = note: the return type of a function must have a statically known size

The E0038 and E0277 errors both say the same thing (Self: !Sized) so one should silence the other. That would bring the error count from 5 to 3. If we could tie the dyn Default failure to the <dyn Default>::default() one, we could bring the error count down to 2. Finally, we could mark the expression type to be {type error} to avoid the E0308, leaving just 1 error left.

@scottmcm
Copy link
Member Author

let x: u32 = <dyn Default>::default();

Note that I wasn't actually trying to use dyn here, so I don't know why the output shows that.

I think it's possible that the root issue might be things turning Default into dyn Default too early -- at least in new editions we don't need to do that, and I think it'd be better not to assume that's what was meant. Giving a "hey, we don't know if you meant impl Default or dyn Default" when seeing a trait in type position might avoid going down this garden path in the first place.

@estebank
Copy link
Contributor

Note that I wasn't actually trying to use dyn here, so I don't know why the output shows that.

I'd added it to the playground to see the other errors without the "you must use dyn here". The "bad trait use" should also check whether we're in an item body or not, and propose using impl Trait besides dyn Trait. And we should "poison" the node's type with {type error} whenever we encounter a bare dyn Trait, in general.

estebank added a commit to estebank/rust that referenced this issue May 30, 2024
Address rust-lang#51077 in editions>=2021 by treating `<Trait>` as a `<{type error}>` instead of `<dyn Trait>`, silencing subsequent errors. We new emit a single error ("missing `dyn`").

```
error[E0782]: trait objects must include the `dyn` keyword
 --> f800.rs:2:15
  |
2 | let x: u32 = <Default>::default();
  |               ^^^^^^^
  |
help: add `dyn` keyword before this trait
  |
2 | let x: u32 = <dyn Default>::default();
  |               +++
```

instead of 6

```
error[E0782]: trait objects must include the `dyn` keyword
 --> f800.rs:2:15
  |
2 | let x: u32 = <Default>::default();
  |               ^^^^^^^
  |
help: add `dyn` keyword before this trait
  |
2 | let x: u32 = <dyn Default>::default();
  |               +++

error[E0038]: the trait `Default` cannot be made into an object
 --> f800.rs:2:15
  |
2 | let x: u32 = <Default>::default();
  |               ^^^^^^^ `Default` cannot be made into an object
  |
  = note: the trait cannot be made into an object because it requires `Self: Sized`
  = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

error[E0277]: the size for values of type `dyn Default` cannot be known at compilation time
   --> f800.rs:2:15
    |
2   | let x: u32 = <Default>::default();
    |               ^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `dyn Default`
note: required by a bound in `default`
   --> /home/gh-estebank/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/default.rs:104:20
    |
104 | pub trait Default: Sized {
    |                    ^^^^^ required by this bound in `Default::default`
...
136 |     fn default() -> Self;
    |        ------- required by a bound in this associated function

error[E0308]: mismatched types
 --> f800.rs:2:14
  |
2 | let x: u32 = <Default>::default();
  |        ---   ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `dyn Default`
  |        |
  |        expected due to this
  |
  = note:      expected type `u32`
          found trait object `dyn Default`
  = help: `u32` implements `Default` so you could change the expected type to `Box<dyn Default>`

error[E0038]: the trait `Default` cannot be made into an object
 --> f800.rs:2:14
  |
2 | let x: u32 = <Default>::default();
  |              ^^^^^^^^^^^^^^^^^^^^ `Default` cannot be made into an object
  |
  = note: the trait cannot be made into an object because it requires `Self: Sized`
  = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

error[E0277]: the size for values of type `dyn Default` cannot be known at compilation time
 --> f800.rs:2:14
  |
2 | let x: u32 = <Default>::default();
  |              ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `dyn Default`
  = note: the return type of a function must have a statically known size
```
estebank added a commit to estebank/rust that referenced this issue Jun 9, 2024
Address rust-lang#51077 in editions>=2021 by treating `<Trait>` as a `<{type error}>` instead of `<dyn Trait>`, silencing subsequent errors. We new emit a single error ("missing `dyn`").

```
error[E0782]: trait objects must include the `dyn` keyword
 --> f800.rs:2:15
  |
2 | let x: u32 = <Default>::default();
  |               ^^^^^^^
  |
help: add `dyn` keyword before this trait
  |
2 | let x: u32 = <dyn Default>::default();
  |               +++
```

instead of 6

```
error[E0782]: trait objects must include the `dyn` keyword
 --> f800.rs:2:15
  |
2 | let x: u32 = <Default>::default();
  |               ^^^^^^^
  |
help: add `dyn` keyword before this trait
  |
2 | let x: u32 = <dyn Default>::default();
  |               +++

error[E0038]: the trait `Default` cannot be made into an object
 --> f800.rs:2:15
  |
2 | let x: u32 = <Default>::default();
  |               ^^^^^^^ `Default` cannot be made into an object
  |
  = note: the trait cannot be made into an object because it requires `Self: Sized`
  = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

error[E0277]: the size for values of type `dyn Default` cannot be known at compilation time
   --> f800.rs:2:15
    |
2   | let x: u32 = <Default>::default();
    |               ^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `dyn Default`
note: required by a bound in `default`
   --> /home/gh-estebank/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/default.rs:104:20
    |
104 | pub trait Default: Sized {
    |                    ^^^^^ required by this bound in `Default::default`
...
136 |     fn default() -> Self;
    |        ------- required by a bound in this associated function

error[E0308]: mismatched types
 --> f800.rs:2:14
  |
2 | let x: u32 = <Default>::default();
  |        ---   ^^^^^^^^^^^^^^^^^^^^ expected `u32`, found `dyn Default`
  |        |
  |        expected due to this
  |
  = note:      expected type `u32`
          found trait object `dyn Default`
  = help: `u32` implements `Default` so you could change the expected type to `Box<dyn Default>`

error[E0038]: the trait `Default` cannot be made into an object
 --> f800.rs:2:14
  |
2 | let x: u32 = <Default>::default();
  |              ^^^^^^^^^^^^^^^^^^^^ `Default` cannot be made into an object
  |
  = note: the trait cannot be made into an object because it requires `Self: Sized`
  = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>

error[E0277]: the size for values of type `dyn Default` cannot be known at compilation time
 --> f800.rs:2:14
  |
2 | let x: u32 = <Default>::default();
  |              ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
  |
  = help: the trait `Sized` is not implemented for `dyn Default`
  = note: the return type of a function must have a statically known size
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-frontend Area: Compiler frontend (errors, parsing and HIR) A-traits Area: Trait system C-feature-request Category: A feature request, i.e: not implemented / a PR. D-verbose Diagnostics: Too much output caused by a single piece of incorrect code. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics
Projects
None yet
Development

No branches or pull requests

5 participants