Auto merge of #77087 - estebank:issue-45817, r=matthewjasper

Provide structured suggestions when finding structs when expecting a trait

When finding an ADT in a trait object definition provide some solutions. Fix #45817.
Given `<Param as Trait>::Assoc: Ty` suggest `Param: Trait<Assoc = Ty>`. Fix #75829.
This commit is contained in:
bors 2020-10-10 23:27:28 +00:00
commit 08764ad163
7 changed files with 524 additions and 23 deletions

View file

@ -0,0 +1,19 @@
trait Bar {
type Baz;
}
struct Foo<T> where T: Bar, <T as Bar>::Baz: String { //~ ERROR expected trait, found struct
t: T,
}
struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found struct
t: &'a T,
}
fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String { //~ ERROR expected trait, found struct
}
fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { //~ ERROR expected trait, found
}
fn main() {}

View file

@ -0,0 +1,83 @@
error[E0404]: expected trait, found struct `String`
--> $DIR/assoc_type_bound_with_struct.rs:5:46
|
LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: String {
| ^^^^^^ not a trait
|
::: $SRC_DIR/alloc/src/string.rs:LL:COL
|
LL | pub trait ToString {
| ------------------ similarly named trait `ToString` defined here
|
help: constrain the associated type to `String`
|
LL | struct Foo<T> where T: Bar, T: Bar<Baz = String> {
| ^^^^^^^^^^^^^^^^^^^^
help: a trait with a similar name exists
|
LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: ToString {
| ^^^^^^^^
error[E0404]: expected trait, found struct `String`
--> $DIR/assoc_type_bound_with_struct.rs:9:54
|
LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String {
| ^^^^^^ not a trait
|
::: $SRC_DIR/alloc/src/string.rs:LL:COL
|
LL | pub trait ToString {
| ------------------ similarly named trait `ToString` defined here
|
help: constrain the associated type to `String`
|
LL | struct Qux<'a, T> where T: Bar, &'a T: Bar<Baz = String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: a trait with a similar name exists
|
LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: ToString {
| ^^^^^^^^
error[E0404]: expected trait, found struct `String`
--> $DIR/assoc_type_bound_with_struct.rs:13:45
|
LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String {
| ^^^^^^ not a trait
|
::: $SRC_DIR/alloc/src/string.rs:LL:COL
|
LL | pub trait ToString {
| ------------------ similarly named trait `ToString` defined here
|
help: constrain the associated type to `String`
|
LL | fn foo<T: Bar>(_: T) where T: Bar<Baz = String> {
| ^^^^^^^^^^^^^^^^^^^^
help: a trait with a similar name exists
|
LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: ToString {
| ^^^^^^^^
error[E0404]: expected trait, found struct `String`
--> $DIR/assoc_type_bound_with_struct.rs:16:57
|
LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String {
| ^^^^^^ not a trait
|
::: $SRC_DIR/alloc/src/string.rs:LL:COL
|
LL | pub trait ToString {
| ------------------ similarly named trait `ToString` defined here
|
help: constrain the associated type to `String`
|
LL | fn qux<'a, T: Bar>(_: &'a T) where &'a T: Bar<Baz = String> {
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: a trait with a similar name exists
|
LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString {
| ^^^^^^^^
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0404`.

View file

@ -1,9 +1,38 @@
// We don't need those errors. Ideally we would silence them, but to do so we need to move the
// lint from being an early-lint during parsing to a late-lint, because it needs to be aware of
// the types involved.
#![allow(bare_trait_objects)]
struct Foo;
fn foo(_x: Box<Foo + Send>) { } //~ ERROR expected trait, found struct `Foo`
type A<T> = Box<dyn Vec<T>>; //~ ERROR expected trait, found struct `Vec`
type TypeAlias<T> = Box<dyn Vec<T>>; //~ ERROR expected trait, found struct `Vec`
fn main() { }
struct A;
fn a() -> A + 'static { //~ ERROR expected trait, found
A
}
fn b<'a,T,E>(iter: Iterator<Item=Result<T,E> + 'a>) { //~ ERROR expected trait, found
panic!()
}
fn c() -> 'static + A { //~ ERROR expected trait, found
A
}
fn d<'a,T,E>(iter: Iterator<Item='a + Result<T,E>>) { //~ ERROR expected trait, found
panic!()
}
fn e() -> 'static + A + 'static { //~ ERROR expected trait, found
//~^ ERROR only a single explicit lifetime bound is permitted
A
}
fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) { //~ ERROR expected trait, found
//~^ ERROR only a single explicit lifetime bound is permitted
panic!()
}
struct Traitor;
trait Trait {}
fn g() -> Traitor + 'static { //~ ERROR expected trait, found struct `Traitor`
A
}
fn main() {}

View file

@ -1,15 +1,168 @@
error[E0226]: only a single explicit lifetime bound is permitted
--> $DIR/trait-bounds-not-on-struct.rs:25:25
|
LL | fn e() -> 'static + A + 'static {
| ^^^^^^^
error[E0226]: only a single explicit lifetime bound is permitted
--> $DIR/trait-bounds-not-on-struct.rs:29:53
|
LL | fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) {
| ^^
error[E0404]: expected trait, found struct `Foo`
--> $DIR/trait-bounds-not-on-struct.rs:5:16
--> $DIR/trait-bounds-not-on-struct.rs:8:16
|
LL | fn foo(_x: Box<Foo + Send>) { }
| ^^^ not a trait
|
help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
--> $DIR/trait-bounds-not-on-struct.rs:8:22
|
LL | fn foo(_x: Box<Foo + Send>) { }
| --- ^^^^ ...because of this bound
| |
| expected this type to be a trait...
error[E0404]: expected trait, found struct `Vec`
--> $DIR/trait-bounds-not-on-struct.rs:7:21
--> $DIR/trait-bounds-not-on-struct.rs:10:29
|
LL | type A<T> = Box<dyn Vec<T>>;
| ^^^^^^ not a trait
LL | type TypeAlias<T> = Box<dyn Vec<T>>;
| ^^^^^^ not a trait
error: aborting due to 2 previous errors
error[E0404]: expected trait, found struct `A`
--> $DIR/trait-bounds-not-on-struct.rs:13:11
|
LL | fn a() -> A + 'static {
| ^ not a trait
|
help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
--> $DIR/trait-bounds-not-on-struct.rs:13:15
|
LL | fn a() -> A + 'static {
| - ^^^^^^^ ...because of this bound
| |
| expected this type to be a trait...
help: if you meant to use a type and not a trait here, remove the bounds
|
LL | fn a() -> A {
| --
For more information about this error, try `rustc --explain E0404`.
error[E0404]: expected trait, found enum `Result`
--> $DIR/trait-bounds-not-on-struct.rs:16:34
|
LL | fn b<'a,T,E>(iter: Iterator<Item=Result<T,E> + 'a>) {
| ^^^^^^^^^^^ not a trait
|
help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
--> $DIR/trait-bounds-not-on-struct.rs:16:48
|
LL | fn b<'a,T,E>(iter: Iterator<Item=Result<T,E> + 'a>) {
| ----------- ^^ ...because of this bound
| |
| expected this type to be a trait...
help: if you meant to use a type and not a trait here, remove the bounds
|
LL | fn b<'a,T,E>(iter: Iterator<Item=Result<T,E>>) {
| --
error[E0404]: expected trait, found struct `A`
--> $DIR/trait-bounds-not-on-struct.rs:19:21
|
LL | fn c() -> 'static + A {
| ^ not a trait
|
help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
--> $DIR/trait-bounds-not-on-struct.rs:19:11
|
LL | fn c() -> 'static + A {
| ^^^^^^^ - expected this type to be a trait...
| |
| ...because of this bound
help: if you meant to use a type and not a trait here, remove the bounds
|
LL | fn c() -> A {
| --
error[E0404]: expected trait, found enum `Result`
--> $DIR/trait-bounds-not-on-struct.rs:22:39
|
LL | fn d<'a,T,E>(iter: Iterator<Item='a + Result<T,E>>) {
| ^^^^^^^^^^^ not a trait
|
help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
--> $DIR/trait-bounds-not-on-struct.rs:22:34
|
LL | fn d<'a,T,E>(iter: Iterator<Item='a + Result<T,E>>) {
| ^^ ----------- expected this type to be a trait...
| |
| ...because of this bound
help: if you meant to use a type and not a trait here, remove the bounds
|
LL | fn d<'a,T,E>(iter: Iterator<Item=Result<T,E>>) {
| --
error[E0404]: expected trait, found struct `A`
--> $DIR/trait-bounds-not-on-struct.rs:25:21
|
LL | fn e() -> 'static + A + 'static {
| ^ not a trait
|
help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
--> $DIR/trait-bounds-not-on-struct.rs:25:11
|
LL | fn e() -> 'static + A + 'static {
| ^^^^^^^ - ^^^^^^^ ...because of these bounds
| |
| expected this type to be a trait...
help: if you meant to use a type and not a trait here, remove the bounds
|
LL | fn e() -> A {
| ---
error[E0404]: expected trait, found enum `Result`
--> $DIR/trait-bounds-not-on-struct.rs:29:39
|
LL | fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) {
| ^^^^^^^^^^^ not a trait
|
help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
--> $DIR/trait-bounds-not-on-struct.rs:29:34
|
LL | fn f<'a,T,E>(iter: Iterator<Item='a + Result<T,E> + 'a>) {
| ^^ ----------- ^^ ...because of these bounds
| |
| expected this type to be a trait...
help: if you meant to use a type and not a trait here, remove the bounds
|
LL | fn f<'a,T,E>(iter: Iterator<Item=Result<T,E>>) {
| -- --
error[E0404]: expected trait, found struct `Traitor`
--> $DIR/trait-bounds-not-on-struct.rs:35:11
|
LL | trait Trait {}
| ----------- similarly named trait `Trait` defined here
LL | fn g() -> Traitor + 'static {
| ^^^^^^^ not a trait
|
help: `+` is used to constrain a "trait object" type with lifetimes or auto-traits; structs and enums can't be bound in that way
--> $DIR/trait-bounds-not-on-struct.rs:35:21
|
LL | fn g() -> Traitor + 'static {
| ------- ^^^^^^^ ...because of this bound
| |
| expected this type to be a trait...
help: if you meant to use a type and not a trait here, remove the bounds
|
LL | fn g() -> Traitor {
| --
help: a trait with a similar name exists
|
LL | fn g() -> Trait + 'static {
| ^^^^^
error: aborting due to 11 previous errors
Some errors have detailed explanations: E0226, E0404.
For more information about an error, try `rustc --explain E0226`.