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:
commit
08764ad163
7 changed files with 524 additions and 23 deletions
19
src/test/ui/traits/assoc_type_bound_with_struct.rs
Normal file
19
src/test/ui/traits/assoc_type_bound_with_struct.rs
Normal 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() {}
|
||||
83
src/test/ui/traits/assoc_type_bound_with_struct.stderr
Normal file
83
src/test/ui/traits/assoc_type_bound_with_struct.stderr
Normal 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`.
|
||||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue