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

rustc suggests dyn SomeTrait for traits which aren't object safe #119525

Closed
Wilfred opened this issue Jan 2, 2024 · 1 comment · Fixed by #119148
Closed

rustc suggests dyn SomeTrait for traits which aren't object safe #119525

Wilfred opened this issue Jan 2, 2024 · 1 comment · Fixed by #119148
Assignees
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix`. A-trait-objects Area: trait objects, vtable layout T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Wilfred
Copy link
Contributor

Wilfred commented Jan 2, 2024

Code

fn ord_prefer_dot(s: &str) -> Ord {
    (s.starts_with("."), s)
}

Current output

error[E0038]: the trait `Ord` cannot be made into an object
   --> src/lib.rs:1:31
    |
1   | fn ord_prefer_dot(s: &str) -> Ord {
    |                               ^^^ `Ord` cannot be made into an object
    |
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>
   --> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/cmp.rs:305:15
    |
305 | pub trait Eq: PartialEq<Self> {
    |               ^^^^^^^^^^^^^^^ the trait cannot be made into an object because it uses `Self` as a type parameter
...
793 | pub trait Ord: Eq + PartialOrd<Self> {
    |                     ^^^^^^^^^^^^^^^^ the trait cannot be made into an object because it uses `Self` as a type parameter

error[E0782]: trait objects must include the `dyn` keyword
 --> src/lib.rs:1:31
  |
1 | fn ord_prefer_dot(s: &str) -> Ord {
  |                               ^^^
  |
help: add `dyn` keyword before this trait
  |
1 | fn ord_prefer_dot(s: &str) -> dyn Ord {
  |                               +++

Some errors have detailed explanations: E0038, E0782.
For more information about an error, try `rustc --explain E0038`.

Desired output

error[E0038]: the trait `Ord` cannot be made into an object
   --> src/lib.rs:1:31
    |
1   | fn ord_prefer_dot(s: &str) -> Ord {
    |                               ^^^ `Ord` cannot be made into an object
    |
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>
   --> /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/cmp.rs:305:15
    |
305 | pub trait Eq: PartialEq<Self> {
    |               ^^^^^^^^^^^^^^^ the trait cannot be made into an object because it uses `Self` as a type parameter
...
793 | pub trait Ord: Eq + PartialOrd<Self> {
    |                     ^^^^^^^^^^^^^^^^ the trait cannot be made into an object because it uses `Self` as a type parameter

help: add `impl` keyword before this trait
  |
1 | fn ord_prefer_dot(s: &str) -> impl Ord {
  |                               ++++

Rationale and extra context

In this case, a possible valid implementation would be:

fn ord_prefer_dot(s: &str) -> impl Ord + '_ {
    (s.starts_with("."), s)
}

It would be an improvement to not suggest dyn Ord, but ideally rustc would suggest impl Ord I think.

Other cases

No response

Anything else?

No response

@Wilfred Wilfred added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 2, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jan 2, 2024
@fmease
Copy link
Member

fmease commented Jan 3, 2024

As far as I can tell, #119148 would slightly help here by also suggesting impl Ord (next to Box<dyn Ord>).

@estebank, do you think you can tweak #119148 to prefer impl-Trait over dyn-Trait if !tcx.check_is_object_safe(def_id) (or in a follow-up PR)? Unless that extra query call would lead to cycles of course.

@fmease fmease added A-trait-objects Area: trait objects, vtable layout A-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix`. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Jan 3, 2024
@estebank estebank self-assigned this Jan 3, 2024
compiler-errors added a commit to compiler-errors/rust that referenced this issue Jan 5, 2024
Tweak suggestions for bare trait used as a type

```
error[E0782]: trait objects must include the `dyn` keyword
  --> $DIR/not-on-bare-trait-2021.rs:11:11
   |
LL | fn bar(x: Foo) -> Foo {
   |           ^^^
   |
help: use a generic type parameter, constrained by the trait `Foo`
   |
LL | fn bar<T: Foo>(x: T) -> Foo {
   |       ++++++++    ~
help: you can also use `impl Foo`, but users won't be able to specify the type paramer when calling the `fn`, having to rely exclusively on type inference
   |
LL | fn bar(x: impl Foo) -> Foo {
   |           ++++
help: alternatively, use a trait object to accept any type that implements `Foo`, accessing its methods at runtime using dynamic dispatch
   |
LL | fn bar(x: &dyn Foo) -> Foo {
   |           ++++

error[E0782]: trait objects must include the `dyn` keyword
  --> $DIR/not-on-bare-trait-2021.rs:11:19
   |
LL | fn bar(x: Foo) -> Foo {
   |                   ^^^
   |
help: use `impl Foo` to return an opaque type, as long as you return a single underlying type
   |
LL | fn bar(x: Foo) -> impl Foo {
   |                   ++++
help: alternatively, you can return an owned trait object
   |
LL | fn bar(x: Foo) -> Box<dyn Foo> {
   |                   +++++++    +
```

Fix rust-lang#119525:

```

error[E0038]: the trait `Ord` cannot be made into an object
  --> $DIR/bare-trait-dont-suggest-dyn.rs:3:33
   |
LL | fn ord_prefer_dot(s: String) -> Ord {
   |                                 ^^^ `Ord` cannot be made into an object
   |
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>
  --> $SRC_DIR/core/src/cmp.rs:LL:COL
   |
   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
   |
   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
help: consider using an opaque type instead
   |
LL | fn ord_prefer_dot(s: String) -> impl Ord {
   |                                 ++++
```
@bors bors closed this as completed in 78ef946 Jan 5, 2024
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Jan 5, 2024
Rollup merge of rust-lang#119148 - estebank:bare-traits, r=davidtwco

Tweak suggestions for bare trait used as a type

```
error[E0782]: trait objects must include the `dyn` keyword
  --> $DIR/not-on-bare-trait-2021.rs:11:11
   |
LL | fn bar(x: Foo) -> Foo {
   |           ^^^
   |
help: use a generic type parameter, constrained by the trait `Foo`
   |
LL | fn bar<T: Foo>(x: T) -> Foo {
   |       ++++++++    ~
help: you can also use `impl Foo`, but users won't be able to specify the type paramer when calling the `fn`, having to rely exclusively on type inference
   |
LL | fn bar(x: impl Foo) -> Foo {
   |           ++++
help: alternatively, use a trait object to accept any type that implements `Foo`, accessing its methods at runtime using dynamic dispatch
   |
LL | fn bar(x: &dyn Foo) -> Foo {
   |           ++++

error[E0782]: trait objects must include the `dyn` keyword
  --> $DIR/not-on-bare-trait-2021.rs:11:19
   |
LL | fn bar(x: Foo) -> Foo {
   |                   ^^^
   |
help: use `impl Foo` to return an opaque type, as long as you return a single underlying type
   |
LL | fn bar(x: Foo) -> impl Foo {
   |                   ++++
help: alternatively, you can return an owned trait object
   |
LL | fn bar(x: Foo) -> Box<dyn Foo> {
   |                   +++++++    +
```

Fix rust-lang#119525:

```

error[E0038]: the trait `Ord` cannot be made into an object
  --> $DIR/bare-trait-dont-suggest-dyn.rs:3:33
   |
LL | fn ord_prefer_dot(s: String) -> Ord {
   |                                 ^^^ `Ord` cannot be made into an object
   |
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>
  --> $SRC_DIR/core/src/cmp.rs:LL:COL
   |
   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
   |
   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
help: consider using an opaque type instead
   |
LL | fn ord_prefer_dot(s: String) -> impl Ord {
   |                                 ++++
```
flip1995 pushed a commit to flip1995/rust that referenced this issue Jan 11, 2024
Tweak suggestions for bare trait used as a type

```
error[E0782]: trait objects must include the `dyn` keyword
  --> $DIR/not-on-bare-trait-2021.rs:11:11
   |
LL | fn bar(x: Foo) -> Foo {
   |           ^^^
   |
help: use a generic type parameter, constrained by the trait `Foo`
   |
LL | fn bar<T: Foo>(x: T) -> Foo {
   |       ++++++++    ~
help: you can also use `impl Foo`, but users won't be able to specify the type paramer when calling the `fn`, having to rely exclusively on type inference
   |
LL | fn bar(x: impl Foo) -> Foo {
   |           ++++
help: alternatively, use a trait object to accept any type that implements `Foo`, accessing its methods at runtime using dynamic dispatch
   |
LL | fn bar(x: &dyn Foo) -> Foo {
   |           ++++

error[E0782]: trait objects must include the `dyn` keyword
  --> $DIR/not-on-bare-trait-2021.rs:11:19
   |
LL | fn bar(x: Foo) -> Foo {
   |                   ^^^
   |
help: use `impl Foo` to return an opaque type, as long as you return a single underlying type
   |
LL | fn bar(x: Foo) -> impl Foo {
   |                   ++++
help: alternatively, you can return an owned trait object
   |
LL | fn bar(x: Foo) -> Box<dyn Foo> {
   |                   +++++++    +
```

Fix rust-lang#119525:

```

error[E0038]: the trait `Ord` cannot be made into an object
  --> $DIR/bare-trait-dont-suggest-dyn.rs:3:33
   |
LL | fn ord_prefer_dot(s: String) -> Ord {
   |                                 ^^^ `Ord` cannot be made into an object
   |
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>
  --> $SRC_DIR/core/src/cmp.rs:LL:COL
   |
   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
  ::: $SRC_DIR/core/src/cmp.rs:LL:COL
   |
   = note: the trait cannot be made into an object because it uses `Self` as a type parameter
help: consider using an opaque type instead
   |
LL | fn ord_prefer_dot(s: String) -> impl Ord {
   |                                 ++++
```
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-suggestion-diagnostics Area: Suggestions generated by the compiler applied by `cargo fix`. A-trait-objects Area: trait objects, vtable layout T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants