about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2019-10-08 16:03:38 -0700
committerEsteban Küber <esteban@kuber.com.ar>2019-10-15 13:55:43 -0700
commit99ab45b91de9fc6c07903dbe3075757f0e5e9071 (patch)
tree6ff2df433369aa7e61246955db6864a26186950f
parentdbd75c8c40a06ac682251b67a548a8252c5d4b18 (diff)
downloadrust-99ab45b91de9fc6c07903dbe3075757f0e5e9071.tar.gz
rust-99ab45b91de9fc6c07903dbe3075757f0e5e9071.zip
Handle `Self` restriction needed
-rw-r--r--src/librustc/traits/error_reporting.rs28
-rw-r--r--src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr7
-rw-r--r--src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr7
-rw-r--r--src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr7
-rw-r--r--src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr7
-rw-r--r--src/test/ui/issues/issue-20005.stderr2
-rw-r--r--src/test/ui/issues/issue-27078.stderr5
-rw-r--r--src/test/ui/type/type-params-in-different-spaces-2.stderr8
-rw-r--r--src/test/ui/wf/wf-trait-default-fn-arg.stderr7
-rw-r--r--src/test/ui/wf/wf-trait-default-fn-ret.stderr7
-rw-r--r--src/test/ui/wf/wf-trait-default-fn-where-clause.stderr7
-rw-r--r--src/test/ui/wf/wf-trait-fn-arg.stderr7
-rw-r--r--src/test/ui/wf/wf-trait-fn-ret.stderr7
-rw-r--r--src/test/ui/wf/wf-trait-fn-where-clause.stderr7
14 files changed, 76 insertions, 37 deletions
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index c8baafef50a..6e111089d06 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -986,6 +986,34 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         while let Some(node) = self.tcx.hir().find(hir_id) {
             debug!("suggest_restricting_param_bound node={:?}", node);
             match node {
+                hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Fn(decl, _, generics, _), ..
+                }) |
+                hir::Node::TraitItem(hir::TraitItem {
+                    generics,
+                    kind: hir::TraitItemKind::Method(hir::MethodSig { decl, .. }, _), ..
+                }) |
+                hir::Node::ImplItem(hir::ImplItem {
+                    generics,
+                    kind: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, _), ..
+                }) if param_ty.name.as_str() == "Self" => {
+                    if !generics.where_clause.predicates.is_empty() {
+                        err.span_suggestion(
+                            generics.where_clause.span().unwrap().shrink_to_hi(),
+                            "consider further restricting `Self`",
+                            format!(", {}", trait_ref.to_predicate()),
+                            Applicability::MachineApplicable,
+                        );
+                    } else {
+                        err.span_suggestion(
+                            decl.output.span().shrink_to_hi(),
+                            "consider further restricting `Self`",
+                            format!(" where {}", trait_ref.to_predicate()),
+                            Applicability::MachineApplicable,
+                        );
+                    }
+                    return;
+                }
                 hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) |
                 hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) |
                 hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) |
diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
index 9f033687a00..79525e6362f 100644
--- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
+++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
@@ -2,9 +2,10 @@ error[E0277]: the trait bound `Self: Get` is not satisfied
   --> $DIR/associated-types-for-unimpl-trait.rs:7:5
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
-   |
-   = help: consider adding a `where Self: Get` bound
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^
+   |     |                                                        |
+   |     |                                                        help: consider further restricting `Self`: `where Self: Get`
+   |     the trait `Get` is not implemented for `Self`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
index 56cd6d09cad..43950defc7c 100644
--- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
@@ -2,9 +2,10 @@ error[E0277]: the trait bound `Self: Get` is not satisfied
   --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
-   |
-   = help: consider adding a `where Self: Get` bound
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^
+   |     |                                                        |
+   |     |                                                        help: consider further restricting `Self`: `where Self: Get`
+   |     the trait `Get` is not implemented for `Self`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
index 71175d36f64..82e366dbea4 100644
--- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
@@ -2,9 +2,10 @@ error[E0277]: the trait bound `Self: Get` is not satisfied
   --> $DIR/associated-types-no-suitable-supertrait.rs:17:5
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
-   |
-   = help: consider adding a `where Self: Get` bound
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^
+   |     |                                                        |
+   |     |                                                        help: consider further restricting `Self`: `where Self: Get`
+   |     the trait `Get` is not implemented for `Self`
 
 error[E0277]: the trait bound `(T, U): Get` is not satisfied
   --> $DIR/associated-types-no-suitable-supertrait.rs:22:5
diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
index a260e379182..54daeca4252 100644
--- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
+++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
@@ -2,9 +2,10 @@ error[E0277]: the trait bound `Self: Get` is not satisfied
   --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:9:5
    |
 LL |     fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
-   |
-   = help: consider adding a `where Self: Get` bound
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |     |                                                       |
+   |     |                                                       help: consider further restricting `Self`: `where Self: Get`
+   |     the trait `Get` is not implemented for `Self`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20005.stderr b/src/test/ui/issues/issue-20005.stderr
index 2754d6bdd83..31376f2d1be 100644
--- a/src/test/ui/issues/issue-20005.stderr
+++ b/src/test/ui/issues/issue-20005.stderr
@@ -7,13 +7,13 @@ LL |   trait From<Src> {
 LL | /     fn to<Dst>(
 LL | |         self
 LL | |     ) -> <Dst as From<Self>>::Result where Dst: From<Self> {
+   | |                                                           - help: consider further restricting `Self`: `, Self: std::marker::Sized`
 LL | |         From::from(self)
 LL | |     }
    | |_____^ doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `Self`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-   = help: consider adding a `where Self: std::marker::Sized` bound
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-27078.stderr b/src/test/ui/issues/issue-27078.stderr
index 76cc3e7b0a3..fbc72d063f3 100644
--- a/src/test/ui/issues/issue-27078.stderr
+++ b/src/test/ui/issues/issue-27078.stderr
@@ -2,11 +2,12 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
   --> $DIR/issue-27078.rs:5:12
    |
 LL |     fn foo(self) -> &'static i32 {
-   |            ^^^^ doesn't have a size known at compile-time
+   |            ^^^^                 - help: consider further restricting `Self`: `where Self: std::marker::Sized`
+   |            |
+   |            doesn't have a size known at compile-time
    |
    = help: the trait `std::marker::Sized` is not implemented for `Self`
    = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
-   = help: consider adding a `where Self: std::marker::Sized` bound
    = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
 
diff --git a/src/test/ui/type/type-params-in-different-spaces-2.stderr b/src/test/ui/type/type-params-in-different-spaces-2.stderr
index 7d4bbc813c0..7ce249a60b8 100644
--- a/src/test/ui/type/type-params-in-different-spaces-2.stderr
+++ b/src/test/ui/type/type-params-in-different-spaces-2.stderr
@@ -4,10 +4,10 @@ error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
 LL |     fn op(_: T) -> Self;
    |     -------------------- required by `Tr::op`
 ...
+LL |     fn test<U>(u: U) -> Self {
+   |                             - help: consider further restricting `Self`: `where Self: Tr<U>`
 LL |         Tr::op(u)
    |         ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
-   |
-   = help: consider adding a `where Self: Tr<U>` bound
 
 error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
   --> $DIR/type-params-in-different-spaces-2.rs:16:9
@@ -15,10 +15,10 @@ error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
 LL |     fn op(_: T) -> Self;
    |     -------------------- required by `Tr::op`
 ...
+LL |     fn test<U>(u: U) -> Self {
+   |                             - help: consider further restricting `Self`: `where Self: Tr<U>`
 LL |         Tr::op(u)
    |         ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
-   |
-   = help: consider adding a `where Self: Tr<U>` bound
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/wf/wf-trait-default-fn-arg.stderr b/src/test/ui/wf/wf-trait-default-fn-arg.stderr
index 4d0e1f2f0f4..3efcdf72eee 100644
--- a/src/test/ui/wf/wf-trait-default-fn-arg.stderr
+++ b/src/test/ui/wf/wf-trait-default-fn-arg.stderr
@@ -4,14 +4,15 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
 LL |   struct Bar<T:Eq+?Sized> { value: Box<T> }
    |   ----------------------- required by `Bar`
 ...
-LL | /     fn bar(&self, x: &Bar<Self>) {
+LL |       fn bar(&self, x: &Bar<Self>) {
+   |       ^                            - help: consider further restricting `Self`: `where Self: std::cmp::Eq`
+   |  _____|
+   | |
 LL | |
 LL | |         //
 LL | |         // Here, Eq ought to be implemented.
 LL | |     }
    | |_____^ the trait `std::cmp::Eq` is not implemented for `Self`
-   |
-   = help: consider adding a `where Self: std::cmp::Eq` bound
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-default-fn-ret.stderr b/src/test/ui/wf/wf-trait-default-fn-ret.stderr
index e82b76b61c4..e32630a5a4a 100644
--- a/src/test/ui/wf/wf-trait-default-fn-ret.stderr
+++ b/src/test/ui/wf/wf-trait-default-fn-ret.stderr
@@ -4,15 +4,16 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
 LL |   struct Bar<T:Eq+?Sized> { value: Box<T> }
    |   ----------------------- required by `Bar`
 ...
-LL | /     fn bar(&self) -> Bar<Self> {
+LL |       fn bar(&self) -> Bar<Self> {
+   |       ^                         - help: consider further restricting `Self`: `where Self: std::cmp::Eq`
+   |  _____|
+   | |
 LL | |
 LL | |         //
 LL | |         // Here, Eq ought to be implemented.
 LL | |         loop { }
 LL | |     }
    | |_____^ the trait `std::cmp::Eq` is not implemented for `Self`
-   |
-   = help: consider adding a `where Self: std::cmp::Eq` bound
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr
index 6504f6698d9..a443ff1bb63 100644
--- a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr
+++ b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr
@@ -4,14 +4,15 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied
 LL |   trait Bar<T:Eq+?Sized> { }
    |   ---------------------- required by `Bar`
 ...
-LL | /     fn bar<A>(&self) where A: Bar<Self> {
+LL |       fn bar<A>(&self) where A: Bar<Self> {
+   |       ^                                  - help: consider further restricting `Self`: `, Self: std::cmp::Eq`
+   |  _____|
+   | |
 LL | |
 LL | |         //
 LL | |         // Here, Eq ought to be implemented.
 LL | |     }
    | |_____^ the trait `std::cmp::Eq` is not implemented for `Self`
-   |
-   = help: consider adding a `where Self: std::cmp::Eq` bound
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-fn-arg.stderr b/src/test/ui/wf/wf-trait-fn-arg.stderr
index 0887d4b2fcd..42a28ee6763 100644
--- a/src/test/ui/wf/wf-trait-fn-arg.stderr
+++ b/src/test/ui/wf/wf-trait-fn-arg.stderr
@@ -5,9 +5,10 @@ LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
    | ----------------------- required by `Bar`
 ...
 LL |     fn bar(&self, x: &Bar<Self>);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self`
-   |
-   = help: consider adding a `where Self: std::cmp::Eq` bound
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |     |                           |
+   |     |                           help: consider further restricting `Self`: `where Self: std::cmp::Eq`
+   |     the trait `std::cmp::Eq` is not implemented for `Self`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-fn-ret.stderr b/src/test/ui/wf/wf-trait-fn-ret.stderr
index 5555081498c..7ec4dbe0056 100644
--- a/src/test/ui/wf/wf-trait-fn-ret.stderr
+++ b/src/test/ui/wf/wf-trait-fn-ret.stderr
@@ -5,9 +5,10 @@ LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
    | ----------------------- required by `Bar`
 ...
 LL |     fn bar(&self) -> &Bar<Self>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self`
-   |
-   = help: consider adding a `where Self: std::cmp::Eq` bound
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |     |                          |
+   |     |                          help: consider further restricting `Self`: `where Self: std::cmp::Eq`
+   |     the trait `std::cmp::Eq` is not implemented for `Self`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-trait-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-fn-where-clause.stderr
index 5e8fd898239..256edb5b2ca 100644
--- a/src/test/ui/wf/wf-trait-fn-where-clause.stderr
+++ b/src/test/ui/wf/wf-trait-fn-where-clause.stderr
@@ -5,9 +5,10 @@ LL | struct Bar<T:Eq+?Sized> { value: Box<T> }
    | ----------------------- required by `Bar`
 ...
 LL |     fn bar(&self) where Self: Sized, Bar<Self>: Copy;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self`
-   |
-   = help: consider adding a `where Self: std::cmp::Eq` bound
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
+   |     |                                               |
+   |     |                                               help: consider further restricting `Self`: `, Self: std::cmp::Eq`
+   |     the trait `std::cmp::Eq` is not implemented for `Self`
 
 error: aborting due to previous error