diff options
| author | Mark Simulacrum <mark.simulacrum@gmail.com> | 2017-07-12 06:58:44 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-07-12 06:58:44 -0600 |
| commit | 1a7dc0a2cb8ddf8c767dafb288069ceed7ab92e3 (patch) | |
| tree | 783b7336358b6cf8a25ae4db507175e91a8fbd5d | |
| parent | 0926f9b72fc3deed0e9d06261b08646425a158f8 (diff) | |
| parent | 05d352613226e890b7017b84edbc5b0ea4d6d147 (diff) | |
| download | rust-1a7dc0a2cb8ddf8c767dafb288069ceed7ab92e3.tar.gz rust-1a7dc0a2cb8ddf8c767dafb288069ceed7ab92e3.zip | |
Rollup merge of #43000 - estebank:on-unimplemented-path, r=arielb1
`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`
```
12 files changed, 147 insertions, 4 deletions
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 0bf0e21baaf..c02d1394f6b 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -330,6 +330,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .filter(|a| a.check_name("rustc_on_unimplemented")) .next() { + let name = self.tcx.item_name(def_id).as_str(); let err_sp = item.span.substitute_dummy(span); let trait_str = self.tcx.item_path_str(trait_ref.def_id); if let Some(istring) = item.value_str() { @@ -347,6 +348,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Piece::NextArgument(a) => match a.position { Position::ArgumentNamed(s) => match generic_map.get(s) { Some(val) => Some(val), + None if s == name => { + Some(&trait_str) + } None => { span_err!(self.tcx.sess, err_sp, E0272, "the #[rustc_on_unimplemented] attribute on trait \ diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6e2c36c86a3..cdbe5e14e90 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1167,6 +1167,7 @@ fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) { if let Some(istring) = attr.value_str() { let istring = istring.as_str(); + let name = tcx.item_name(def_id).as_str(); let parser = Parser::new(&istring); let types = &generics.types; for token in parser { @@ -1175,13 +1176,14 @@ fn check_on_unimplemented<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Piece::NextArgument(a) => match a.position { // `{Self}` is allowed Position::ArgumentNamed(s) if s == "Self" => (), + // `{ThisTraitsName}` is allowed + Position::ArgumentNamed(s) if s == name => (), // So is `{A}` if A is a type parameter Position::ArgumentNamed(s) => match types.iter().find(|t| { t.name == s }) { Some(_) => (), None => { - let name = tcx.item_name(def_id); span_err!(tcx.sess, attr.span, E0230, "there is no type parameter \ {} on trait {}", diff --git a/src/test/compile-fail/on-unimplemented/bad-annotation.rs b/src/test/ui/on-unimplemented/bad-annotation.rs index 8580749084d..8580749084d 100644 --- a/src/test/compile-fail/on-unimplemented/bad-annotation.rs +++ b/src/test/ui/on-unimplemented/bad-annotation.rs diff --git a/src/test/ui/on-unimplemented/bad-annotation.stderr b/src/test/ui/on-unimplemented/bad-annotation.stderr new file mode 100644 index 00000000000..8599477e8ed --- /dev/null +++ b/src/test/ui/on-unimplemented/bad-annotation.stderr @@ -0,0 +1,22 @@ +error[E0232]: this attribute must have a value + --> $DIR/bad-annotation.rs:26:1 + | +26 | #[rustc_on_unimplemented] //~ ERROR this attribute must have a value + | ^^^^^^^^^^^^^^^^^^^^^^^^^ attribute requires a value + | + = note: eg `#[rustc_on_unimplemented = "foo"]` + +error[E0230]: there is no type parameter C on trait BadAnnotation2 + --> $DIR/bad-annotation.rs:30:1 + | +30 | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0231]: only named substitution parameters are allowed + --> $DIR/bad-annotation.rs:35:1 + | +35 | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/compile-fail/on-unimplemented/multiple-impls.rs b/src/test/ui/on-unimplemented/multiple-impls.rs index 15375936b89..15375936b89 100644 --- a/src/test/compile-fail/on-unimplemented/multiple-impls.rs +++ b/src/test/ui/on-unimplemented/multiple-impls.rs diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr new file mode 100644 index 00000000000..a1fa8b720a8 --- /dev/null +++ b/src/test/ui/on-unimplemented/multiple-impls.stderr @@ -0,0 +1,53 @@ +error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied + --> $DIR/multiple-impls.rs:43:5 + | +43 | Index::index(&[] as &[i32], 2u32); + | ^^^^^^^^^^^^ trait message + | + = help: the trait `Index<u32>` is not implemented for `[i32]` + = note: required by `Index::index` + +error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied + --> $DIR/multiple-impls.rs:43:5 + | +43 | Index::index(&[] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait message + | + = help: the trait `Index<u32>` is not implemented for `[i32]` + +error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied + --> $DIR/multiple-impls.rs:49:5 + | +49 | Index::index(&[] as &[i32], Foo(2u32)); + | ^^^^^^^^^^^^ on impl for Foo + | + = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]` + = note: required by `Index::index` + +error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied + --> $DIR/multiple-impls.rs:49:5 + | +49 | Index::index(&[] as &[i32], Foo(2u32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Foo + | + = help: the trait `Index<Foo<u32>>` is not implemented for `[i32]` + +error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied + --> $DIR/multiple-impls.rs:55:5 + | +55 | Index::index(&[] as &[i32], Bar(2u32)); + | ^^^^^^^^^^^^ on impl for Bar + | + = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]` + = note: required by `Index::index` + +error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied + --> $DIR/multiple-impls.rs:55:5 + | +55 | Index::index(&[] as &[i32], Bar(2u32)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ on impl for Bar + | + = help: the trait `Index<Bar<u32>>` is not implemented for `[i32]` + +error: aborting due to 6 previous errors + diff --git a/src/test/compile-fail/on-unimplemented/on-impl.rs b/src/test/ui/on-unimplemented/on-impl.rs index 66d612baab4..66d612baab4 100644 --- a/src/test/compile-fail/on-unimplemented/on-impl.rs +++ b/src/test/ui/on-unimplemented/on-impl.rs diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr new file mode 100644 index 00000000000..c8c06bf44fd --- /dev/null +++ b/src/test/ui/on-unimplemented/on-impl.stderr @@ -0,0 +1,19 @@ +error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied + --> $DIR/on-impl.rs:32:5 + | +32 | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | + = help: the trait `Index<u32>` is not implemented for `[i32]` + = note: required by `Index::index` + +error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied + --> $DIR/on-impl.rs:32:5 + | +32 | Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice + | + = help: the trait `Index<u32>` is not implemented for `[i32]` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/on-unimplemented/on-trait.rs b/src/test/ui/on-unimplemented/on-trait.rs index a8daef356a5..ed7ec9b1436 100644 --- a/src/test/compile-fail/on-unimplemented/on-trait.rs +++ b/src/test/ui/on-unimplemented/on-trait.rs @@ -11,9 +11,12 @@ #![feature(on_unimplemented)] -#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"] -trait Foo<Bar, Baz, Quux> -{} +pub mod Bar { + #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}` in `{Foo}`"] + pub trait Foo<Bar, Baz, Quux> {} +} + +use Bar::Foo; fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T { panic!() diff --git a/src/test/ui/on-unimplemented/on-trait.stderr b/src/test/ui/on-unimplemented/on-trait.stderr new file mode 100644 index 00000000000..84986c1ecfd --- /dev/null +++ b/src/test/ui/on-unimplemented/on-trait.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `std::option::Option<std::vec::Vec<u8>>: MyFromIterator<&u8>` is not satisfied + --> $DIR/on-trait.rs:37:30 + | +37 | let y: Option<Vec<u8>> = collect(x.iter()); // this should give approximately the same error for x.iter().collect() + | ^^^^^^^ a collection of type `std::option::Option<std::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8` + | + = help: the trait `MyFromIterator<&u8>` is not implemented for `std::option::Option<std::vec::Vec<u8>>` + = note: required by `collect` + +error[E0277]: the trait bound `std::string::String: Bar::Foo<u8, _, u32>` is not satisfied + --> $DIR/on-trait.rs:42:21 + | +42 | let x: String = foobar(); //~ ERROR + | ^^^^^^ test error `std::string::String` with `u8` `_` `u32` in `Bar::Foo` + | + = help: the trait `Bar::Foo<u8, _, u32>` is not implemented for `std::string::String` + = note: required by `foobar` + +error: aborting due to 2 previous errors + diff --git a/src/test/compile-fail/on-unimplemented/slice-index.rs b/src/test/ui/on-unimplemented/slice-index.rs index 5d30c2e982e..5d30c2e982e 100644 --- a/src/test/compile-fail/on-unimplemented/slice-index.rs +++ b/src/test/ui/on-unimplemented/slice-index.rs diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr new file mode 100644 index 00000000000..68789f77f75 --- /dev/null +++ b/src/test/ui/on-unimplemented/slice-index.stderr @@ -0,0 +1,20 @@ +error[E0277]: the trait bound `i32: std::slice::SliceIndex<[i32]>` is not satisfied + --> $DIR/slice-index.rs:21:5 + | +21 | x[1i32]; //~ ERROR E0277 + | ^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `i32` + = note: required because of the requirements on the impl of `std::ops::Index<i32>` for `[i32]` + +error[E0277]: the trait bound `std::ops::RangeTo<i32>: std::slice::SliceIndex<[i32]>` is not satisfied + --> $DIR/slice-index.rs:24:5 + | +24 | x[..1i32]; //~ ERROR E0277 + | ^^^^^^^^^ slice indices are of type `usize` or ranges of `usize` + | + = help: the trait `std::slice::SliceIndex<[i32]>` is not implemented for `std::ops::RangeTo<i32>` + = note: required because of the requirements on the impl of `std::ops::Index<std::ops::RangeTo<i32>>` for `[i32]` + +error: aborting due to 2 previous errors + |
