about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMark Simulacrum <mark.simulacrum@gmail.com>2017-07-12 06:58:44 -0600
committerGitHub <noreply@github.com>2017-07-12 06:58:44 -0600
commit1a7dc0a2cb8ddf8c767dafb288069ceed7ab92e3 (patch)
tree783b7336358b6cf8a25ae4db507175e91a8fbd5d
parent0926f9b72fc3deed0e9d06261b08646425a158f8 (diff)
parent05d352613226e890b7017b84edbc5b0ea4d6d147 (diff)
downloadrust-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`
```
-rw-r--r--src/librustc/traits/error_reporting.rs4
-rw-r--r--src/librustc_typeck/check/mod.rs4
-rw-r--r--src/test/ui/on-unimplemented/bad-annotation.rs (renamed from src/test/compile-fail/on-unimplemented/bad-annotation.rs)0
-rw-r--r--src/test/ui/on-unimplemented/bad-annotation.stderr22
-rw-r--r--src/test/ui/on-unimplemented/multiple-impls.rs (renamed from src/test/compile-fail/on-unimplemented/multiple-impls.rs)0
-rw-r--r--src/test/ui/on-unimplemented/multiple-impls.stderr53
-rw-r--r--src/test/ui/on-unimplemented/on-impl.rs (renamed from src/test/compile-fail/on-unimplemented/on-impl.rs)0
-rw-r--r--src/test/ui/on-unimplemented/on-impl.stderr19
-rw-r--r--src/test/ui/on-unimplemented/on-trait.rs (renamed from src/test/compile-fail/on-unimplemented/on-trait.rs)9
-rw-r--r--src/test/ui/on-unimplemented/on-trait.stderr20
-rw-r--r--src/test/ui/on-unimplemented/slice-index.rs (renamed from src/test/compile-fail/on-unimplemented/slice-index.rs)0
-rw-r--r--src/test/ui/on-unimplemented/slice-index.stderr20
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
+