Skip to content

Suboptimal diagnostics when trying to create a trait object for a trait with GATs #103155

Closed

Description

Given the following code (playground 1):

trait Foo {
    type Bar<T>;
}

fn bar(x: &dyn Foo) {}

The current output is:

error[E0191]: the value of the associated type `Bar` (from trait `Foo`) must be specified
 --> src/lib.rs:5:16
  |
2 |     type Bar<T>;
  |     ----------- `Bar` defined here
...
5 | fn bar(x: &dyn Foo) {}
  |                ^^^ help: specify the associated type: `Foo<Bar = Type>`

Following this suggestion (playground 2)...

trait Foo {
    type Bar<T>;
}

fn bar(x: &dyn Foo<Bar = i32>) {}

... produces another diagnostic:

error[E0107]: missing generics for associated type `Foo::Bar`
 --> src/lib.rs:5:20
  |
5 | fn bar(x: &dyn Foo<Bar = i32>) {}
  |                    ^^^ expected 1 generic argument
  |
note: associated type defined here, with 1 generic parameter: `T`
 --> src/lib.rs:2:10
  |
2 |     type Bar<T>;
  |          ^^^ -
help: add missing generic argument
  |
5 | fn bar(x: &dyn Foo<Bar<T> = i32>) {}
  |                    ~~~~~~

Finally, specifying the generic argument for Bar (playground 3)...

trait Foo {
    type Bar<T>;
}

fn bar(x: &dyn Foo<Bar<i32> = i32>) {}

... reveals that our struggle was all for naught:

error[E0038]: the trait `Foo` cannot be made into an object
 --> src/lib.rs:5:12
  |
5 | fn bar(x: &dyn Foo<Bar<i32> = i32>) {}
  |            ^^^^^^^^^^^^^^^^^^^^^^^ `Foo` 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/lib.rs:2:10
  |
1 | trait Foo {
  |       --- this trait cannot be made into an object...
2 |     type Bar<T>;
  |          ^^^ ...because it contains the generic associated type `Bar`
  = help: consider moving `Bar` to another trait

Ideally, the first snippet should produce an object safety error right away:

error[E0038]: the trait `Foo` cannot be made into an object
 --> src/lib.rs:5:12
  |
5 | fn bar(x: &dyn Foo) {}
  |            ^^^^^^^ `Foo` 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/lib.rs:2:10
  |
1 | trait Foo {
  |       --- this trait cannot be made into an object...
2 |     type Bar<T>;
  |          ^^^ ...because it contains the generic associated type `Bar`
  = help: consider moving `Bar` to another trait

In case #![feature(generic_associated_types_extended)] is enabled, E0191 should still be emitted, but the suggestion should include the generic argument for Bar:

error[E0191]: the value of the associated type `Bar` (from trait `Foo`) must be specified
 --> src/lib.rs:5:16
  |
2 |     type Bar<T>;
  |     ----------- `Bar` defined here
...
5 | fn bar(x: &dyn Foo) {}
  |                ^^^ help: specify the associated type: `Foo<Bar<T> = Type>`

@rustbot modify labels +D-terse +F-generic_associated_types

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    A-GATsArea: Generic associated types (GATs)A-diagnosticsArea: Messages for errors, warnings, and lintsD-terseDiagnostics: An error or lint that doesn't give enough information about the problem at hand.F-generic_associated_types`#![feature(generic_associated_types)]` a.k.a. GATsT-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