Skip to content

Commit 05d3526

Browse files
committed
rustc_on_unimplemented supports referring to trait
Add support to `rustc_on_unimplemented` to reference the full path of the annotated trait. For the following code: ```rust pub mod Bar { #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}` in `{Foo}`"] pub trait Foo<Bar, Baz, Quux> {} } ``` the error message will be: ``` test error `std::string::String` with `u8` `_` `u32` in `Bar::Foo` ```
1 parent 3610a70 commit 05d3526

12 files changed

+147
-4
lines changed

src/librustc/traits/error_reporting.rs

+4
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
330330
.filter(|a| a.check_name("rustc_on_unimplemented"))
331331
.next()
332332
{
333+
let name = self.tcx.item_name(def_id).as_str();
333334
let err_sp = item.span.substitute_dummy(span);
334335
let trait_str = self.tcx.item_path_str(trait_ref.def_id);
335336
if let Some(istring) = item.value_str() {
@@ -347,6 +348,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
347348
Piece::NextArgument(a) => match a.position {
348349
Position::ArgumentNamed(s) => match generic_map.get(s) {
349350
Some(val) => Some(val),
351+
None if s == name => {
352+
Some(&trait_str)
353+
}
350354
None => {
351355
span_err!(self.tcx.sess, err_sp, E0272,
352356
"the #[rustc_on_unimplemented] attribute on trait \

src/librustc_typeck/check/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,7 @@ fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
11661166
}) {
11671167
if let Some(istring) = attr.value_str() {
11681168
let istring = istring.as_str();
1169+
let name = tcx.item_name(def_id).as_str();
11691170
let parser = Parser::new(&istring);
11701171
let types = &generics.types;
11711172
for token in parser {
@@ -1174,13 +1175,14 @@ fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
11741175
Piece::NextArgument(a) => match a.position {
11751176
// `{Self}` is allowed
11761177
Position::ArgumentNamed(s) if s == "Self" => (),
1178+
// `{ThisTraitsName}` is allowed
1179+
Position::ArgumentNamed(s) if s == name => (),
11771180
// So is `{A}` if A is a type parameter
11781181
Position::ArgumentNamed(s) => match types.iter().find(|t| {
11791182
t.name == s
11801183
}) {
11811184
Some(_) => (),
11821185
None => {
1183-
let name = tcx.item_name(def_id);
11841186
span_err!(tcx.sess, attr.span, E0230,
11851187
"there is no type parameter \
11861188
{} on trait {}",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0232]: this attribute must have a value
2+
--> $DIR/bad-annotation.rs:26:1
3+
|
4+
26 | #[rustc_on_unimplemented] //~ ERROR this attribute must have a value
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ attribute requires a value
6+
|
7+
= note: eg `#[rustc_on_unimplemented = "foo"]`
8+
9+
error[E0230]: there is no type parameter C on trait BadAnnotation2
10+
--> $DIR/bad-annotation.rs:30:1
11+
|
12+
30 | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
15+
error[E0231]: only named substitution parameters are allowed
16+
--> $DIR/bad-annotation.rs:35:1
17+
|
18+
35 | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"]
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
21+
error: aborting due to 3 previous errors
22+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
2+
--> $DIR/multiple-impls.rs:43:5
3+
|
4+
43 | Index::index(&[] as &[i32], 2u32);
5+
| ^^^^^^^^^^^^ trait message
6+
|
7+
= help: the trait `Index<u32>` is not implemented for `[i32]`
8+
= note: required by `Index::index`
9+
10+
error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
11+
--> $DIR/multiple-impls.rs:43:5
12+
|
13+
43 | Index::index(&[] as &[i32], 2u32);
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message
15+
|
16+
= help: the trait `Index<u32>` is not implemented for `[i32]`
17+
18+
error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
19+
--> $DIR/multiple-impls.rs:49:5
20+
|
21+
49 | Index::index(&[] as &[i32], Foo(2u32));
22+
| ^^^^^^^^^^^^ on impl for Foo
23+
|
24+
= help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
25+
= note: required by `Index::index`
26+
27+
error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
28+
--> $DIR/multiple-impls.rs:49:5
29+
|
30+
49 | Index::index(&[] as &[i32], Foo(2u32));
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo
32+
|
33+
= help: the trait `Index<Foo<u32>>` is not implemented for `[i32]`
34+
35+
error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
36+
--> $DIR/multiple-impls.rs:55:5
37+
|
38+
55 | Index::index(&[] as &[i32], Bar(2u32));
39+
| ^^^^^^^^^^^^ on impl for Bar
40+
|
41+
= help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
42+
= note: required by `Index::index`
43+
44+
error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
45+
--> $DIR/multiple-impls.rs:55:5
46+
|
47+
55 | Index::index(&[] as &[i32], Bar(2u32));
48+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar
49+
|
50+
= help: the trait `Index<Bar<u32>>` is not implemented for `[i32]`
51+
52+
error: aborting due to 6 previous errors
53+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
2+
--> $DIR/on-impl.rs:32:5
3+
|
4+
32 | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
5+
| ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
6+
|
7+
= help: the trait `Index<u32>` is not implemented for `[i32]`
8+
= note: required by `Index::index`
9+
10+
error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
11+
--> $DIR/on-impl.rs:32:5
12+
|
13+
32 | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
15+
|
16+
= help: the trait `Index<u32>` is not implemented for `[i32]`
17+
18+
error: aborting due to 2 previous errors
19+

src/test/compile-fail/on-unimplemented/on-trait.rs renamed to src/test/ui/on-unimplemented/on-trait.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,12 @@
1111

1212
#![feature(on_unimplemented)]
1313

14-
#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
15-
trait Foo<Bar, Baz, Quux>
16-
{}
14+
pub mod Bar {
15+
#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}` in `{Foo}`"]
16+
pub trait Foo<Bar, Baz, Quux> {}
17+
}
18+
19+
use Bar::Foo;
1720

1821
fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {
1922
panic!()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0277]: the trait bound `std::option::Option<std::vec::Vec<u8>>: MyFromIterator<&u8>` is not satisfied
2+
--> $DIR/on-trait.rs:37:30
3+
|
4+
37 | let y: Option<Vec<u8>> = collect(x.iter()); // this should give approximately the same error for x.iter().collect()
5+
| ^^^^^^^ a collection of type `std::option::Option<std::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
6+
|
7+
= help: the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option<std::vec::Vec<u8>>`
8+
= note: required by `collect`
9+
10+
error[E0277]: the trait bound `std::string::String: Bar::Foo<u8, _, u32>` is not satisfied
11+
--> $DIR/on-trait.rs:42:21
12+
|
13+
42 | let x: String = foobar(); //~ ERROR
14+
| ^^^^^^ test error `std::string::String` with `u8` `_` `u32` in `Bar::Foo`
15+
|
16+
= help: the trait `Bar::Foo<u8, _, u32>` is not implemented for `std::string::String`
17+
= note: required by `foobar`
18+
19+
error: aborting due to 2 previous errors
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0277]: the trait bound `i32: std::slice::SliceIndex<[i32]>` is not satisfied
2+
--> $DIR/slice-index.rs:21:5
3+
|
4+
21 | x[1i32]; //~ ERROR E0277
5+
| ^^^^^^^ slice indices are of type `usize` or ranges of `usize`
6+
|
7+
= help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32`
8+
= note: required because of the requirements on the impl of `std::ops::Index<i32>` for `[i32]`
9+
10+
error[E0277]: the trait bound `std::ops::RangeTo<i32>: std::slice::SliceIndex<[i32]>` is not satisfied
11+
--> $DIR/slice-index.rs:24:5
12+
|
13+
24 | x[..1i32]; //~ ERROR E0277
14+
| ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize`
15+
|
16+
= help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo<i32>`
17+
= note: required because of the requirements on the impl of `std::ops::Index<std::ops::RangeTo<i32>>` for `[i32]`
18+
19+
error: aborting due to 2 previous errors
20+

0 commit comments

Comments
 (0)