about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc/hir/mod.rs77
-rw-r--r--src/librustc/traits/error_reporting.rs81
-rw-r--r--src/librustc_mir/borrow_check/conflict_errors.rs64
-rw-r--r--src/test/ui/binop/binop-consume-args.stderr40
-rw-r--r--src/test/ui/binop/binop-move-semantics.stderr4
-rw-r--r--src/test/ui/borrowck/borrowck-unboxed-closures.stderr2
-rw-r--r--src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr2
-rw-r--r--src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr4
-rw-r--r--src/test/ui/issues/issue-34721.fixed2
-rw-r--r--src/test/ui/issues/issue-34721.stderr2
-rw-r--r--src/test/ui/once-cant-call-twice-on-heap.stderr2
-rw-r--r--src/test/ui/unop-move-semantics.stderr2
12 files changed, 128 insertions, 154 deletions
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index 66bb3a8d883..0b79f624709 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -16,9 +16,9 @@ use crate::ty::AdtKind;
 use crate::ty::query::Providers;
 use crate::util::nodemap::{NodeMap, FxHashSet};
 
-use errors::FatalError;
+use errors::{Applicability, DiagnosticBuilder, FatalError};
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
-use syntax::source_map::Spanned;
+use syntax::source_map::{Spanned, SourceMap};
 use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
 use syntax::ast::{Attribute, Label, LitKind, StrStyle, FloatTy, IntTy, UintTy};
 pub use syntax::ast::{Mutability, Constness, Unsafety, Movability, CaptureBy};
@@ -644,6 +644,79 @@ impl Generics {
             self.params.iter().map(|p| p.span).collect::<Vec<Span>>().into()
         }
     }
+
+    /// Suggest restricting a type param with a new bound.
+    pub fn suggest_constraining_type_param(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        param_name: &str,
+        constraint: &str,
+        source_map: &SourceMap,
+        span: Span,
+    ) -> bool {
+        let restrict_msg = "consider further restricting this bound";
+        if let Some(param) = self.params.iter().filter(|p| {
+            p.name.ident().as_str() == param_name
+        }).next() {
+            if param_name.starts_with("impl ") {
+                // `impl Trait` in argument:
+                // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
+                err.span_suggestion(
+                    param.span,
+                    restrict_msg,
+                    // `impl CurrentTrait + MissingTrait`
+                    format!("{} + {}", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            } else if self.where_clause.predicates.is_empty() &&
+                    param.bounds.is_empty()
+            {
+                // If there are no bounds whatsoever, suggest adding a constraint
+                // to the type parameter:
+                // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
+                err.span_suggestion(
+                    param.span,
+                    "consider restricting this bound",
+                    format!("{}: {}", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            } else if !self.where_clause.predicates.is_empty() {
+                // There is a `where` clause, so suggest expanding it:
+                // `fn foo<T>(t: T) where T: Debug {}` →
+                // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
+                err.span_suggestion(
+                    self.where_clause.span().unwrap().shrink_to_hi(),
+                    &format!("consider further restricting type parameter `{}`", param_name),
+                    format!(", {}: {}", param_name, constraint),
+                    Applicability::MachineApplicable,
+                );
+            } else {
+                // If there is no `where` clause lean towards constraining to the
+                // type parameter:
+                // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
+                // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
+                let sp = param.span.with_hi(span.hi());
+                let span = source_map.span_through_char(sp, ':');
+                if sp != param.span && sp != span {
+                    // Only suggest if we have high certainty that the span
+                    // covers the colon in `foo<T: Trait>`.
+                    err.span_suggestion(
+                        span,
+                        restrict_msg,
+                        format!("{}: {} + ", param_name, constraint),
+                        Applicability::MachineApplicable,
+                    );
+                } else {
+                    err.span_label(
+                        param.span,
+                        &format!("consider adding a `where {}: {}` bound", param_name, constraint),
+                    );
+                }
+            }
+            return true;
+        }
+        false
+    }
 }
 
 /// Synthetic type parameters are converted to another form during lowering; this allows
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 65d08ab03aa..db7c5c3f778 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -1091,7 +1091,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
     fn suggest_restricting_param_bound(
         &self,
-        err: &mut DiagnosticBuilder<'_>,
+        mut err: &mut DiagnosticBuilder<'_>,
         trait_ref: &ty::PolyTraitRef<'_>,
         body_id: hir::HirId,
     ) {
@@ -1102,7 +1102,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             _ => return,
         };
 
-        let mut suggest_restriction = |generics: &hir::Generics, msg| {
+        let suggest_restriction = |
+            generics: &hir::Generics,
+            msg,
+            err: &mut DiagnosticBuilder<'_>,
+        | {
             let span = generics.where_clause.span_for_predicates_or_empty_place();
             if !span.from_expansion() && span.desugaring_kind().is_none() {
                 err.span_suggestion(
@@ -1132,7 +1136,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     kind: hir::TraitItemKind::Method(..), ..
                 }) if param_ty && self_ty == self.tcx.types.self_param => {
                     // Restricting `Self` for a single method.
-                    suggest_restriction(&generics, "`Self`");
+                    suggest_restriction(&generics, "`Self`", err);
                     return;
                 }
 
@@ -1154,7 +1158,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     kind: hir::ItemKind::Impl(_, _, _, generics, ..), ..
                 }) if projection.is_some() => {
                     // Missing associated type bound.
-                    suggest_restriction(&generics, "the associated type");
+                    suggest_restriction(&generics, "the associated type", err);
                     return;
                 }
 
@@ -1183,68 +1187,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
                 if param_ty => {
                     // Missing generic type parameter bound.
-                    let restrict_msg = "consider further restricting this bound";
                     let param_name = self_ty.to_string();
-                    for param in generics.params.iter().filter(|p| {
-                        p.name.ident().as_str() == param_name
-                    }) {
-                        if param_name.starts_with("impl ") {
-                            // `impl Trait` in argument:
-                            // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
-                            err.span_suggestion(
-                                param.span,
-                                restrict_msg,
-                                // `impl CurrentTrait + MissingTrait`
-                                format!("{} + {}", param.name.ident(), trait_ref),
-                                Applicability::MachineApplicable,
-                            );
-                        } else if generics.where_clause.predicates.is_empty() &&
-                                param.bounds.is_empty()
-                        {
-                            // If there are no bounds whatsoever, suggest adding a constraint
-                            // to the type parameter:
-                            // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
-                            err.span_suggestion(
-                                param.span,
-                                "consider restricting this bound",
-                                format!("{}", trait_ref.to_predicate()),
-                                Applicability::MachineApplicable,
-                            );
-                        } else if !generics.where_clause.predicates.is_empty() {
-                            // There is a `where` clause, so suggest expanding it:
-                            // `fn foo<T>(t: T) where T: Debug {}` →
-                            // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
-                            err.span_suggestion(
-                                generics.where_clause.span().unwrap().shrink_to_hi(),
-                                &format!(
-                                    "consider further restricting type parameter `{}`",
-                                    param_name,
-                                ),
-                                format!(", {}", trait_ref.to_predicate()),
-                                Applicability::MachineApplicable,
-                            );
-                        } else {
-                            // If there is no `where` clause lean towards constraining to the
-                            // type parameter:
-                            // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
-                            // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
-                            let sp = param.span.with_hi(span.hi());
-                            let span = self.tcx.sess.source_map()
-                                .span_through_char(sp, ':');
-                            if sp != param.span && sp != span {
-                                // Only suggest if we have high certainty that the span
-                                // covers the colon in `foo<T: Trait>`.
-                                err.span_suggestion(span, restrict_msg, format!(
-                                    "{} + ",
-                                    trait_ref.to_predicate(),
-                                ), Applicability::MachineApplicable);
-                            } else {
-                                err.span_label(param.span, &format!(
-                                    "consider adding a `where {}` bound",
-                                    trait_ref.to_predicate(),
-                                ));
-                            }
-                        }
+                    let constraint = trait_ref.to_string();
+                    if generics.suggest_constraining_type_param(
+                        &mut err,
+                        &param_name,
+                        &constraint,
+                        self.tcx.sess.source_map(),
+                        *span,
+                    ) {
                         return;
                     }
                 }
diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs
index e3da090a62d..e9065abcebe 100644
--- a/src/librustc_mir/borrow_check/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/conflict_errors.rs
@@ -233,63 +233,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     let generics = tcx.generics_of(self.mir_def_id);
                     let param = generics.type_param(&param_ty, tcx);
                     let generics = tcx.hir().get_generics(self.mir_def_id).unwrap();
-                    let msg = "consider adding a `Copy` constraint to this type argument";
-                    for param in generics.params.iter().filter(|p| {
-                        p.name.ident().as_str() == param.name.as_str()
-                    }) {
-                        let param_name = param.name.ident().as_str();
-                        if param_name.starts_with("impl ") {
-                            // `impl Trait` in argument:
-                            // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
-                            err.span_suggestion(
-                                param.span,
-                                msg,
-                                // `impl CurrentTrait + MissingTrait`
-                                format!("{} + Copy", param_name),
-                                Applicability::MachineApplicable,
-                            );
-                        } else if generics.where_clause.predicates.is_empty() &&
-                            param.bounds.is_empty()
-                        {
-                            // If there are no bounds whatsoever, suggest adding a constraint
-                            // to the type parameter:
-                            // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
-                            err.span_suggestion(
-                                param.span,
-                                msg,
-                                format!("{}: Copy", param_name),
-                                Applicability::MachineApplicable,
-                            );
-                        } else if !generics.where_clause.predicates.is_empty() {
-                            // There is a `where` clause, so suggest expanding it:
-                            // `fn foo<T>(t: T) where T: Debug {}` →
-                            // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
-                            err.span_suggestion(
-                                generics.where_clause.span().unwrap().shrink_to_hi(),
-                                msg,
-                                format!(", {}: Copy", param_name),
-                                Applicability::MachineApplicable,
-                            );
-                        } else {
-                            // If there is no `where` clause lean towards constraining to the
-                            // type parameter:
-                            // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
-                            // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
-                            let sp = param.span.with_hi(span.hi());
-                            let span = tcx.sess.source_map()
-                                .span_through_char(sp, ':');
-                            if sp != param.span && sp != span {
-                                // Only suggest if we have high certainty that the span
-                                // covers the colon in `foo<T: Trait>`.
-                                err.span_suggestion(span, msg, format!(
-                                    "{}: Copy +",
-                                    param_name,
-                                ), Applicability::MachineApplicable);
-                            } else {
-                                err.span_label(param.span, msg);
-                            }
-                        }
-                    }
+                    generics.suggest_constraining_type_param(
+                        &mut err,
+                        &param.name.as_str(),
+                        "Copy",
+                        tcx.sess.source_map(),
+                        span,
+                    );
                 }
                 let span = if let Some(local) = place.as_local() {
                     let decl = &self.body.local_decls[local];
diff --git a/src/test/ui/binop/binop-consume-args.stderr b/src/test/ui/binop/binop-consume-args.stderr
index 5a6a2f92583..876e984ecb0 100644
--- a/src/test/ui/binop/binop-consume-args.stderr
+++ b/src/test/ui/binop/binop-consume-args.stderr
@@ -4,7 +4,7 @@ error[E0382]: use of moved value: `lhs`
 LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
    |        --                       --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
    |        |
-   |        help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
+   |        help: consider further restricting this bound: `A: Copy +`
 LL |     lhs + rhs;
    |     --- value moved here
 LL |     drop(lhs);
@@ -16,7 +16,7 @@ error[E0382]: use of moved value: `rhs`
 LL | fn add<A: Add<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
    |                              |
-   |                              help: consider adding a `Copy` constraint to this type argument: `B: Copy`
+   |                              help: consider restricting this bound: `B: Copy`
 LL |     lhs + rhs;
    |           --- value moved here
 LL |     drop(lhs);
@@ -29,7 +29,7 @@ error[E0382]: use of moved value: `lhs`
 LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
    |        --                       --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
    |        |
-   |        help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
+   |        help: consider further restricting this bound: `A: Copy +`
 LL |     lhs - rhs;
    |     --- value moved here
 LL |     drop(lhs);
@@ -41,7 +41,7 @@ error[E0382]: use of moved value: `rhs`
 LL | fn sub<A: Sub<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
    |                              |
-   |                              help: consider adding a `Copy` constraint to this type argument: `B: Copy`
+   |                              help: consider restricting this bound: `B: Copy`
 LL |     lhs - rhs;
    |           --- value moved here
 LL |     drop(lhs);
@@ -54,7 +54,7 @@ error[E0382]: use of moved value: `lhs`
 LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
    |        --                       --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
    |        |
-   |        help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
+   |        help: consider further restricting this bound: `A: Copy +`
 LL |     lhs * rhs;
    |     --- value moved here
 LL |     drop(lhs);
@@ -66,7 +66,7 @@ error[E0382]: use of moved value: `rhs`
 LL | fn mul<A: Mul<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
    |                              |
-   |                              help: consider adding a `Copy` constraint to this type argument: `B: Copy`
+   |                              help: consider restricting this bound: `B: Copy`
 LL |     lhs * rhs;
    |           --- value moved here
 LL |     drop(lhs);
@@ -79,7 +79,7 @@ error[E0382]: use of moved value: `lhs`
 LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
    |        --                       --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
    |        |
-   |        help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
+   |        help: consider further restricting this bound: `A: Copy +`
 LL |     lhs / rhs;
    |     --- value moved here
 LL |     drop(lhs);
@@ -91,7 +91,7 @@ error[E0382]: use of moved value: `rhs`
 LL | fn div<A: Div<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
    |                              |
-   |                              help: consider adding a `Copy` constraint to this type argument: `B: Copy`
+   |                              help: consider restricting this bound: `B: Copy`
 LL |     lhs / rhs;
    |           --- value moved here
 LL |     drop(lhs);
@@ -104,7 +104,7 @@ error[E0382]: use of moved value: `lhs`
 LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
    |        --                       --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
    |        |
-   |        help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
+   |        help: consider further restricting this bound: `A: Copy +`
 LL |     lhs % rhs;
    |     --- value moved here
 LL |     drop(lhs);
@@ -116,7 +116,7 @@ error[E0382]: use of moved value: `rhs`
 LL | fn rem<A: Rem<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
    |                              |
-   |                              help: consider adding a `Copy` constraint to this type argument: `B: Copy`
+   |                              help: consider restricting this bound: `B: Copy`
 LL |     lhs % rhs;
    |           --- value moved here
 LL |     drop(lhs);
@@ -129,7 +129,7 @@ error[E0382]: use of moved value: `lhs`
 LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
    |           --                          --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
    |           |
-   |           help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
+   |           help: consider further restricting this bound: `A: Copy +`
 LL |     lhs & rhs;
    |     --- value moved here
 LL |     drop(lhs);
@@ -141,7 +141,7 @@ error[E0382]: use of moved value: `rhs`
 LL | fn bitand<A: BitAnd<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                    -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
    |                                    |
-   |                                    help: consider adding a `Copy` constraint to this type argument: `B: Copy`
+   |                                    help: consider restricting this bound: `B: Copy`
 LL |     lhs & rhs;
    |           --- value moved here
 LL |     drop(lhs);
@@ -154,7 +154,7 @@ error[E0382]: use of moved value: `lhs`
 LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
    |          --                         --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
    |          |
-   |          help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
+   |          help: consider further restricting this bound: `A: Copy +`
 LL |     lhs | rhs;
    |     --- value moved here
 LL |     drop(lhs);
@@ -166,7 +166,7 @@ error[E0382]: use of moved value: `rhs`
 LL | fn bitor<A: BitOr<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                  -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
    |                                  |
-   |                                  help: consider adding a `Copy` constraint to this type argument: `B: Copy`
+   |                                  help: consider restricting this bound: `B: Copy`
 LL |     lhs | rhs;
    |           --- value moved here
 LL |     drop(lhs);
@@ -179,7 +179,7 @@ error[E0382]: use of moved value: `lhs`
 LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
    |           --                          --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
    |           |
-   |           help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
+   |           help: consider further restricting this bound: `A: Copy +`
 LL |     lhs ^ rhs;
    |     --- value moved here
 LL |     drop(lhs);
@@ -191,7 +191,7 @@ error[E0382]: use of moved value: `rhs`
 LL | fn bitxor<A: BitXor<B, Output=()>, B>(lhs: A, rhs: B) {
    |                                    -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
    |                                    |
-   |                                    help: consider adding a `Copy` constraint to this type argument: `B: Copy`
+   |                                    help: consider restricting this bound: `B: Copy`
 LL |     lhs ^ rhs;
    |           --- value moved here
 LL |     drop(lhs);
@@ -204,7 +204,7 @@ error[E0382]: use of moved value: `lhs`
 LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
    |        --                       --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
    |        |
-   |        help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
+   |        help: consider further restricting this bound: `A: Copy +`
 LL |     lhs << rhs;
    |     --- value moved here
 LL |     drop(lhs);
@@ -216,7 +216,7 @@ error[E0382]: use of moved value: `rhs`
 LL | fn shl<A: Shl<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
    |                              |
-   |                              help: consider adding a `Copy` constraint to this type argument: `B: Copy`
+   |                              help: consider restricting this bound: `B: Copy`
 LL |     lhs << rhs;
    |            --- value moved here
 LL |     drop(lhs);
@@ -229,7 +229,7 @@ error[E0382]: use of moved value: `lhs`
 LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
    |        --                       --- move occurs because `lhs` has type `A`, which does not implement the `Copy` trait
    |        |
-   |        help: consider adding a `Copy` constraint to this type argument: `A: Copy +`
+   |        help: consider further restricting this bound: `A: Copy +`
 LL |     lhs >> rhs;
    |     --- value moved here
 LL |     drop(lhs);
@@ -241,7 +241,7 @@ error[E0382]: use of moved value: `rhs`
 LL | fn shr<A: Shr<B, Output=()>, B>(lhs: A, rhs: B) {
    |                              -          --- move occurs because `rhs` has type `B`, which does not implement the `Copy` trait
    |                              |
-   |                              help: consider adding a `Copy` constraint to this type argument: `B: Copy`
+   |                              help: consider restricting this bound: `B: Copy`
 LL |     lhs >> rhs;
    |            --- value moved here
 LL |     drop(lhs);
diff --git a/src/test/ui/binop/binop-move-semantics.stderr b/src/test/ui/binop/binop-move-semantics.stderr
index 8efb73657fa..7552dc66974 100644
--- a/src/test/ui/binop/binop-move-semantics.stderr
+++ b/src/test/ui/binop/binop-move-semantics.stderr
@@ -4,7 +4,7 @@ error[E0382]: use of moved value: `x`
 LL | fn double_move<T: Add<Output=()>>(x: T) {
    |                --                 - move occurs because `x` has type `T`, which does not implement the `Copy` trait
    |                |
-   |                help: consider adding a `Copy` constraint to this type argument: `T: Copy +`
+   |                help: consider further restricting this bound: `T: Copy +`
 LL |     x
    |     - value moved here
 LL |     +
@@ -17,7 +17,7 @@ error[E0382]: borrow of moved value: `x`
 LL | fn move_then_borrow<T: Add<Output=()> + Clone>(x: T) {
    |                     --                         - move occurs because `x` has type `T`, which does not implement the `Copy` trait
    |                     |
-   |                     help: consider adding a `Copy` constraint to this type argument: `T: Copy +`
+   |                     help: consider further restricting this bound: `T: Copy +`
 LL |     x
    |     - value moved here
 LL |     +
diff --git a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr
index 5a0afda013e..5cd0471cd0d 100644
--- a/src/test/ui/borrowck/borrowck-unboxed-closures.stderr
+++ b/src/test/ui/borrowck/borrowck-unboxed-closures.stderr
@@ -22,7 +22,7 @@ error[E0382]: use of moved value: `f`
 LL | fn c<F:FnOnce(isize, isize) -> isize>(f: F) {
    |      --                               - move occurs because `f` has type `F`, which does not implement the `Copy` trait
    |      |
-   |      help: consider adding a `Copy` constraint to this type argument: `F: Copy +`
+   |      help: consider further restricting this bound: `F: Copy +`
 LL |     f(1, 2);
    |     - value moved here
 LL |     f(1, 2);
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
index afcb467ad47..5c38f47b363 100644
--- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr
@@ -7,7 +7,7 @@ LL |     where B : for<'ccx> Bar<'ccx>
    |               ------------------- required by this bound in `want_bar_for_any_ccx`
 ...
 LL |     where B : Qux
-   |                  - help: consider further restricting type parameter `B`: `, for<'ccx> B: Bar<'ccx>`
+   |                  - help: consider further restricting type parameter `B`: `, B: for<'ccx> Bar<'ccx>`
 ...
 LL |     want_bar_for_any_ccx(b);
    |                          ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
index 20913b4f28c..768bc6c7184 100644
--- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
+++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits.rs:18:26
    |
 LL |     where F : Foo<'x>
-   |                      - help: consider further restricting type parameter `F`: `, for<'tcx> F: Foo<'tcx>`
+   |                      - help: consider further restricting type parameter `F`: `, F: for<'tcx> Foo<'tcx>`
 ...
 LL |     want_foo_for_any_tcx(f);
    |                          ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F`
@@ -16,7 +16,7 @@ error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26
    |
 LL |     where B : Bar<'x>
-   |                      - help: consider further restricting type parameter `B`: `, for<'ccx> B: Bar<'ccx>`
+   |                      - help: consider further restricting type parameter `B`: `, B: for<'ccx> Bar<'ccx>`
 ...
 LL |     want_bar_for_any_ccx(b);
    |                          ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B`
diff --git a/src/test/ui/issues/issue-34721.fixed b/src/test/ui/issues/issue-34721.fixed
index 88f0345bde6..ba2810ee3d7 100644
--- a/src/test/ui/issues/issue-34721.fixed
+++ b/src/test/ui/issues/issue-34721.fixed
@@ -18,7 +18,7 @@ pub mod bar {
 mod baz {
     use bar;
     use Foo;
-    pub fn baz<T: Copy + Foo>(x: T) -> T {
+    pub fn baz<T: Copy +  Foo>(x: T) -> T {
         if 0 == 1 {
             bar::bar(x.zero())
         } else {
diff --git a/src/test/ui/issues/issue-34721.stderr b/src/test/ui/issues/issue-34721.stderr
index abf65afd7ed..3002b07e8c9 100644
--- a/src/test/ui/issues/issue-34721.stderr
+++ b/src/test/ui/issues/issue-34721.stderr
@@ -4,7 +4,7 @@ error[E0382]: use of moved value: `x`
 LL |     pub fn baz<T: Foo>(x: T) -> T {
    |                --      - move occurs because `x` has type `T`, which does not implement the `Copy` trait
    |                |
-   |                help: consider adding a `Copy` constraint to this type argument: `T: Copy +`
+   |                help: consider further restricting this bound: `T: Copy +`
 LL |         if 0 == 1 {
 LL |             bar::bar(x.zero())
    |                      - value moved here
diff --git a/src/test/ui/once-cant-call-twice-on-heap.stderr b/src/test/ui/once-cant-call-twice-on-heap.stderr
index 22f98c2a979..fd998060218 100644
--- a/src/test/ui/once-cant-call-twice-on-heap.stderr
+++ b/src/test/ui/once-cant-call-twice-on-heap.stderr
@@ -4,7 +4,7 @@ error[E0382]: use of moved value: `blk`
 LL | fn foo<F:FnOnce()>(blk: F) {
    |        --          --- move occurs because `blk` has type `F`, which does not implement the `Copy` trait
    |        |
-   |        help: consider adding a `Copy` constraint to this type argument: `F: Copy +`
+   |        help: consider further restricting this bound: `F: Copy +`
 LL |     blk();
    |     --- value moved here
 LL |     blk();
diff --git a/src/test/ui/unop-move-semantics.stderr b/src/test/ui/unop-move-semantics.stderr
index 0dbd3b8cd0d..092c419d7cb 100644
--- a/src/test/ui/unop-move-semantics.stderr
+++ b/src/test/ui/unop-move-semantics.stderr
@@ -4,7 +4,7 @@ error[E0382]: borrow of moved value: `x`
 LL | fn move_then_borrow<T: Not<Output=T> + Clone>(x: T) {
    |                     --                        - move occurs because `x` has type `T`, which does not implement the `Copy` trait
    |                     |
-   |                     help: consider adding a `Copy` constraint to this type argument: `T: Copy +`
+   |                     help: consider further restricting this bound: `T: Copy +`
 LL |     !x;
    |      - value moved here
 LL |