Auto merge of #83729 - JohnTitor:issue-43913, r=estebank
Add a suggestion when using a type alias instead of trait alias Fixes #43913 r? `@estebank`
This commit is contained in:
commit
8ad0821b03
@ -8,14 +8,15 @@ struct Foo;
|
|||||||
struct Bar;
|
struct Bar;
|
||||||
|
|
||||||
impl Foo for Bar {} // error: `Foo` is not a trait
|
impl Foo for Bar {} // error: `Foo` is not a trait
|
||||||
|
fn baz<T: Foo>(t: T) {} // error: `Foo` is not a trait
|
||||||
```
|
```
|
||||||
|
|
||||||
Another erroneous code example:
|
Another erroneous code example:
|
||||||
|
|
||||||
```compile_fail,E0404
|
```compile_fail,E0404
|
||||||
struct Foo;
|
type Foo = Iterator<Item=String>;
|
||||||
|
|
||||||
fn bar<T: Foo>(t: T) {} // error: `Foo` is not a trait
|
fn bar<T: Foo>(t: T) {} // error: `Foo` is a type alias
|
||||||
```
|
```
|
||||||
|
|
||||||
Please verify that the trait's name was not misspelled or that the right
|
Please verify that the trait's name was not misspelled or that the right
|
||||||
@ -30,14 +31,27 @@ struct Bar;
|
|||||||
impl Foo for Bar { // ok!
|
impl Foo for Bar { // ok!
|
||||||
// functions implementation
|
// functions implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn baz<T: Foo>(t: T) {} // ok!
|
||||||
```
|
```
|
||||||
|
|
||||||
or:
|
Alternatively, you could introduce a new trait with your desired restrictions
|
||||||
|
as a super trait:
|
||||||
|
|
||||||
```
|
```
|
||||||
trait Foo {
|
# trait Foo {}
|
||||||
// some functions
|
# struct Bar;
|
||||||
}
|
# impl Foo for Bar {}
|
||||||
|
trait Qux: Foo {} // Anything that implements Qux also needs to implement Foo
|
||||||
|
fn baz<T: Qux>(t: T) {} // also ok!
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, if you are on nightly and want to use a trait alias
|
||||||
|
instead of a type alias, you should use `#![feature(trait_alias)]`:
|
||||||
|
|
||||||
|
```
|
||||||
|
#![feature(trait_alias)]
|
||||||
|
trait Foo = Iterator<Item=String>;
|
||||||
|
|
||||||
fn bar<T: Foo>(t: T) {} // ok!
|
fn bar<T: Foo>(t: T) {} // ok!
|
||||||
```
|
```
|
||||||
|
@ -930,7 +930,14 @@ fn smart_resolve_context_dependent_help(
|
|||||||
let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
|
let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
|
||||||
`type` alias";
|
`type` alias";
|
||||||
if let Some(span) = self.def_span(def_id) {
|
if let Some(span) = self.def_span(def_id) {
|
||||||
err.span_help(span, msg);
|
if let Ok(snip) = self.r.session.source_map().span_to_snippet(span) {
|
||||||
|
// The span contains a type alias so we should be able to
|
||||||
|
// replace `type` with `trait`.
|
||||||
|
let snip = snip.replacen("type", "trait", 1);
|
||||||
|
err.span_suggestion(span, msg, snip, Applicability::MaybeIncorrect);
|
||||||
|
} else {
|
||||||
|
err.span_help(span, msg);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err.help(msg);
|
err.help(msg);
|
||||||
}
|
}
|
||||||
|
@ -5,10 +5,9 @@ LL | impl Bar for Baz { }
|
|||||||
| ^^^ type aliases cannot be used as traits
|
| ^^^ type aliases cannot be used as traits
|
||||||
|
|
|
|
||||||
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
|
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
|
||||||
--> $DIR/two_files_data.rs:5:1
|
|
||||||
|
|
|
|
||||||
LL | type Bar = dyn Foo;
|
LL | trait Bar = dyn Foo;
|
||||||
| ^^^^^^^^^^^^^^^^^^^
|
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -5,10 +5,9 @@ LL | impl Foo for S {
|
|||||||
| ^^^ type aliases cannot be used as traits
|
| ^^^ type aliases cannot be used as traits
|
||||||
|
|
|
|
||||||
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
|
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
|
||||||
--> $DIR/issue-3907.rs:5:1
|
|
||||||
|
|
|
|
||||||
LL | type Foo = dyn issue_3907::Foo;
|
LL | trait Foo = dyn issue_3907::Foo;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
||||||
help: consider importing this trait instead
|
help: consider importing this trait instead
|
||||||
|
|
|
|
||||||
LL | use issue_3907::Foo;
|
LL | use issue_3907::Foo;
|
||||||
|
@ -11,16 +11,16 @@ LL | trait I {}
|
|||||||
| ------- similarly named trait `I` defined here
|
| ------- similarly named trait `I` defined here
|
||||||
LL | type K = dyn I;
|
LL | type K = dyn I;
|
||||||
LL | impl K for isize {}
|
LL | impl K for isize {}
|
||||||
| ^
|
| ^ type aliases cannot be used as traits
|
||||||
| |
|
|
||||||
| type aliases cannot be used as traits
|
|
||||||
| help: a trait with a similar name exists: `I`
|
|
||||||
|
|
|
|
||||||
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
|
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
|
||||||
--> $DIR/issue-5035.rs:2:1
|
|
||||||
|
|
|
|
||||||
LL | type K = dyn I;
|
LL | trait K = dyn I;
|
||||||
| ^^^^^^^^^^^^^^^
|
|
|
||||||
|
help: a trait with a similar name exists
|
||||||
|
|
|
||||||
|
LL | impl I for isize {}
|
||||||
|
| ^
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -11,10 +11,9 @@ LL | fn g<F:Typedef(isize) -> isize>(x: F) {}
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used as traits
|
| ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used as traits
|
||||||
|
|
|
|
||||||
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
|
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
|
||||||
--> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:4:1
|
|
||||||
|
|
|
|
||||||
LL | type Typedef = isize;
|
LL | trait Typedef = isize;
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^
|
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
// Regression test of #43913.
|
||||||
|
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![feature(trait_alias)]
|
||||||
|
#![allow(bare_trait_objects, dead_code)]
|
||||||
|
|
||||||
|
trait Strings = Iterator<Item=String>;
|
||||||
|
|
||||||
|
struct Struct<S: Strings>(S);
|
||||||
|
//~^ ERROR: expected trait, found type alias `Strings`
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,13 @@
|
|||||||
|
// Regression test of #43913.
|
||||||
|
|
||||||
|
// run-rustfix
|
||||||
|
|
||||||
|
#![feature(trait_alias)]
|
||||||
|
#![allow(bare_trait_objects, dead_code)]
|
||||||
|
|
||||||
|
type Strings = Iterator<Item=String>;
|
||||||
|
|
||||||
|
struct Struct<S: Strings>(S);
|
||||||
|
//~^ ERROR: expected trait, found type alias `Strings`
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,14 @@
|
|||||||
|
error[E0404]: expected trait, found type alias `Strings`
|
||||||
|
--> $DIR/suggest-trait-alias-instead-of-type.rs:10:18
|
||||||
|
|
|
||||||
|
LL | struct Struct<S: Strings>(S);
|
||||||
|
| ^^^^^^^ type aliases cannot be used as traits
|
||||||
|
|
|
||||||
|
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
|
||||||
|
|
|
||||||
|
LL | trait Strings = Iterator<Item=String>;
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0404`.
|
Loading…
Reference in New Issue
Block a user