Skip to content

Commit 8ad0821

Browse files
committed
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`
2 parents bb491ed + eea27b8 commit 8ad0821

File tree

9 files changed

+81
-23
lines changed

9 files changed

+81
-23
lines changed

compiler/rustc_error_codes/src/error_codes/E0404.md

+20-6
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ struct Foo;
88
struct Bar;
99
1010
impl Foo for Bar {} // error: `Foo` is not a trait
11+
fn baz<T: Foo>(t: T) {} // error: `Foo` is not a trait
1112
```
1213

1314
Another erroneous code example:
1415

1516
```compile_fail,E0404
16-
struct Foo;
17+
type Foo = Iterator<Item=String>;
1718
18-
fn bar<T: Foo>(t: T) {} // error: `Foo` is not a trait
19+
fn bar<T: Foo>(t: T) {} // error: `Foo` is a type alias
1920
```
2021

2122
Please verify that the trait's name was not misspelled or that the right
@@ -30,14 +31,27 @@ struct Bar;
3031
impl Foo for Bar { // ok!
3132
// functions implementation
3233
}
34+
35+
fn baz<T: Foo>(t: T) {} // ok!
3336
```
3437

35-
or:
38+
Alternatively, you could introduce a new trait with your desired restrictions
39+
as a super trait:
3640

3741
```
38-
trait Foo {
39-
// some functions
40-
}
42+
# trait Foo {}
43+
# struct Bar;
44+
# impl Foo for Bar {}
45+
trait Qux: Foo {} // Anything that implements Qux also needs to implement Foo
46+
fn baz<T: Qux>(t: T) {} // also ok!
47+
```
48+
49+
Finally, if you are on nightly and want to use a trait alias
50+
instead of a type alias, you should use `#![feature(trait_alias)]`:
51+
52+
```
53+
#![feature(trait_alias)]
54+
trait Foo = Iterator<Item=String>;
4155
4256
fn bar<T: Foo>(t: T) {} // ok!
4357
```

compiler/rustc_resolve/src/late/diagnostics.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,14 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
930930
let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
931931
`type` alias";
932932
if let Some(span) = self.def_span(def_id) {
933-
err.span_help(span, msg);
933+
if let Ok(snip) = self.r.session.source_map().span_to_snippet(span) {
934+
// The span contains a type alias so we should be able to
935+
// replace `type` with `trait`.
936+
let snip = snip.replacen("type", "trait", 1);
937+
err.span_suggestion(span, msg, snip, Applicability::MaybeIncorrect);
938+
} else {
939+
err.span_help(span, msg);
940+
}
934941
} else {
935942
err.help(msg);
936943
}

src/test/ui/codemap_tests/two_files.stderr

+2-3
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ LL | impl Bar for Baz { }
55
| ^^^ type aliases cannot be used as traits
66
|
77
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
8-
--> $DIR/two_files_data.rs:5:1
98
|
10-
LL | type Bar = dyn Foo;
11-
| ^^^^^^^^^^^^^^^^^^^
9+
LL | trait Bar = dyn Foo;
10+
|
1211

1312
error: aborting due to previous error
1413

src/test/ui/resolve/issue-3907.stderr

+2-3
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ LL | impl Foo for S {
55
| ^^^ type aliases cannot be used as traits
66
|
77
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
8-
--> $DIR/issue-3907.rs:5:1
98
|
10-
LL | type Foo = dyn issue_3907::Foo;
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9+
LL | trait Foo = dyn issue_3907::Foo;
10+
|
1211
help: consider importing this trait instead
1312
|
1413
LL | use issue_3907::Foo;

src/test/ui/resolve/issue-5035.stderr

+7-7
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ LL | trait I {}
1111
| ------- similarly named trait `I` defined here
1212
LL | type K = dyn I;
1313
LL | impl K for isize {}
14-
| ^
15-
| |
16-
| type aliases cannot be used as traits
17-
| help: a trait with a similar name exists: `I`
14+
| ^ type aliases cannot be used as traits
1815
|
1916
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
20-
--> $DIR/issue-5035.rs:2:1
2117
|
22-
LL | type K = dyn I;
23-
| ^^^^^^^^^^^^^^^
18+
LL | trait K = dyn I;
19+
|
20+
help: a trait with a similar name exists
21+
|
22+
LL | impl I for isize {}
23+
| ^
2424

2525
error: aborting due to 2 previous errors
2626

src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr

+2-3
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@ LL | fn g<F:Typedef(isize) -> isize>(x: F) {}
1111
| ^^^^^^^^^^^^^^^^^^^^^^^ type aliases cannot be used as traits
1212
|
1313
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
14-
--> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:4:1
1514
|
16-
LL | type Typedef = isize;
17-
| ^^^^^^^^^^^^^^^^^^^^^
15+
LL | trait Typedef = isize;
16+
|
1817

1918
error: aborting due to 2 previous errors
2019

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Regression test of #43913.
2+
3+
// run-rustfix
4+
5+
#![feature(trait_alias)]
6+
#![allow(bare_trait_objects, dead_code)]
7+
8+
trait Strings = Iterator<Item=String>;
9+
10+
struct Struct<S: Strings>(S);
11+
//~^ ERROR: expected trait, found type alias `Strings`
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Regression test of #43913.
2+
3+
// run-rustfix
4+
5+
#![feature(trait_alias)]
6+
#![allow(bare_trait_objects, dead_code)]
7+
8+
type Strings = Iterator<Item=String>;
9+
10+
struct Struct<S: Strings>(S);
11+
//~^ ERROR: expected trait, found type alias `Strings`
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0404]: expected trait, found type alias `Strings`
2+
--> $DIR/suggest-trait-alias-instead-of-type.rs:10:18
3+
|
4+
LL | struct Struct<S: Strings>(S);
5+
| ^^^^^^^ type aliases cannot be used as traits
6+
|
7+
help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
8+
|
9+
LL | trait Strings = Iterator<Item=String>;
10+
|
11+
12+
error: aborting due to previous error
13+
14+
For more information about this error, try `rustc --explain E0404`.

0 commit comments

Comments
 (0)