Skip to content

Commit

Permalink
Rollup merge of rust-lang#83729 - JohnTitor:issue-43913, r=estebank
Browse files Browse the repository at this point in the history
Add a suggestion when using a type alias instead of trait alias

Fixes rust-lang#43913

r? ``@estebank``
  • Loading branch information
Dylan-DPC authored Apr 20, 2021
2 parents c8e5d46 + eea27b8 commit 66cf14a
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 23 deletions.
26 changes: 20 additions & 6 deletions compiler/rustc_error_codes/src/error_codes/E0404.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ struct Foo;
struct Bar;
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:

```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
Expand All @@ -30,14 +31,27 @@ struct Bar;
impl Foo for Bar { // ok!
// 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 {
// some functions
}
# trait Foo {}
# 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!
```
9 changes: 8 additions & 1 deletion compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -930,7 +930,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
`type` alias";
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 {
err.help(msg);
}
Expand Down
5 changes: 2 additions & 3 deletions src/test/ui/codemap_tests/two_files.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ LL | impl Bar for Baz { }
| ^^^ type aliases cannot be used as traits
|
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

Expand Down
5 changes: 2 additions & 3 deletions src/test/ui/resolve/issue-3907.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ LL | impl Foo for S {
| ^^^ type aliases cannot be used as traits
|
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
|
LL | use issue_3907::Foo;
Expand Down
14 changes: 7 additions & 7 deletions src/test/ui/resolve/issue-5035.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ LL | trait I {}
| ------- similarly named trait `I` defined here
LL | type K = dyn I;
LL | impl K for isize {}
| ^
| |
| type aliases cannot be used as traits
| help: a trait with a similar name exists: `I`
| ^ type aliases cannot be used as traits
|
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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ LL | fn g<F:Typedef(isize) -> isize>(x: F) {}
| ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used as traits
|
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

Expand Down
13 changes: 13 additions & 0 deletions src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.fixed
Original file line number Diff line number Diff line change
@@ -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() {}
13 changes: 13 additions & 0 deletions src/test/ui/traits/alias/suggest-trait-alias-instead-of-type.rs
Original file line number Diff line number Diff line change
@@ -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() {}
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 66cf14a

Please sign in to comment.