about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2020-04-22 16:03:39 -0700
committerEsteban Küber <esteban@kuber.com.ar>2020-05-12 11:19:07 -0700
commit545320a22ff61c30e932200c07466ba3f2be76aa (patch)
tree9cf4304599aa09e7ec7c054e3c875c90c474c0da
parentd903a9def4c29846ec6215ccc7fa76d39428f577 (diff)
downloadrust-545320a22ff61c30e932200c07466ba3f2be76aa.tar.gz
rust-545320a22ff61c30e932200c07466ba3f2be76aa.zip
Suggest adding super trait constraints
-rw-r--r--src/librustc_trait_selection/traits/error_reporting/suggestions.rs45
-rw-r--r--src/test/ui/associated-types/defaults-unsound-62211-1.stderr16
-rw-r--r--src/test/ui/associated-types/defaults-unsound-62211-2.stderr16
-rw-r--r--src/test/ui/associated-types/issue-63593.stderr4
-rw-r--r--src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.rs11
-rw-r--r--src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr17
6 files changed, 96 insertions, 13 deletions
diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
index e0b99333fd1..5abae7ed68b 100644
--- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs
@@ -15,7 +15,7 @@ use rustc_middle::ty::{
     self, suggest_constraining_type_param, AdtKind, DefIdTree, Infer, InferTy, ToPredicate, Ty,
     TyCtxt, TypeFoldable, WithConstness,
 };
-use rustc_span::symbol::{kw, sym, Symbol};
+use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
 use std::fmt;
 
@@ -173,6 +173,7 @@ fn suggest_restriction(
     fn_sig: Option<&hir::FnSig<'_>>,
     projection: Option<&ty::ProjectionTy<'_>>,
     trait_ref: ty::PolyTraitRef<'_>,
+    super_traits: Option<(&Ident, &hir::GenericBounds<'_>)>,
 ) {
     let span = generics.where_clause.span_for_predicates_or_empty_place();
     if span.from_expansion() || span.desugaring_kind().is_some() {
@@ -262,8 +263,22 @@ fn suggest_restriction(
         );
     } else {
         // Trivial case: `T` needs an extra bound: `T: Bound`.
-        let (sp, sugg) =
-            predicate_constraint(generics, trait_ref.without_const().to_predicate().to_string());
+        let (sp, sugg) = match super_traits {
+            None => {
+                predicate_constraint(generics, trait_ref.without_const().to_predicate().to_string())
+            }
+            Some((ident, bounds)) => match bounds {
+                [.., bound] => (
+                    bound.span().shrink_to_hi(),
+                    format!(" + {}", trait_ref.print_only_trait_path().to_string()),
+                ),
+                [] => (
+                    ident.span.shrink_to_hi(),
+                    format!(": {}", trait_ref.print_only_trait_path().to_string()),
+                ),
+            },
+        };
+
         let appl = Applicability::MachineApplicable;
         err.span_suggestion(sp, &format!("consider further restricting {}", msg), sugg, appl);
     }
@@ -288,13 +303,33 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         let mut hir_id = body_id;
         while let Some(node) = self.tcx.hir().find(hir_id) {
             match node {
+                hir::Node::Item(hir::Item {
+                    ident,
+                    kind: hir::ItemKind::Trait(_, _, generics, bounds, _),
+                    ..
+                }) if param_ty && self_ty == self.tcx.types.self_param => {
+                    // Restricting `Self` for a single method.
+                    suggest_restriction(
+                        &generics,
+                        "`Self`",
+                        err,
+                        None,
+                        projection,
+                        trait_ref,
+                        Some((ident, bounds)),
+                    );
+                    return;
+                }
+
                 hir::Node::TraitItem(hir::TraitItem {
                     generics,
                     kind: hir::TraitItemKind::Fn(..),
                     ..
                 }) if param_ty && self_ty == self.tcx.types.self_param => {
                     // Restricting `Self` for a single method.
-                    suggest_restriction(&generics, "`Self`", err, None, projection, trait_ref);
+                    suggest_restriction(
+                        &generics, "`Self`", err, None, projection, trait_ref, None,
+                    );
                     return;
                 }
 
@@ -319,6 +354,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         Some(fn_sig),
                         projection,
                         trait_ref,
+                        None,
                     );
                     return;
                 }
@@ -336,6 +372,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         None,
                         projection,
                         trait_ref,
+                        None,
                     );
                     return;
                 }
diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr
index 856d513d60b..c804bc3d833 100644
--- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr
+++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
   --> $DIR/defaults-unsound-62211-1.rs:21:18
    |
 LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
+   | --------------------------- help: consider further restricting `Self`: `+ std::marker::Copy`
+   | |
+   | required by `UncheckedCopy`
 ...
 LL |     type Output: Copy
    |                  ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
@@ -11,7 +13,9 @@ error[E0277]: cannot add-assign `&'static str` to `Self`
   --> $DIR/defaults-unsound-62211-1.rs:25:7
    |
 LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
+   | --------------------------- help: consider further restricting `Self`: `+ std::ops::AddAssign<&'static str>`
+   | |
+   | required by `UncheckedCopy`
 ...
 LL |     + AddAssign<&'static str>
    |       ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
@@ -22,7 +26,9 @@ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
   --> $DIR/defaults-unsound-62211-1.rs:23:7
    |
 LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
+   | --------------------------- help: consider further restricting `Self`: `+ std::ops::Deref`
+   | |
+   | required by `UncheckedCopy`
 ...
 LL |     + Deref<Target = str>
    |       ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
@@ -31,7 +37,9 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
   --> $DIR/defaults-unsound-62211-1.rs:28:7
    |
 LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
+   | --------------------------- help: consider further restricting `Self`: `+ std::fmt::Display`
+   | |
+   | required by `UncheckedCopy`
 ...
 LL |     + Display = Self;
    |       ^^^^^^^ `Self` cannot be formatted with the default formatter
diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr
index 1060c82fec2..aee5e4b28ca 100644
--- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr
+++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr
@@ -2,7 +2,9 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
   --> $DIR/defaults-unsound-62211-2.rs:21:18
    |
 LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
+   | --------------------------- help: consider further restricting `Self`: `+ std::marker::Copy`
+   | |
+   | required by `UncheckedCopy`
 ...
 LL |     type Output: Copy
    |                  ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
@@ -11,7 +13,9 @@ error[E0277]: cannot add-assign `&'static str` to `Self`
   --> $DIR/defaults-unsound-62211-2.rs:25:7
    |
 LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
+   | --------------------------- help: consider further restricting `Self`: `+ std::ops::AddAssign<&'static str>`
+   | |
+   | required by `UncheckedCopy`
 ...
 LL |     + AddAssign<&'static str>
    |       ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
@@ -22,7 +26,9 @@ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
   --> $DIR/defaults-unsound-62211-2.rs:23:7
    |
 LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
+   | --------------------------- help: consider further restricting `Self`: `+ std::ops::Deref`
+   | |
+   | required by `UncheckedCopy`
 ...
 LL |     + Deref<Target = str>
    |       ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
@@ -31,7 +37,9 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display`
   --> $DIR/defaults-unsound-62211-2.rs:28:7
    |
 LL | trait UncheckedCopy: Sized {
-   | -------------------------- required by `UncheckedCopy`
+   | --------------------------- help: consider further restricting `Self`: `+ std::fmt::Display`
+   | |
+   | required by `UncheckedCopy`
 ...
 LL |     + Display = Self;
    |       ^^^^^^^ `Self` cannot be formatted with the default formatter
diff --git a/src/test/ui/associated-types/issue-63593.stderr b/src/test/ui/associated-types/issue-63593.stderr
index c27800f5a3f..42529fd2b22 100644
--- a/src/test/ui/associated-types/issue-63593.stderr
+++ b/src/test/ui/associated-types/issue-63593.stderr
@@ -2,7 +2,9 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation
   --> $DIR/issue-63593.rs:9:5
    |
 LL | trait MyTrait {
-   | ------------- required by `MyTrait`
+   | -------------- help: consider further restricting `Self`: `: std::marker::Sized`
+   | |
+   | required by `MyTrait`
 LL |     type This = Self;
    |     ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
diff --git a/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.rs b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.rs
new file mode 100644
index 00000000000..0474bf0a339
--- /dev/null
+++ b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.rs
@@ -0,0 +1,11 @@
+use std::ops::{Add, Sub, Mul, Div};
+
+trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> {}
+//~^ ERROR the size for values of type `Self` cannot be known at compilation time
+
+impl<T> ArithmeticOps for T where T: Add<Output=T> + Sub<Output=T> + Mul<Output=T> + Div<Output=T> {
+    // Nothing to implement, since T already supports the other traits.
+    // It has the functions it needs already
+}
+
+fn main() {}
diff --git a/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr
new file mode 100644
index 00000000000..707bcf5e2fe
--- /dev/null
+++ b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr
@@ -0,0 +1,17 @@
+error[E0277]: the size for values of type `Self` cannot be known at compilation time
+  --> $DIR/trait-with-supertraits-needing-sized-self.rs:3:22
+   |
+LL | trait ArithmeticOps: Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + Div<Output=Self> {}
+   |                      ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time               - help: consider further restricting `Self`: `+ std::marker::Sized`
+   | 
+  ::: $SRC_DIR/libcore/ops/arith.rs:LL:COL
+   |
+LL | pub trait Add<Rhs = Self> {
+   |               --- required by this bound in `std::ops::Add`
+   |
+   = 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>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.