Skip to content

Commit

Permalink
Auto merge of #75536 - estebank:e0255-suggestion, r=varkor
Browse files Browse the repository at this point in the history
Tweak output of E0225

When encountering multiple non-auto trait bounds suggest creating a new
trait and explain what auto-traits are.

_Inspired by https://fasterthanli.me/articles/frustrated-its-not-you-its-rust_
  • Loading branch information
bors committed Aug 16, 2020
2 parents de32266 + 0afb9c2 commit 97ba0c7
Show file tree
Hide file tree
Showing 11 changed files with 295 additions and 139 deletions.
12 changes: 8 additions & 4 deletions src/librustc_trait_selection/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,14 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
diag.span_label(*sp, format!("referenced here ({})", use_desc));
}
}
diag.span_label(
self.bottom().1,
format!("trait alias used in trait object type ({})", use_desc),
);
if self.top().1 != self.bottom().1 {
// When the trait object is in a return type these two spans match, we don't want
// redundant labels.
diag.span_label(
self.bottom().1,
format!("trait alias used in trait object type ({})", use_desc),
);
}
}

pub fn trait_ref(&self) -> ty::PolyTraitRef<'tcx> {
Expand Down
14 changes: 14 additions & 0 deletions src/librustc_typeck/astconv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1666,6 +1666,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"additional use",
);
first_trait.label_with_exp_info(&mut err, "first non-auto trait", "first use");
err.help(&format!(
"consider creating a new trait with all of these as super-traits and using that \
trait here instead: `trait NewTrait: {} {{}}`",
regular_traits
.iter()
.map(|t| t.trait_ref().print_only_trait_path().to_string())
.collect::<Vec<_>>()
.join(" + "),
));
err.note(
"auto-traits like `Send` and `Sync` are traits that have special properties; \
for more information on them, visit \
<https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>",
);
err.emit();
}

Expand Down
40 changes: 20 additions & 20 deletions src/test/ui/associated-types/missing-associated-types.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
--> $DIR/missing-associated-types.rs:12:32
|
LL | type Foo<Rhs> = dyn Add<Rhs> + Sub<Rhs> + X<Rhs> + Y<Rhs>;
| -------- ^^^^^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| -------- ^^^^^^^^ additional non-auto trait
| |
| first non-auto trait
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::ops::Add<Rhs> + std::ops::Sub<Rhs> + X<Rhs> + Y<Rhs> {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error[E0191]: the value of the associated types `A` (from trait `Y`), `Output` (from trait `std::ops::Add`), `Output` (from trait `std::ops::Mul`), `Output` (from trait `std::ops::Sub`) must be specified
--> $DIR/missing-associated-types.rs:12:21
Expand All @@ -31,12 +31,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
--> $DIR/missing-associated-types.rs:15:32
|
LL | type Bar<Rhs> = dyn Add<Rhs> + Sub<Rhs> + X<Rhs> + Z<Rhs>;
| -------- ^^^^^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| -------- ^^^^^^^^ additional non-auto trait
| |
| first non-auto trait
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::ops::Add<Rhs> + std::ops::Sub<Rhs> + X<Rhs> + Z<Rhs> {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error[E0191]: the value of the associated types `A` (from trait `Z`), `B` (from trait `Z`), `Output` (from trait `std::ops::Add`), `Output` (from trait `std::ops::Div`), `Output` (from trait `std::ops::Div`), `Output` (from trait `std::ops::Mul`), `Output` (from trait `std::ops::Sub`) must be specified
--> $DIR/missing-associated-types.rs:15:21
Expand Down Expand Up @@ -67,12 +67,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
--> $DIR/missing-associated-types.rs:18:32
|
LL | type Baz<Rhs> = dyn Add<Rhs> + Sub<Rhs> + Y<Rhs>;
| -------- ^^^^^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| -------- ^^^^^^^^ additional non-auto trait
| |
| first non-auto trait
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::ops::Add<Rhs> + std::ops::Sub<Rhs> + Y<Rhs> {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error[E0191]: the value of the associated types `A` (from trait `Y`), `Output` (from trait `std::ops::Add`), `Output` (from trait `std::ops::Sub`) must be specified
--> $DIR/missing-associated-types.rs:18:21
Expand All @@ -95,12 +95,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
--> $DIR/missing-associated-types.rs:21:32
|
LL | type Bat<Rhs> = dyn Add<Rhs> + Sub<Rhs> + Fine<Rhs>;
| -------- ^^^^^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| -------- ^^^^^^^^ additional non-auto trait
| |
| first non-auto trait
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::ops::Add<Rhs> + std::ops::Sub<Rhs> + Fine<Rhs> {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error[E0191]: the value of the associated types `Output` (from trait `std::ops::Add`), `Output` (from trait `std::ops::Sub`) must be specified
--> $DIR/missing-associated-types.rs:21:21
Expand Down
10 changes: 5 additions & 5 deletions src/test/ui/bad/bad-sized.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
--> $DIR/bad-sized.rs:4:28
|
LL | let x: Vec<dyn Trait + Sized> = Vec::new();
| ----- ^^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| ----- ^^^^^ additional non-auto trait
| |
| first non-auto trait
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Trait + std::marker::Sized {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
--> $DIR/bad-sized.rs:4:12
Expand Down
13 changes: 8 additions & 5 deletions src/test/ui/error-codes/E0225.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
--> $DIR/E0225.rs:6:36
|
LL | let _: Box<dyn std::io::Read + std::io::Write>;
| ------------- ^^^^^^^^^^^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| ------------- ^^^^^^^^^^^^^^ additional non-auto trait
| |
| first non-auto trait
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/E0225.rs:8:20
Expand All @@ -22,6 +22,9 @@ LL | let _: Box<dyn Foo>;
| |
| trait alias used in trait object type (additional use)
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: std::io::Read + std::io::Write {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error: aborting due to 2 previous errors

Expand Down
10 changes: 5 additions & 5 deletions src/test/ui/issues/issue-22560.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
--> $DIR/issue-22560.rs:9:23
|
LL | type Test = dyn Add + Sub;
| --- ^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| --- ^^^ additional non-auto trait
| |
| first non-auto trait
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Add<[type error]> + Sub<[type error]> {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error[E0191]: the value of the associated types `Output` (from trait `Add`), `Output` (from trait `Sub`) must be specified
--> $DIR/issue-22560.rs:9:17
Expand Down
20 changes: 10 additions & 10 deletions src/test/ui/issues/issue-32963.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
--> $DIR/issue-32963.rs:8:31
|
LL | size_of_copy::<dyn Misc + Copy>();
| ---- ^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| ---- ^^^^ additional non-auto trait
| |
| first non-auto trait
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Misc + std::marker::Copy {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/issue-32963.rs:8:31
|
LL | size_of_copy::<dyn Misc + Copy>();
| ---- ^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| ---- ^^^^ additional non-auto trait
| |
| first non-auto trait
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Misc + std::marker::Copy {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error[E0277]: the trait bound `dyn Misc: std::marker::Copy` is not satisfied
--> $DIR/issue-32963.rs:8:5
Expand Down
30 changes: 15 additions & 15 deletions src/test/ui/parser/trait-object-trait-parens.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -40,34 +40,34 @@ error[E0225]: only auto traits can be used as additional traits in a trait objec
--> $DIR/trait-object-trait-parens.rs:8:35
|
LL | let _: Box<(Obj) + (?Sized) + (for<'a> Trait<'a>)>;
| ----- ^^^^^^^^^^^^^^^^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| ----- ^^^^^^^^^^^^^^^^^^^ additional non-auto trait
| |
| first non-auto trait
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: Obj + for<'a> Trait<'a> {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-object-trait-parens.rs:12:49
|
LL | let _: Box<(?Sized) + (for<'a> Trait<'a>) + (Obj)>;
| ------------------- ^^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| ------------------- ^^^^^ additional non-auto trait
| |
| first non-auto trait
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> Trait<'a> + Obj {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error[E0225]: only auto traits can be used as additional traits in a trait object
--> $DIR/trait-object-trait-parens.rs:16:38
|
LL | let _: Box<(for<'a> Trait<'a>) + (Obj) + (?Sized)>;
| ----------------- ^^^^^
| | |
| | additional non-auto trait
| | trait alias used in trait object type (additional use)
| ----------------- ^^^^^ additional non-auto trait
| |
| first non-auto trait
| trait alias used in trait object type (first use)
|
= help: consider creating a new trait with all of these as super-traits and using that trait here instead: `trait NewTrait: for<'a> Trait<'a> + Obj {}`
= note: auto-traits like `Send` and `Sync` are traits that have special properties; for more information on them, visit <https://doc.rust-lang.org/reference/special-types-and-traits.html#auto-traits>

error: aborting due to 6 previous errors; 3 warnings emitted

Expand Down
Loading

0 comments on commit 97ba0c7

Please sign in to comment.