about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-12-19 11:33:00 +0000
committerbors <bors@rust-lang.org>2019-12-19 11:33:00 +0000
commit0de96d37fbcc54978458c18f5067cd9817669bc8 (patch)
tree9fb998a8d7f0d19bc4ad5a7e37ee1fa694e27de6
parentc605199e89572e586a5f37bc698c48b6a10896fb (diff)
parent06985c68592112ef256eb08140f38a30b602d35c (diff)
downloadrust-0de96d37fbcc54978458c18f5067cd9817669bc8.tar.gz
rust-0de96d37fbcc54978458c18f5067cd9817669bc8.zip
Auto merge of #67419 - Centril:rollup-v7b0ypv, r=Centril
Rollup of 8 pull requests

Successful merges:

 - #67189 (Unify binop wording)
 - #67270 (std: Implement `LineWriter::write_vectored`)
 - #67286 (Fix the configure.py TOML field for a couple LLVM options)
 - #67321 (make htons const fn)
 - #67382 (Remove some unnecessary `ATTR_*` constants.)
 - #67389 (Remove `SO_NOSIGPIPE` dummy variable on platforms that don't use it.)
 - #67394 (Remove outdated references to @T from comments)
 - #67406 (Suggest associated type when the specified one cannot be found)

Failed merges:

r? @ghost
-rwxr-xr-xsrc/bootstrap/configure.py4
-rw-r--r--src/librustc/ich/mod.rs22
-rw-r--r--src/librustc_incremental/assert_dep_graph.rs9
-rw-r--r--src/librustc_incremental/assert_module_sources.rs8
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs7
-rw-r--r--src/librustc_typeck/astconv.rs103
-rw-r--r--src/librustc_typeck/check/op.rs85
-rw-r--r--src/libstd/io/buffered.rs172
-rw-r--r--src/libstd/net/addr.rs14
-rw-r--r--src/libstd/net/mod.rs19
-rw-r--r--src/libstd/sys/unix/net.rs17
-rw-r--r--src/libstd/sys/vxworks/net.rs1
-rw-r--r--src/libsyntax/ptr.rs9
-rw-r--r--src/test/ui/autoderef-full-lval.rs4
-rw-r--r--src/test/ui/autoderef-full-lval.stderr4
-rw-r--r--src/test/ui/binary-op-on-double-ref.rs2
-rw-r--r--src/test/ui/binary-op-on-double-ref.stderr2
-rw-r--r--src/test/ui/binop/binop-bitxor-str.rs2
-rw-r--r--src/test/ui/binop/binop-bitxor-str.stderr2
-rw-r--r--src/test/ui/binop/binop-mul-bool.rs2
-rw-r--r--src/test/ui/binop/binop-mul-bool.stderr2
-rw-r--r--src/test/ui/binop/binop-typeck.rs2
-rw-r--r--src/test/ui/binop/binop-typeck.stderr2
-rw-r--r--src/test/ui/for/for-loop-type-error.rs2
-rw-r--r--src/test/ui/for/for-loop-type-error.stderr2
-rw-r--r--src/test/ui/issues/issue-14915.rs2
-rw-r--r--src/test/ui/issues/issue-14915.stderr2
-rw-r--r--src/test/ui/issues/issue-24363.rs2
-rw-r--r--src/test/ui/issues/issue-24363.stderr2
-rw-r--r--src/test/ui/issues/issue-28837.rs18
-rw-r--r--src/test/ui/issues/issue-28837.stderr18
-rw-r--r--src/test/ui/issues/issue-31076.rs4
-rw-r--r--src/test/ui/issues/issue-31076.stderr4
-rw-r--r--src/test/ui/issues/issue-35668.rs2
-rw-r--r--src/test/ui/issues/issue-35668.stderr2
-rw-r--r--src/test/ui/issues/issue-3820.rs2
-rw-r--r--src/test/ui/issues/issue-3820.stderr2
-rw-r--r--src/test/ui/issues/issue-40610.rs2
-rw-r--r--src/test/ui/issues/issue-40610.stderr2
-rw-r--r--src/test/ui/issues/issue-41394.rs2
-rw-r--r--src/test/ui/issues/issue-41394.stderr2
-rw-r--r--src/test/ui/issues/issue-47377.stderr2
-rw-r--r--src/test/ui/issues/issue-47380.stderr2
-rw-r--r--src/test/ui/or-patterns/or-patterns-syntactic-fail.rs2
-rw-r--r--src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr2
-rw-r--r--src/test/ui/pattern/pattern-tyvar-2.rs2
-rw-r--r--src/test/ui/pattern/pattern-tyvar-2.stderr2
-rw-r--r--src/test/ui/span/issue-39018.rs26
-rw-r--r--src/test/ui/span/issue-39018.stderr26
-rw-r--r--src/test/ui/span/type-binding.stderr2
-rw-r--r--src/test/ui/str/str-concat-on-double-ref.rs2
-rw-r--r--src/test/ui/str/str-concat-on-double-ref.stderr2
-rw-r--r--src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs2
-rw-r--r--src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr2
-rw-r--r--src/test/ui/traits/trait-resolution-in-overloaded-op.rs2
-rw-r--r--src/test/ui/traits/trait-resolution-in-overloaded-op.stderr2
-rw-r--r--src/test/ui/type/type-check/missing_trait_impl.rs2
-rw-r--r--src/test/ui/type/type-check/missing_trait_impl.stderr2
-rw-r--r--src/test/ui/vec/vec-res-add.rs2
-rw-r--r--src/test/ui/vec/vec-res-add.stderr2
60 files changed, 435 insertions, 217 deletions
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index bb6041d7f31..7cfc5385e21 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -59,13 +59,13 @@ o("full-tools", None, "enable all tools")
 o("lld", "rust.lld", "build lld")
 o("lldb", "rust.lldb", "build lldb")
 o("missing-tools", "dist.missing-tools", "allow failures when building tools")
-o("use-libcxx", "llvm.use_libcxx", "build LLVM with libc++")
+o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++")
 
 o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags")
 o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags")
 o("ldflags", "llvm.ldflags", "build LLVM with these extra linker flags")
 
-o("llvm-libunwind", "rust.llvm_libunwind", "use LLVM libunwind")
+o("llvm-libunwind", "rust.llvm-libunwind", "use LLVM libunwind")
 
 # Optimization and debugging options. These may be overridden by the release
 # channel, etc.
diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs
index ece438266c0..cd2e32de9d5 100644
--- a/src/librustc/ich/mod.rs
+++ b/src/librustc/ich/mod.rs
@@ -12,21 +12,13 @@ mod impls_hir;
 mod impls_ty;
 mod impls_syntax;
 
-pub const ATTR_DIRTY: Symbol = sym::rustc_dirty;
-pub const ATTR_CLEAN: Symbol = sym::rustc_clean;
-pub const ATTR_IF_THIS_CHANGED: Symbol = sym::rustc_if_this_changed;
-pub const ATTR_THEN_THIS_WOULD_NEED: Symbol = sym::rustc_then_this_would_need;
-pub const ATTR_PARTITION_REUSED: Symbol = sym::rustc_partition_reused;
-pub const ATTR_PARTITION_CODEGENED: Symbol = sym::rustc_partition_codegened;
-pub const ATTR_EXPECTED_CGU_REUSE: Symbol = sym::rustc_expected_cgu_reuse;
-
 pub const IGNORED_ATTRIBUTES: &[Symbol] = &[
     sym::cfg,
-    ATTR_IF_THIS_CHANGED,
-    ATTR_THEN_THIS_WOULD_NEED,
-    ATTR_DIRTY,
-    ATTR_CLEAN,
-    ATTR_PARTITION_REUSED,
-    ATTR_PARTITION_CODEGENED,
-    ATTR_EXPECTED_CGU_REUSE,
+    sym::rustc_if_this_changed,
+    sym::rustc_then_this_would_need,
+    sym::rustc_dirty,
+    sym::rustc_clean,
+    sym::rustc_partition_reused,
+    sym::rustc_partition_codegened,
+    sym::rustc_expected_cgu_reuse,
 ];
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index 07d426af6ee..e3e3b0b1748 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -44,11 +44,10 @@ use rustc_data_structures::graph::implementation::{
 };
 use rustc::hir;
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
-use rustc::ich::{ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED};
 use std::env;
 use std::fs::{self, File};
 use std::io::Write;
-use syntax::ast;
+use syntax::{ast, symbol::sym};
 use syntax_pos::Span;
 
 pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
@@ -78,7 +77,7 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) {
             assert!(tcx.sess.opts.debugging_opts.query_dep_graph,
                     "cannot use the `#[{}]` or `#[{}]` annotations \
                     without supplying `-Z query-dep-graph`",
-                    ATTR_IF_THIS_CHANGED, ATTR_THEN_THIS_WOULD_NEED);
+                    sym::rustc_if_this_changed, sym::rustc_then_this_would_need);
         }
 
         // Check paths.
@@ -114,7 +113,7 @@ impl IfThisChanged<'tcx> {
         let def_id = self.tcx.hir().local_def_id(hir_id);
         let def_path_hash = self.tcx.def_path_hash(def_id);
         for attr in attrs {
-            if attr.check_name(ATTR_IF_THIS_CHANGED) {
+            if attr.check_name(sym::rustc_if_this_changed) {
                 let dep_node_interned = self.argument(attr);
                 let dep_node = match dep_node_interned {
                     None => def_path_hash.to_dep_node(DepKind::Hir),
@@ -130,7 +129,7 @@ impl IfThisChanged<'tcx> {
                     }
                 };
                 self.if_this_changed.push((attr.span, def_id, dep_node));
-            } else if attr.check_name(ATTR_THEN_THIS_WOULD_NEED) {
+            } else if attr.check_name(sym::rustc_then_this_would_need) {
                 let dep_node_interned = self.argument(attr);
                 let dep_node = match dep_node_interned {
                     Some(n) => {
diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs
index c2e3fa8f28d..1a675ea002c 100644
--- a/src/librustc_incremental/assert_module_sources.rs
+++ b/src/librustc_incremental/assert_module_sources.rs
@@ -28,8 +28,6 @@ use rustc::ty::TyCtxt;
 use std::collections::BTreeSet;
 use syntax::ast;
 use syntax::symbol::{Symbol, sym};
-use rustc::ich::{ATTR_PARTITION_REUSED, ATTR_PARTITION_CODEGENED,
-                 ATTR_EXPECTED_CGU_REUSE};
 
 pub fn assert_module_sources(tcx: TyCtxt<'_>) {
     tcx.dep_graph.with_ignore(|| {
@@ -62,11 +60,11 @@ struct AssertModuleSource<'tcx> {
 
 impl AssertModuleSource<'tcx> {
     fn check_attr(&self, attr: &ast::Attribute) {
-        let (expected_reuse, comp_kind) = if attr.check_name(ATTR_PARTITION_REUSED) {
+        let (expected_reuse, comp_kind) = if attr.check_name(sym::rustc_partition_reused) {
             (CguReuse::PreLto, ComparisonKind::AtLeast)
-        } else if attr.check_name(ATTR_PARTITION_CODEGENED) {
+        } else if attr.check_name(sym::rustc_partition_codegened) {
             (CguReuse::No, ComparisonKind::Exact)
-        } else if attr.check_name(ATTR_EXPECTED_CGU_REUSE) {
+        } else if attr.check_name(sym::rustc_expected_cgu_reuse) {
             match &*self.field(attr, sym::kind).as_str() {
                 "no" => (CguReuse::No, ComparisonKind::Exact),
                 "pre-lto" => (CguReuse::PreLto, ComparisonKind::Exact),
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index ea156a94ea1..c919db070a6 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -22,7 +22,6 @@ use rustc::hir::Node as HirNode;
 use rustc::hir::def_id::DefId;
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir::intravisit;
-use rustc::ich::{ATTR_DIRTY, ATTR_CLEAN};
 use rustc::ty::TyCtxt;
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::FxHashSet;
@@ -224,7 +223,7 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
 
         let mut all_attrs = FindAllAttrs {
             tcx,
-            attr_names: vec![ATTR_DIRTY, ATTR_CLEAN],
+            attr_names: vec![sym::rustc_dirty, sym::rustc_clean],
             found_attrs: vec![],
         };
         intravisit::walk_crate(&mut all_attrs, krate);
@@ -246,9 +245,9 @@ impl DirtyCleanVisitor<'tcx> {
     fn assertion_maybe(&mut self, item_id: hir::HirId, attr: &Attribute)
         -> Option<Assertion>
     {
-        let is_clean = if attr.check_name(ATTR_DIRTY) {
+        let is_clean = if attr.check_name(sym::rustc_dirty) {
             false
-        } else if attr.check_name(ATTR_CLEAN) {
+        } else if attr.check_name(sym::rustc_clean) {
             true
         } else {
             // skip: not rustc_clean/dirty
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index af978d5095e..290f86d626e 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1145,11 +1145,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         } else {
             // Otherwise, we have to walk through the supertraits to find
             // those that do.
-            let candidates = traits::supertraits(tcx, trait_ref).filter(|r| {
-                self.trait_defines_associated_type_named(r.def_id(), binding.item_name)
-            });
             self.one_bound_for_assoc_type(
-                candidates,
+                || traits::supertraits(tcx, trait_ref),
                 &trait_ref.print_only_trait_path().to_string(),
                 binding.item_name,
                 binding.span
@@ -1531,50 +1528,48 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         debug!("find_bound_for_assoc_item: predicates={:#?}", predicates);
 
-        let bounds = predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref());
-
-        // Check that there is exactly one way to find an associated type with the
-        // correct name.
-        let suitable_bounds = traits::transitive_bounds(tcx, bounds)
-            .filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name));
-
         let param_hir_id = tcx.hir().as_local_hir_id(ty_param_def_id).unwrap();
         let param_name = tcx.hir().ty_param_name(param_hir_id);
-        self.one_bound_for_assoc_type(suitable_bounds,
-                                      &param_name.as_str(),
-                                      assoc_name,
-                                      span)
+        self.one_bound_for_assoc_type(
+            || traits::transitive_bounds(tcx, predicates
+                .iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref())),
+            &param_name.as_str(),
+            assoc_name,
+            span,
+        )
     }
 
-    // Checks that `bounds` contains exactly one element and reports appropriate
-    // errors otherwise.
     fn one_bound_for_assoc_type<I>(&self,
-                                   mut bounds: I,
+                                   all_candidates: impl Fn() -> I,
                                    ty_param_name: &str,
                                    assoc_name: ast::Ident,
                                    span: Span)
         -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
         where I: Iterator<Item = ty::PolyTraitRef<'tcx>>
     {
-        let bound = match bounds.next() {
+        let mut matching_candidates = all_candidates().filter(|r| {
+            self.trait_defines_associated_type_named(r.def_id(), assoc_name)
+        });
+
+        let bound = match matching_candidates.next() {
             Some(bound) => bound,
             None => {
-                struct_span_err!(self.tcx().sess, span, E0220,
-                                 "associated type `{}` not found for `{}`",
-                                 assoc_name,
-                                 ty_param_name)
-                    .span_label(span, format!("associated type `{}` not found", assoc_name))
-                    .emit();
+                self.complain_about_assoc_type_not_found(
+                    all_candidates,
+                    ty_param_name,
+                    assoc_name,
+                    span
+                );
                 return Err(ErrorReported);
             }
         };
 
         debug!("one_bound_for_assoc_type: bound = {:?}", bound);
 
-        if let Some(bound2) = bounds.next() {
+        if let Some(bound2) = matching_candidates.next() {
             debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2);
 
-            let bounds = iter::once(bound).chain(iter::once(bound2)).chain(bounds);
+            let bounds = iter::once(bound).chain(iter::once(bound2)).chain(matching_candidates);
             let mut err = struct_span_err!(
                 self.tcx().sess, span, E0221,
                 "ambiguous associated type `{}` in bounds of `{}`",
@@ -1606,6 +1601,50 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         return Ok(bound);
     }
 
+    fn complain_about_assoc_type_not_found<I>(&self,
+                                              all_candidates: impl Fn() -> I,
+                                              ty_param_name: &str,
+                                              assoc_name: ast::Ident,
+                                              span: Span)
+    where I: Iterator<Item = ty::PolyTraitRef<'tcx>> {
+        let mut err = struct_span_err!(self.tcx().sess, span, E0220,
+                                 "associated type `{}` not found for `{}`",
+                                 assoc_name,
+                                 ty_param_name);
+
+        let all_candidate_names: Vec<_> = all_candidates()
+            .map(|r| self.tcx().associated_items(r.def_id()))
+            .flatten()
+            .filter_map(|item|
+                if item.kind == ty::AssocKind::Type {
+                    Some(item.ident.name)
+                } else {
+                    None
+                }
+            )
+            .collect();
+
+        if let Some(suggested_name) = find_best_match_for_name(
+            all_candidate_names.iter(),
+            &assoc_name.as_str(),
+            None,
+        ) {
+            err.span_suggestion(
+                span,
+                "there is an associated type with a similar name",
+                suggested_name.to_string(),
+                Applicability::MaybeIncorrect,
+            );
+        } else {
+            err.span_label(
+                span,
+                format!("associated type `{}` not found", assoc_name)
+            );
+        }
+
+        err.emit();
+    }
+
     // Create a type from a path to an associated type.
     // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
     // and item_segment is the path segment for `D`. We return a type and a def for
@@ -1660,10 +1699,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     }
                 };
 
-                let candidates = traits::supertraits(tcx, ty::Binder::bind(trait_ref))
-                    .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_ident));
-
-                self.one_bound_for_assoc_type(candidates, "Self", assoc_ident, span)?
+                self.one_bound_for_assoc_type(
+                    || traits::supertraits(tcx, ty::Binder::bind(trait_ref)),
+                    "Self",
+                    assoc_ident,
+                    span
+                )?
             }
             (&ty::Param(_), Res::SelfTy(Some(param_did), None)) |
             (&ty::Param(_), Res::Def(DefKind::TyParam, param_did)) => {
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 321faa4a322..4f20a91e4b0 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -334,10 +334,70 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             err.emit();
                         }
                         IsAssign::No => {
+                            let (message, missing_trait) = match op.node {
+                                hir::BinOpKind::Add    => {
+                                    (format!("cannot add `{}` to `{}`", rhs_ty, lhs_ty),
+                                    Some("std::ops::Add"))
+                                },
+                                hir::BinOpKind::Sub    => {
+                                    (format!("cannot substract `{}` from `{}`", rhs_ty, lhs_ty),
+                                    Some("std::ops::Sub"))
+                                },
+                                hir::BinOpKind::Mul    => {
+                                    (format!("cannot multiply `{}` to `{}`", rhs_ty, lhs_ty),
+                                    Some("std::ops::Mul"))
+                                },
+                                hir::BinOpKind::Div    => {
+                                    (format!("cannot divide `{}` by `{}`", lhs_ty, rhs_ty),
+                                    Some("std::ops::Div"))
+                                },
+                                hir::BinOpKind::Rem    => {
+                                    (format!("cannot mod `{}` by `{}`", lhs_ty, rhs_ty),
+                                    Some("std::ops::Rem"))
+                                },
+                                hir::BinOpKind::BitAnd => {
+                                    (format!("no implementation for `{} & {}`", lhs_ty, rhs_ty),
+                                    Some("std::ops::BitAnd"))
+                                },
+                                hir::BinOpKind::BitXor => {
+                                    (format!("no implementation for `{} ^ {}`", lhs_ty, rhs_ty),
+                                    Some("std::ops::BitXor"))
+                                },
+                                hir::BinOpKind::BitOr  => {
+                                    (format!("no implementation for `{} | {}`", lhs_ty, rhs_ty),
+                                    Some("std::ops::BitOr"))
+                                },
+                                hir::BinOpKind::Shl    => {
+                                    (format!("no implementation for `{} << {}`", lhs_ty, rhs_ty),
+                                    Some("std::ops::Shl"))
+                                },
+                                hir::BinOpKind::Shr    => {
+                                    (format!("no implementation for `{} >> {}`", lhs_ty, rhs_ty),
+                                    Some("std::ops::Shr"))
+                                },
+                                hir::BinOpKind::Eq |
+                                hir::BinOpKind::Ne     => {
+                                    (format!(
+                                            "binary operation `{}` cannot be applied to type `{}`",
+                                            op.node.as_str(), lhs_ty),
+                                    Some("std::cmp::PartialEq"))
+                                },
+                                hir::BinOpKind::Lt |
+                                hir::BinOpKind::Le |
+                                hir::BinOpKind::Gt |
+                                hir::BinOpKind::Ge     => {
+                                    (format!(
+                                            "binary operation `{}` cannot be applied to type `{}`",
+                                            op.node.as_str(), lhs_ty),
+                                    Some("std::cmp::PartialOrd"))
+                                }
+                                _ => (format!(
+                                        "binary operation `{}` cannot be applied to type `{}`",
+                                        op.node.as_str(), lhs_ty),
+                                    None)
+                            };
                             let mut err = struct_span_err!(self.tcx.sess, op.span, E0369,
-                                "binary operation `{}` cannot be applied to type `{}`",
-                                op.node.as_str(),
-                                lhs_ty);
+                                "{}", message.as_str());
 
                             let mut involves_fn = false;
                             if !lhs_expr.span.eq(&rhs_expr.span) {
@@ -382,25 +442,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                     }
                                 }
                             }
-                            let missing_trait = match op.node {
-                                hir::BinOpKind::Add    => Some("std::ops::Add"),
-                                hir::BinOpKind::Sub    => Some("std::ops::Sub"),
-                                hir::BinOpKind::Mul    => Some("std::ops::Mul"),
-                                hir::BinOpKind::Div    => Some("std::ops::Div"),
-                                hir::BinOpKind::Rem    => Some("std::ops::Rem"),
-                                hir::BinOpKind::BitAnd => Some("std::ops::BitAnd"),
-                                hir::BinOpKind::BitXor => Some("std::ops::BitXor"),
-                                hir::BinOpKind::BitOr  => Some("std::ops::BitOr"),
-                                hir::BinOpKind::Shl    => Some("std::ops::Shl"),
-                                hir::BinOpKind::Shr    => Some("std::ops::Shr"),
-                                hir::BinOpKind::Eq |
-                                hir::BinOpKind::Ne => Some("std::cmp::PartialEq"),
-                                hir::BinOpKind::Lt |
-                                hir::BinOpKind::Le |
-                                hir::BinOpKind::Gt |
-                                hir::BinOpKind::Ge => Some("std::cmp::PartialOrd"),
-                                _ => None
-                            };
                             if let Some(missing_trait) = missing_trait {
                                 if op.node == hir::BinOpKind::Add &&
                                     self.check_str_addition(
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index 8e81b292f6f..df259dc2f56 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -989,6 +989,68 @@ impl<W: Write> Write for LineWriter<W> {
         }
     }
 
+    // Vectored writes are very similar to the writes above, but adjusted for
+    // the list of buffers that we have to write.
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        if self.need_flush {
+            self.flush()?;
+        }
+
+        // Find the last newline, and failing that write the whole buffer
+        let last_newline = bufs
+            .iter()
+            .enumerate()
+            .rev()
+            .filter_map(|(i, buf)| {
+                let pos = memchr::memrchr(b'\n', buf)?;
+                Some((i, pos))
+            })
+            .next();
+        let (i, j) = match last_newline {
+            Some(pair) => pair,
+            None => return self.inner.write_vectored(bufs),
+        };
+        let (prefix, suffix) = bufs.split_at(i);
+        let (buf, suffix) = suffix.split_at(1);
+        let buf = &buf[0];
+
+        // Write everything up to the last newline, flushing afterwards. Note
+        // that only if we finished our entire `write_vectored` do we try the
+        // subsequent
+        // `write`
+        let mut n = 0;
+        let prefix_amt = prefix.iter().map(|i| i.len()).sum();
+        if prefix_amt > 0 {
+            n += self.inner.write_vectored(prefix)?;
+            self.need_flush = true;
+        }
+        if n == prefix_amt {
+            match self.inner.write(&buf[..=j]) {
+                Ok(m) => n += m,
+                Err(e) if n == 0 => return Err(e),
+                Err(_) => return Ok(n),
+            }
+            self.need_flush = true;
+        }
+        if self.flush().is_err() || n != j + 1 + prefix_amt {
+            return Ok(n);
+        }
+
+        // ... and now write out everything remaining
+        match self.inner.write(&buf[j + 1..]) {
+            Ok(i) => n += i,
+            Err(_) => return Ok(n),
+        }
+
+        if suffix.iter().map(|s| s.len()).sum::<usize>() == 0 {
+            return Ok(n)
+        }
+        match self.inner.write_vectored(suffix) {
+            Ok(i) => Ok(n + i),
+            Err(_) => Ok(n),
+        }
+    }
+
     fn flush(&mut self) -> io::Result<()> {
         self.inner.flush()?;
         self.need_flush = false;
@@ -1015,7 +1077,7 @@ where
 #[cfg(test)]
 mod tests {
     use crate::io::prelude::*;
-    use crate::io::{self, BufReader, BufWriter, LineWriter, SeekFrom};
+    use crate::io::{self, BufReader, BufWriter, LineWriter, SeekFrom, IoSlice};
     use crate::sync::atomic::{AtomicUsize, Ordering};
     use crate::thread;
 
@@ -1483,4 +1545,112 @@ mod tests {
 
         assert_eq!(l.write(b"a").unwrap_err().kind(), io::ErrorKind::Other)
     }
+
+    #[test]
+    fn line_vectored() {
+        let mut a = LineWriter::new(Vec::new());
+        assert_eq!(
+            a.write_vectored(&[
+                IoSlice::new(&[]),
+                IoSlice::new(b"\n"),
+                IoSlice::new(&[]),
+                IoSlice::new(b"a"),
+            ])
+            .unwrap(),
+            2,
+        );
+        assert_eq!(a.get_ref(), b"\n");
+
+        assert_eq!(
+            a.write_vectored(&[
+                IoSlice::new(&[]),
+                IoSlice::new(b"b"),
+                IoSlice::new(&[]),
+                IoSlice::new(b"a"),
+                IoSlice::new(&[]),
+                IoSlice::new(b"c"),
+            ])
+            .unwrap(),
+            3,
+        );
+        assert_eq!(a.get_ref(), b"\n");
+        a.flush().unwrap();
+        assert_eq!(a.get_ref(), b"\nabac");
+        assert_eq!(a.write_vectored(&[]).unwrap(), 0);
+        assert_eq!(
+            a.write_vectored(&[
+                IoSlice::new(&[]),
+                IoSlice::new(&[]),
+                IoSlice::new(&[]),
+                IoSlice::new(&[]),
+            ])
+            .unwrap(),
+            0,
+        );
+        assert_eq!(a.write_vectored(&[IoSlice::new(b"a\nb"),]).unwrap(), 3);
+        assert_eq!(a.get_ref(), b"\nabaca\n");
+    }
+
+    #[test]
+    fn line_vectored_partial_and_errors() {
+        enum Call {
+            Write { inputs: Vec<&'static [u8]>, output: io::Result<usize> },
+            Flush { output: io::Result<()> },
+        }
+        struct Writer {
+            calls: Vec<Call>,
+        }
+
+        impl Write for Writer {
+            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+                self.write_vectored(&[IoSlice::new(buf)])
+            }
+
+            fn write_vectored(&mut self, buf: &[IoSlice<'_>]) -> io::Result<usize> {
+                match self.calls.pop().unwrap() {
+                    Call::Write { inputs, output } => {
+                        assert_eq!(inputs, buf.iter().map(|b| &**b).collect::<Vec<_>>());
+                        output
+                    }
+                    _ => panic!("unexpected call to write"),
+                }
+            }
+
+            fn flush(&mut self) -> io::Result<()> {
+                match self.calls.pop().unwrap() {
+                    Call::Flush { output } => output,
+                    _ => panic!("unexpected call to flush"),
+                }
+            }
+        }
+
+        impl Drop for Writer {
+            fn drop(&mut self) {
+                if !thread::panicking() {
+                    assert_eq!(self.calls.len(), 0);
+                }
+            }
+        }
+
+        // partial writes keep going
+        let mut a = LineWriter::new(Writer { calls: Vec::new() });
+        a.write_vectored(&[IoSlice::new(&[]), IoSlice::new(b"abc")]).unwrap();
+        a.get_mut().calls.push(Call::Flush { output: Ok(()) });
+        a.get_mut().calls.push(Call::Write { inputs: vec![b"bcx\n"], output: Ok(4) });
+        a.get_mut().calls.push(Call::Write { inputs: vec![b"abcx\n"], output: Ok(1) });
+        a.write_vectored(&[IoSlice::new(b"x"), IoSlice::new(b"\n")]).unwrap();
+        a.get_mut().calls.push(Call::Flush { output: Ok(()) });
+        a.flush().unwrap();
+
+        // erroneous writes stop and don't write more
+        a.get_mut().calls.push(Call::Write { inputs: vec![b"x\n"], output: Err(err()) });
+        assert_eq!(a.write_vectored(&[IoSlice::new(b"x"), IoSlice::new(b"\na")]).unwrap(), 2);
+        a.get_mut().calls.push(Call::Flush { output: Ok(()) });
+        a.get_mut().calls.push(Call::Write { inputs: vec![b"x\n"], output: Ok(2) });
+        a.flush().unwrap();
+
+        fn err() -> io::Error {
+            io::Error::new(io::ErrorKind::Other, "x")
+        }
+    }
 }
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index d5f4ece726b..a9d88370c61 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -4,7 +4,7 @@ use crate::hash;
 use crate::io;
 use crate::iter;
 use crate::mem;
-use crate::net::{hton, ntoh, IpAddr, Ipv4Addr, Ipv6Addr};
+use crate::net::{htons, ntohs, IpAddr, Ipv4Addr, Ipv6Addr};
 use crate::option;
 use crate::slice;
 use crate::sys::net::netc as c;
@@ -276,7 +276,7 @@ impl SocketAddrV4 {
         SocketAddrV4 {
             inner: c::sockaddr_in {
                 sin_family: c::AF_INET as c::sa_family_t,
-                sin_port: hton(port),
+                sin_port: htons(port),
                 sin_addr: *ip.as_inner(),
                 ..unsafe { mem::zeroed() }
             },
@@ -326,7 +326,7 @@ impl SocketAddrV4 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn port(&self) -> u16 {
-        ntoh(self.inner.sin_port)
+        ntohs(self.inner.sin_port)
     }
 
     /// Changes the port number associated with this socket address.
@@ -342,7 +342,7 @@ impl SocketAddrV4 {
     /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_port(&mut self, new_port: u16) {
-        self.inner.sin_port = hton(new_port);
+        self.inner.sin_port = htons(new_port);
     }
 }
 
@@ -368,7 +368,7 @@ impl SocketAddrV6 {
         SocketAddrV6 {
             inner: c::sockaddr_in6 {
                 sin6_family: c::AF_INET6 as c::sa_family_t,
-                sin6_port: hton(port),
+                sin6_port: htons(port),
                 sin6_addr: *ip.as_inner(),
                 sin6_flowinfo: flowinfo,
                 sin6_scope_id: scope_id,
@@ -420,7 +420,7 @@ impl SocketAddrV6 {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn port(&self) -> u16 {
-        ntoh(self.inner.sin6_port)
+        ntohs(self.inner.sin6_port)
     }
 
     /// Changes the port number associated with this socket address.
@@ -436,7 +436,7 @@ impl SocketAddrV6 {
     /// ```
     #[stable(feature = "sockaddr_setters", since = "1.9.0")]
     pub fn set_port(&mut self, new_port: u16) {
-        self.inner.sin6_port = hton(new_port);
+        self.inner.sin6_port = htons(new_port);
     }
 
     /// Returns the flow information associated with this address.
diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs
index b68146939fd..8652ed8b046 100644
--- a/src/libstd/net/mod.rs
+++ b/src/libstd/net/mod.rs
@@ -85,21 +85,10 @@ pub enum Shutdown {
     Both,
 }
 
-#[doc(hidden)]
-trait NetInt {
-    fn from_be(i: Self) -> Self;
-    fn to_be(&self) -> Self;
-}
-macro_rules! doit {
-    ($($t:ident)*) => ($(impl NetInt for $t {
-        fn from_be(i: Self) -> Self { <$t>::from_be(i) }
-        fn to_be(&self) -> Self { <$t>::to_be(*self) }
-    })*)
-}
-doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
-
-fn hton<I: NetInt>(i: I) -> I { i.to_be() }
-fn ntoh<I: NetInt>(i: I) -> I { I::from_be(i) }
+#[inline]
+const fn htons(i: u16) -> u16 { i.to_be() }
+#[inline]
+const fn ntohs(i: u16) -> u16 { u16::from_be(i) }
 
 fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
     where F: FnMut(io::Result<&SocketAddr>) -> io::Result<T>
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index 946b2b9d8de..5d101ed1f2e 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -28,14 +28,6 @@ use libc::SOCK_CLOEXEC;
 #[cfg(not(target_os = "linux"))]
 const SOCK_CLOEXEC: c_int = 0;
 
-// Another conditional constant for name resolution: Macos et iOS use
-// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket.
-// Other platforms do otherwise.
-#[cfg(target_vendor = "apple")]
-use libc::SO_NOSIGPIPE;
-#[cfg(not(target_vendor = "apple"))]
-const SO_NOSIGPIPE: c_int = 0;
-
 pub struct Socket(FileDesc);
 
 pub fn init() {}
@@ -89,9 +81,12 @@ impl Socket {
             let fd = FileDesc::new(fd);
             fd.set_cloexec()?;
             let socket = Socket(fd);
-            if cfg!(target_vendor = "apple") {
-                setsockopt(&socket, libc::SOL_SOCKET, SO_NOSIGPIPE, 1)?;
-            }
+
+            // macOS and iOS use `SO_NOSIGPIPE` as a `setsockopt`
+            // flag to disable `SIGPIPE` emission on socket.
+            #[cfg(target_vendor = "apple")]
+            setsockopt(&socket, libc::SOL_SOCKET, libc::SO_NOSIGPIPE, 1)?;
+
             Ok(socket)
         }
     }
diff --git a/src/libstd/sys/vxworks/net.rs b/src/libstd/sys/vxworks/net.rs
index 85f5fcff2c2..54466ff2c2e 100644
--- a/src/libstd/sys/vxworks/net.rs
+++ b/src/libstd/sys/vxworks/net.rs
@@ -19,7 +19,6 @@ pub extern crate libc as netc;
 pub type wrlen_t = size_t;
 
 const SOCK_CLOEXEC: c_int = 0;
-const SO_NOSIGPIPE: c_int = 0;
 
 pub struct Socket(FileDesc);
 
diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs
index d987dc855b6..e75cc8b1756 100644
--- a/src/libsyntax/ptr.rs
+++ b/src/libsyntax/ptr.rs
@@ -1,17 +1,12 @@
 //! The AST pointer.
 //!
-//! Provides `P<T>`, a frozen owned smart pointer, as a replacement for `@T` in
-//! the AST.
+//! Provides `P<T>`, a frozen owned smart pointer.
 //!
 //! # Motivations and benefits
 //!
 //! * **Identity**: sharing AST nodes is problematic for the various analysis
 //!   passes (e.g., one may be able to bypass the borrow checker with a shared
-//!   `ExprKind::AddrOf` node taking a mutable borrow). The only reason `@T` in the
-//!   AST hasn't caused issues is because of inefficient folding passes which
-//!   would always deduplicate any such shared nodes. Even if the AST were to
-//!   switch to an arena, this would still hold, i.e., it couldn't use `&'a T`,
-//!   but rather a wrapper like `P<'a, T>`.
+//!   `ExprKind::AddrOf` node taking a mutable borrow).
 //!
 //! * **Immutability**: `P<T>` disallows mutating its inner `T`, unlike `Box<T>`
 //!   (unless it contains an `Unsafe` interior, but that may be denied later).
diff --git a/src/test/ui/autoderef-full-lval.rs b/src/test/ui/autoderef-full-lval.rs
index db09d036ad3..4bef1012e33 100644
--- a/src/test/ui/autoderef-full-lval.rs
+++ b/src/test/ui/autoderef-full-lval.rs
@@ -13,13 +13,13 @@ fn main() {
     let a: Clam = Clam{x: box 1, y: box 2};
     let b: Clam = Clam{x: box 10, y: box 20};
     let z: isize = a.x + b.y;
-    //~^ ERROR binary operation `+` cannot be applied to type `std::boxed::Box<isize>`
+    //~^ ERROR cannot add `std::boxed::Box<isize>` to `std::boxed::Box<isize>`
     println!("{}", z);
     assert_eq!(z, 21);
     let forty: Fish = Fish{a: box 40};
     let two: Fish = Fish{a: box 2};
     let answer: isize = forty.a + two.a;
-    //~^ ERROR binary operation `+` cannot be applied to type `std::boxed::Box<isize>`
+    //~^ ERROR cannot add `std::boxed::Box<isize>` to `std::boxed::Box<isize>`
     println!("{}", answer);
     assert_eq!(answer, 42);
 }
diff --git a/src/test/ui/autoderef-full-lval.stderr b/src/test/ui/autoderef-full-lval.stderr
index c9f3e8b2e26..e2870ef8062 100644
--- a/src/test/ui/autoderef-full-lval.stderr
+++ b/src/test/ui/autoderef-full-lval.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `std::boxed::Box<isize>`
+error[E0369]: cannot add `std::boxed::Box<isize>` to `std::boxed::Box<isize>`
   --> $DIR/autoderef-full-lval.rs:15:24
    |
 LL |     let z: isize = a.x + b.y;
@@ -8,7 +8,7 @@ LL |     let z: isize = a.x + b.y;
    |
    = note: an implementation of `std::ops::Add` might be missing for `std::boxed::Box<isize>`
 
-error[E0369]: binary operation `+` cannot be applied to type `std::boxed::Box<isize>`
+error[E0369]: cannot add `std::boxed::Box<isize>` to `std::boxed::Box<isize>`
   --> $DIR/autoderef-full-lval.rs:21:33
    |
 LL |     let answer: isize = forty.a + two.a;
diff --git a/src/test/ui/binary-op-on-double-ref.rs b/src/test/ui/binary-op-on-double-ref.rs
index 6490cc7fe56..67e01b9327d 100644
--- a/src/test/ui/binary-op-on-double-ref.rs
+++ b/src/test/ui/binary-op-on-double-ref.rs
@@ -2,7 +2,7 @@ fn main() {
     let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
     let vr = v.iter().filter(|x| {
         x % 2 == 0
-        //~^ ERROR binary operation `%` cannot be applied to type `&&{integer}`
+        //~^ ERROR cannot mod `&&{integer}` by `{integer}`
     });
     println!("{:?}", vr);
 }
diff --git a/src/test/ui/binary-op-on-double-ref.stderr b/src/test/ui/binary-op-on-double-ref.stderr
index d036f06a8c7..6c405333ec6 100644
--- a/src/test/ui/binary-op-on-double-ref.stderr
+++ b/src/test/ui/binary-op-on-double-ref.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `%` cannot be applied to type `&&{integer}`
+error[E0369]: cannot mod `&&{integer}` by `{integer}`
   --> $DIR/binary-op-on-double-ref.rs:4:11
    |
 LL |         x % 2 == 0
diff --git a/src/test/ui/binop/binop-bitxor-str.rs b/src/test/ui/binop/binop-bitxor-str.rs
index 6021c344dfb..e98ea4df97d 100644
--- a/src/test/ui/binop/binop-bitxor-str.rs
+++ b/src/test/ui/binop/binop-bitxor-str.rs
@@ -1,3 +1,3 @@
-// error-pattern:`^` cannot be applied to type `std::string::String`
+// error-pattern:no implementation for `std::string::String ^ std::string::String`
 
 fn main() { let x = "a".to_string() ^ "b".to_string(); }
diff --git a/src/test/ui/binop/binop-bitxor-str.stderr b/src/test/ui/binop/binop-bitxor-str.stderr
index 9e8992235ed..9a0d301d863 100644
--- a/src/test/ui/binop/binop-bitxor-str.stderr
+++ b/src/test/ui/binop/binop-bitxor-str.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `^` cannot be applied to type `std::string::String`
+error[E0369]: no implementation for `std::string::String ^ std::string::String`
   --> $DIR/binop-bitxor-str.rs:3:37
    |
 LL | fn main() { let x = "a".to_string() ^ "b".to_string(); }
diff --git a/src/test/ui/binop/binop-mul-bool.rs b/src/test/ui/binop/binop-mul-bool.rs
index 3d5349ba880..27b2f8bb3ff 100644
--- a/src/test/ui/binop/binop-mul-bool.rs
+++ b/src/test/ui/binop/binop-mul-bool.rs
@@ -1,3 +1,3 @@
-// error-pattern:`*` cannot be applied to type `bool`
+// error-pattern:cannot multiply `bool` to `bool`
 
 fn main() { let x = true * false; }
diff --git a/src/test/ui/binop/binop-mul-bool.stderr b/src/test/ui/binop/binop-mul-bool.stderr
index 92e14bccccd..ade22025589 100644
--- a/src/test/ui/binop/binop-mul-bool.stderr
+++ b/src/test/ui/binop/binop-mul-bool.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `*` cannot be applied to type `bool`
+error[E0369]: cannot multiply `bool` to `bool`
   --> $DIR/binop-mul-bool.rs:3:26
    |
 LL | fn main() { let x = true * false; }
diff --git a/src/test/ui/binop/binop-typeck.rs b/src/test/ui/binop/binop-typeck.rs
index e1185cfba26..812fe95db4e 100644
--- a/src/test/ui/binop/binop-typeck.rs
+++ b/src/test/ui/binop/binop-typeck.rs
@@ -4,5 +4,5 @@ fn main() {
     let x = true;
     let y = 1;
     let z = x + y;
-    //~^ ERROR binary operation `+` cannot be applied to type `bool`
+    //~^ ERROR cannot add `{integer}` to `bool`
 }
diff --git a/src/test/ui/binop/binop-typeck.stderr b/src/test/ui/binop/binop-typeck.stderr
index d33cff313e7..ebf82079ef2 100644
--- a/src/test/ui/binop/binop-typeck.stderr
+++ b/src/test/ui/binop/binop-typeck.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `bool`
+error[E0369]: cannot add `{integer}` to `bool`
   --> $DIR/binop-typeck.rs:6:15
    |
 LL |     let z = x + y;
diff --git a/src/test/ui/for/for-loop-type-error.rs b/src/test/ui/for/for-loop-type-error.rs
index 879fa47549e..8d9fc20f0d0 100644
--- a/src/test/ui/for/for-loop-type-error.rs
+++ b/src/test/ui/for/for-loop-type-error.rs
@@ -1,5 +1,5 @@
 pub fn main() {
-    let x = () + (); //~ ERROR binary operation
+    let x = () + (); //~ ERROR cannot add `()` to `()`
 
     // this shouldn't have a flow-on error:
     for _ in x {}
diff --git a/src/test/ui/for/for-loop-type-error.stderr b/src/test/ui/for/for-loop-type-error.stderr
index 588e7a0ed33..0ed26384f40 100644
--- a/src/test/ui/for/for-loop-type-error.stderr
+++ b/src/test/ui/for/for-loop-type-error.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `()`
+error[E0369]: cannot add `()` to `()`
   --> $DIR/for-loop-type-error.rs:2:16
    |
 LL |     let x = () + ();
diff --git a/src/test/ui/issues/issue-14915.rs b/src/test/ui/issues/issue-14915.rs
index 294533f0cbb..4acb51a4e50 100644
--- a/src/test/ui/issues/issue-14915.rs
+++ b/src/test/ui/issues/issue-14915.rs
@@ -4,5 +4,5 @@ fn main() {
     let x: Box<isize> = box 0;
 
     println!("{}", x + 1);
-    //~^ ERROR binary operation `+` cannot be applied to type `std::boxed::Box<isize>`
+    //~^ ERROR cannot add `{integer}` to `std::boxed::Box<isize>`
 }
diff --git a/src/test/ui/issues/issue-14915.stderr b/src/test/ui/issues/issue-14915.stderr
index e8de44320da..00b9909af59 100644
--- a/src/test/ui/issues/issue-14915.stderr
+++ b/src/test/ui/issues/issue-14915.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `std::boxed::Box<isize>`
+error[E0369]: cannot add `{integer}` to `std::boxed::Box<isize>`
   --> $DIR/issue-14915.rs:6:22
    |
 LL |     println!("{}", x + 1);
diff --git a/src/test/ui/issues/issue-24363.rs b/src/test/ui/issues/issue-24363.rs
index a5b45f13e74..34726fba9c6 100644
--- a/src/test/ui/issues/issue-24363.rs
+++ b/src/test/ui/issues/issue-24363.rs
@@ -1,6 +1,6 @@
 fn main() {
     1.create_a_type_error[ //~ `{integer}` is a primitive type and therefore doesn't have fields
-        ()+() //~ ERROR binary operation `+` cannot be applied
+        ()+() //~ ERROR cannot add
               //   ^ ensure that we typeck the inner expression ^
     ];
 }
diff --git a/src/test/ui/issues/issue-24363.stderr b/src/test/ui/issues/issue-24363.stderr
index 50d65e09bb1..a60fb24ec12 100644
--- a/src/test/ui/issues/issue-24363.stderr
+++ b/src/test/ui/issues/issue-24363.stderr
@@ -4,7 +4,7 @@ error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields
 LL |     1.create_a_type_error[
    |       ^^^^^^^^^^^^^^^^^^^
 
-error[E0369]: binary operation `+` cannot be applied to type `()`
+error[E0369]: cannot add `()` to `()`
   --> $DIR/issue-24363.rs:3:11
    |
 LL |         ()+()
diff --git a/src/test/ui/issues/issue-28837.rs b/src/test/ui/issues/issue-28837.rs
index 114473f3acf..438a4c521b1 100644
--- a/src/test/ui/issues/issue-28837.rs
+++ b/src/test/ui/issues/issue-28837.rs
@@ -3,23 +3,23 @@ struct A;
 fn main() {
     let a = A;
 
-    a + a; //~ ERROR binary operation `+` cannot be applied to type `A`
+    a + a; //~ ERROR cannot add `A` to `A`
 
-    a - a; //~ ERROR binary operation `-` cannot be applied to type `A`
+    a - a; //~ ERROR cannot substract `A` from `A`
 
-    a * a; //~ ERROR binary operation `*` cannot be applied to type `A`
+    a * a; //~ ERROR cannot multiply `A` to `A`
 
-    a / a; //~ ERROR binary operation `/` cannot be applied to type `A`
+    a / a; //~ ERROR cannot divide `A` by `A`
 
-    a % a; //~ ERROR binary operation `%` cannot be applied to type `A`
+    a % a; //~ ERROR cannot mod `A` by `A`
 
-    a & a; //~ ERROR binary operation `&` cannot be applied to type `A`
+    a & a; //~ ERROR no implementation for `A & A`
 
-    a | a; //~ ERROR binary operation `|` cannot be applied to type `A`
+    a | a; //~ ERROR no implementation for `A | A`
 
-    a << a; //~ ERROR binary operation `<<` cannot be applied to type `A`
+    a << a; //~ ERROR no implementation for `A << A`
 
-    a >> a; //~ ERROR binary operation `>>` cannot be applied to type `A`
+    a >> a; //~ ERROR no implementation for `A >> A`
 
     a == a; //~ ERROR binary operation `==` cannot be applied to type `A`
 
diff --git a/src/test/ui/issues/issue-28837.stderr b/src/test/ui/issues/issue-28837.stderr
index ac2a9f2203d..2ef571b576f 100644
--- a/src/test/ui/issues/issue-28837.stderr
+++ b/src/test/ui/issues/issue-28837.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `A`
+error[E0369]: cannot add `A` to `A`
   --> $DIR/issue-28837.rs:6:7
    |
 LL |     a + a;
@@ -8,7 +8,7 @@ LL |     a + a;
    |
    = note: an implementation of `std::ops::Add` might be missing for `A`
 
-error[E0369]: binary operation `-` cannot be applied to type `A`
+error[E0369]: cannot substract `A` from `A`
   --> $DIR/issue-28837.rs:8:7
    |
 LL |     a - a;
@@ -18,7 +18,7 @@ LL |     a - a;
    |
    = note: an implementation of `std::ops::Sub` might be missing for `A`
 
-error[E0369]: binary operation `*` cannot be applied to type `A`
+error[E0369]: cannot multiply `A` to `A`
   --> $DIR/issue-28837.rs:10:7
    |
 LL |     a * a;
@@ -28,7 +28,7 @@ LL |     a * a;
    |
    = note: an implementation of `std::ops::Mul` might be missing for `A`
 
-error[E0369]: binary operation `/` cannot be applied to type `A`
+error[E0369]: cannot divide `A` by `A`
   --> $DIR/issue-28837.rs:12:7
    |
 LL |     a / a;
@@ -38,7 +38,7 @@ LL |     a / a;
    |
    = note: an implementation of `std::ops::Div` might be missing for `A`
 
-error[E0369]: binary operation `%` cannot be applied to type `A`
+error[E0369]: cannot mod `A` by `A`
   --> $DIR/issue-28837.rs:14:7
    |
 LL |     a % a;
@@ -48,7 +48,7 @@ LL |     a % a;
    |
    = note: an implementation of `std::ops::Rem` might be missing for `A`
 
-error[E0369]: binary operation `&` cannot be applied to type `A`
+error[E0369]: no implementation for `A & A`
   --> $DIR/issue-28837.rs:16:7
    |
 LL |     a & a;
@@ -58,7 +58,7 @@ LL |     a & a;
    |
    = note: an implementation of `std::ops::BitAnd` might be missing for `A`
 
-error[E0369]: binary operation `|` cannot be applied to type `A`
+error[E0369]: no implementation for `A | A`
   --> $DIR/issue-28837.rs:18:7
    |
 LL |     a | a;
@@ -68,7 +68,7 @@ LL |     a | a;
    |
    = note: an implementation of `std::ops::BitOr` might be missing for `A`
 
-error[E0369]: binary operation `<<` cannot be applied to type `A`
+error[E0369]: no implementation for `A << A`
   --> $DIR/issue-28837.rs:20:7
    |
 LL |     a << a;
@@ -78,7 +78,7 @@ LL |     a << a;
    |
    = note: an implementation of `std::ops::Shl` might be missing for `A`
 
-error[E0369]: binary operation `>>` cannot be applied to type `A`
+error[E0369]: no implementation for `A >> A`
   --> $DIR/issue-28837.rs:22:7
    |
 LL |     a >> a;
diff --git a/src/test/ui/issues/issue-31076.rs b/src/test/ui/issues/issue-31076.rs
index e4531072e9b..f9c35526ec3 100644
--- a/src/test/ui/issues/issue-31076.rs
+++ b/src/test/ui/issues/issue-31076.rs
@@ -11,7 +11,7 @@ impl Add<i32> for i32 {}
 
 fn main() {
     let x = 5 + 6;
-    //~^ ERROR binary operation `+` cannot be applied to type `{integer}`
+    //~^ ERROR cannot add `{integer}` to `{integer}`
     let y = 5i32 + 6i32;
-    //~^ ERROR binary operation `+` cannot be applied to type `i32`
+    //~^ ERROR cannot add `i32` to `i32`
 }
diff --git a/src/test/ui/issues/issue-31076.stderr b/src/test/ui/issues/issue-31076.stderr
index 60a3be1c36b..5d65734cd23 100644
--- a/src/test/ui/issues/issue-31076.stderr
+++ b/src/test/ui/issues/issue-31076.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `{integer}`
+error[E0369]: cannot add `{integer}` to `{integer}`
   --> $DIR/issue-31076.rs:13:15
    |
 LL |     let x = 5 + 6;
@@ -8,7 +8,7 @@ LL |     let x = 5 + 6;
    |
    = note: an implementation of `std::ops::Add` might be missing for `{integer}`
 
-error[E0369]: binary operation `+` cannot be applied to type `i32`
+error[E0369]: cannot add `i32` to `i32`
   --> $DIR/issue-31076.rs:15:18
    |
 LL |     let y = 5i32 + 6i32;
diff --git a/src/test/ui/issues/issue-35668.rs b/src/test/ui/issues/issue-35668.rs
index 1b8ada57ed6..6f6dfb00f86 100644
--- a/src/test/ui/issues/issue-35668.rs
+++ b/src/test/ui/issues/issue-35668.rs
@@ -1,6 +1,6 @@
 fn func<'a, T>(a: &'a [T]) -> impl Iterator<Item=&'a T> {
     a.iter().map(|a| a*a)
-    //~^ ERROR binary operation `*` cannot be applied to type `&T`
+    //~^ ERROR cannot multiply `&T` to `&T`
 }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-35668.stderr b/src/test/ui/issues/issue-35668.stderr
index 59ca874bd20..9d5796a5eef 100644
--- a/src/test/ui/issues/issue-35668.stderr
+++ b/src/test/ui/issues/issue-35668.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `*` cannot be applied to type `&T`
+error[E0369]: cannot multiply `&T` to `&T`
   --> $DIR/issue-35668.rs:2:23
    |
 LL |     a.iter().map(|a| a*a)
diff --git a/src/test/ui/issues/issue-3820.rs b/src/test/ui/issues/issue-3820.rs
index fbf60ce278d..c0906546232 100644
--- a/src/test/ui/issues/issue-3820.rs
+++ b/src/test/ui/issues/issue-3820.rs
@@ -11,5 +11,5 @@ impl Thing {
 fn main() {
     let u = Thing {x: 2};
     let _v = u.mul(&3); // This is ok
-    let w = u * 3; //~ ERROR binary operation `*` cannot be applied to type `Thing`
+    let w = u * 3; //~ ERROR cannot multiply `{integer}` to `Thing`
 }
diff --git a/src/test/ui/issues/issue-3820.stderr b/src/test/ui/issues/issue-3820.stderr
index 35eceb3b3c6..8cc768237a9 100644
--- a/src/test/ui/issues/issue-3820.stderr
+++ b/src/test/ui/issues/issue-3820.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `*` cannot be applied to type `Thing`
+error[E0369]: cannot multiply `{integer}` to `Thing`
   --> $DIR/issue-3820.rs:14:15
    |
 LL |     let w = u * 3;
diff --git a/src/test/ui/issues/issue-40610.rs b/src/test/ui/issues/issue-40610.rs
index 104cf7f54e5..c01233605b5 100644
--- a/src/test/ui/issues/issue-40610.rs
+++ b/src/test/ui/issues/issue-40610.rs
@@ -2,5 +2,5 @@ fn f(_: &[f32]) {}
 
 fn main() {
     () + f(&[1.0]);
-    //~^ ERROR binary operation `+` cannot be applied to type `()`
+    //~^ ERROR cannot add `()` to `()`
 }
diff --git a/src/test/ui/issues/issue-40610.stderr b/src/test/ui/issues/issue-40610.stderr
index 9d577591929..95f45c168e1 100644
--- a/src/test/ui/issues/issue-40610.stderr
+++ b/src/test/ui/issues/issue-40610.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `()`
+error[E0369]: cannot add `()` to `()`
   --> $DIR/issue-40610.rs:4:8
    |
 LL |     () + f(&[1.0]);
diff --git a/src/test/ui/issues/issue-41394.rs b/src/test/ui/issues/issue-41394.rs
index 45318f6efb8..64873ac35a0 100644
--- a/src/test/ui/issues/issue-41394.rs
+++ b/src/test/ui/issues/issue-41394.rs
@@ -1,6 +1,6 @@
 enum Foo {
     A = "" + 1
-    //~^ ERROR binary operation `+` cannot be applied to type `&str`
+    //~^ ERROR cannot add `{integer}` to `&str`
 }
 
 enum Bar {
diff --git a/src/test/ui/issues/issue-41394.stderr b/src/test/ui/issues/issue-41394.stderr
index c8437ab189d..3f60ea4bbf7 100644
--- a/src/test/ui/issues/issue-41394.stderr
+++ b/src/test/ui/issues/issue-41394.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `&str`
+error[E0369]: cannot add `{integer}` to `&str`
   --> $DIR/issue-41394.rs:2:12
    |
 LL |     A = "" + 1
diff --git a/src/test/ui/issues/issue-47377.stderr b/src/test/ui/issues/issue-47377.stderr
index 3460c1dae22..5f785679c55 100644
--- a/src/test/ui/issues/issue-47377.stderr
+++ b/src/test/ui/issues/issue-47377.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `&str`
+error[E0369]: cannot add `&str` to `&str`
   --> $DIR/issue-47377.rs:4:14
    |
 LL |      let _a = b + ", World!";
diff --git a/src/test/ui/issues/issue-47380.stderr b/src/test/ui/issues/issue-47380.stderr
index f334dcbd916..216e32ddae4 100644
--- a/src/test/ui/issues/issue-47380.stderr
+++ b/src/test/ui/issues/issue-47380.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `&str`
+error[E0369]: cannot add `&str` to `&str`
   --> $DIR/issue-47380.rs:3:35
    |
 LL |     println!("🦀🦀🦀🦀🦀"); let _a = b + ", World!";
diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs
index b676ea851a3..ce6836f30f9 100644
--- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs
+++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs
@@ -21,7 +21,7 @@ use E::*;
 
 fn no_top_level_or_patterns() {
     // We do *not* allow or-patterns at the top level of lambdas...
-    let _ = |A | B: E| (); //~ ERROR binary operation `|` cannot be applied to type `E`
+    let _ = |A | B: E| (); //~ ERROR no implementation for `E | ()`
     //           -------- This looks like an or-pattern but is in fact `|A| (B: E | ())`.
 
     // ...and for now neither do we allow or-patterns at the top level of functions.
diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr
index b6ff39d64d6..e77d92e8b07 100644
--- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr
+++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr
@@ -104,7 +104,7 @@ LL | #![feature(or_patterns)]
    |
    = note: `#[warn(incomplete_features)]` on by default
 
-error[E0369]: binary operation `|` cannot be applied to type `E`
+error[E0369]: no implementation for `E | ()`
   --> $DIR/or-patterns-syntactic-fail.rs:24:22
    |
 LL |     let _ = |A | B: E| ();
diff --git a/src/test/ui/pattern/pattern-tyvar-2.rs b/src/test/ui/pattern/pattern-tyvar-2.rs
index 9fba9cb876a..4c6d515b86a 100644
--- a/src/test/ui/pattern/pattern-tyvar-2.rs
+++ b/src/test/ui/pattern/pattern-tyvar-2.rs
@@ -1,6 +1,6 @@
 enum Bar { T1((), Option<Vec<isize>>), T2, }
 
 fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3; } _ => { panic!(); } } }
-//~^ ERROR binary operation `*` cannot be applied to
+//~^ ERROR cannot multiply `{integer}` to `std::vec::Vec<isize>`
 
 fn main() { }
diff --git a/src/test/ui/pattern/pattern-tyvar-2.stderr b/src/test/ui/pattern/pattern-tyvar-2.stderr
index 7c6ae499cbb..bb3e61017d4 100644
--- a/src/test/ui/pattern/pattern-tyvar-2.stderr
+++ b/src/test/ui/pattern/pattern-tyvar-2.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `*` cannot be applied to type `std::vec::Vec<isize>`
+error[E0369]: cannot multiply `{integer}` to `std::vec::Vec<isize>`
   --> $DIR/pattern-tyvar-2.rs:3:71
    |
 LL | fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3; } _ => { panic!(); } } }
diff --git a/src/test/ui/span/issue-39018.rs b/src/test/ui/span/issue-39018.rs
index a3b1d1d8179..b6db4008db0 100644
--- a/src/test/ui/span/issue-39018.rs
+++ b/src/test/ui/span/issue-39018.rs
@@ -1,15 +1,15 @@
 pub fn main() {
     let x = "Hello " + "World!";
-    //~^ ERROR cannot be applied to type
+    //~^ ERROR cannot add
 
     // Make sure that the span outputs a warning
     // for not having an implementation for std::ops::Add
     // that won't output for the above string concatenation
     let y = World::Hello + World::Goodbye;
-    //~^ ERROR cannot be applied to type
+    //~^ ERROR cannot add
 
     let x = "Hello " + "World!".to_owned();
-    //~^ ERROR cannot be applied to type
+    //~^ ERROR cannot add
 }
 
 enum World {
@@ -23,16 +23,16 @@ fn foo() {
     let c = "";
     let d = "";
     let e = &a;
-    let _ = &a + &b; //~ ERROR binary operation
-    let _ = &a + b; //~ ERROR binary operation
+    let _ = &a + &b; //~ ERROR cannot add
+    let _ = &a + b; //~ ERROR cannot add
     let _ = a + &b; // ok
     let _ = a + b; //~ ERROR mismatched types
-    let _ = e + b; //~ ERROR binary operation
-    let _ = e + &b; //~ ERROR binary operation
-    let _ = e + d; //~ ERROR binary operation
-    let _ = e + &d; //~ ERROR binary operation
-    let _ = &c + &d; //~ ERROR binary operation
-    let _ = &c + d; //~ ERROR binary operation
-    let _ = c + &d; //~ ERROR binary operation
-    let _ = c + d; //~ ERROR binary operation
+    let _ = e + b; //~ ERROR cannot add
+    let _ = e + &b; //~ ERROR cannot add
+    let _ = e + d; //~ ERROR cannot add
+    let _ = e + &d; //~ ERROR cannot add
+    let _ = &c + &d; //~ ERROR cannot add
+    let _ = &c + d; //~ ERROR cannot add
+    let _ = c + &d; //~ ERROR cannot add
+    let _ = c + d; //~ ERROR cannot add
 }
diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr
index 9637d1d82ec..8a32561bd01 100644
--- a/src/test/ui/span/issue-39018.stderr
+++ b/src/test/ui/span/issue-39018.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `&str`
+error[E0369]: cannot add `&str` to `&str`
   --> $DIR/issue-39018.rs:2:22
    |
 LL |     let x = "Hello " + "World!";
@@ -12,7 +12,7 @@ help: `to_owned()` can be used to create an owned `String` from a string referen
 LL |     let x = "Hello ".to_owned() + "World!";
    |             ^^^^^^^^^^^^^^^^^^^
 
-error[E0369]: binary operation `+` cannot be applied to type `World`
+error[E0369]: cannot add `World` to `World`
   --> $DIR/issue-39018.rs:8:26
    |
 LL |     let y = World::Hello + World::Goodbye;
@@ -22,7 +22,7 @@ LL |     let y = World::Hello + World::Goodbye;
    |
    = note: an implementation of `std::ops::Add` might be missing for `World`
 
-error[E0369]: binary operation `+` cannot be applied to type `&str`
+error[E0369]: cannot add `std::string::String` to `&str`
   --> $DIR/issue-39018.rs:11:22
    |
 LL |     let x = "Hello " + "World!".to_owned();
@@ -36,7 +36,7 @@ help: `to_owned()` can be used to create an owned `String` from a string referen
 LL |     let x = "Hello ".to_owned() + &"World!".to_owned();
    |             ^^^^^^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^
 
-error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+error[E0369]: cannot add `&std::string::String` to `&std::string::String`
   --> $DIR/issue-39018.rs:26:16
    |
 LL |     let _ = &a + &b;
@@ -50,7 +50,7 @@ help: String concatenation appends the string on the right to the string on the
 LL |     let _ = a + &b;
    |             ^
 
-error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+error[E0369]: cannot add `std::string::String` to `&std::string::String`
   --> $DIR/issue-39018.rs:27:16
    |
 LL |     let _ = &a + b;
@@ -73,7 +73,7 @@ LL |     let _ = a + b;
    |                 expected `&str`, found struct `std::string::String`
    |                 help: consider borrowing here: `&b`
 
-error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+error[E0369]: cannot add `std::string::String` to `&std::string::String`
   --> $DIR/issue-39018.rs:30:15
    |
 LL |     let _ = e + b;
@@ -87,7 +87,7 @@ help: `to_owned()` can be used to create an owned `String` from a string referen
 LL |     let _ = e.to_owned() + &b;
    |             ^^^^^^^^^^^^   ^^
 
-error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+error[E0369]: cannot add `&std::string::String` to `&std::string::String`
   --> $DIR/issue-39018.rs:31:15
    |
 LL |     let _ = e + &b;
@@ -101,7 +101,7 @@ help: `to_owned()` can be used to create an owned `String` from a string referen
 LL |     let _ = e.to_owned() + &b;
    |             ^^^^^^^^^^^^
 
-error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+error[E0369]: cannot add `&str` to `&std::string::String`
   --> $DIR/issue-39018.rs:32:15
    |
 LL |     let _ = e + d;
@@ -115,7 +115,7 @@ help: `to_owned()` can be used to create an owned `String` from a string referen
 LL |     let _ = e.to_owned() + d;
    |             ^^^^^^^^^^^^
 
-error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+error[E0369]: cannot add `&&str` to `&std::string::String`
   --> $DIR/issue-39018.rs:33:15
    |
 LL |     let _ = e + &d;
@@ -129,7 +129,7 @@ help: `to_owned()` can be used to create an owned `String` from a string referen
 LL |     let _ = e.to_owned() + &d;
    |             ^^^^^^^^^^^^
 
-error[E0369]: binary operation `+` cannot be applied to type `&&str`
+error[E0369]: cannot add `&&str` to `&&str`
   --> $DIR/issue-39018.rs:34:16
    |
 LL |     let _ = &c + &d;
@@ -139,7 +139,7 @@ LL |     let _ = &c + &d;
    |
    = note: an implementation of `std::ops::Add` might be missing for `&&str`
 
-error[E0369]: binary operation `+` cannot be applied to type `&&str`
+error[E0369]: cannot add `&str` to `&&str`
   --> $DIR/issue-39018.rs:35:16
    |
 LL |     let _ = &c + d;
@@ -149,7 +149,7 @@ LL |     let _ = &c + d;
    |
    = note: an implementation of `std::ops::Add` might be missing for `&&str`
 
-error[E0369]: binary operation `+` cannot be applied to type `&str`
+error[E0369]: cannot add `&&str` to `&str`
   --> $DIR/issue-39018.rs:36:15
    |
 LL |     let _ = c + &d;
@@ -163,7 +163,7 @@ help: `to_owned()` can be used to create an owned `String` from a string referen
 LL |     let _ = c.to_owned() + &d;
    |             ^^^^^^^^^^^^
 
-error[E0369]: binary operation `+` cannot be applied to type `&str`
+error[E0369]: cannot add `&str` to `&str`
   --> $DIR/issue-39018.rs:37:15
    |
 LL |     let _ = c + d;
diff --git a/src/test/ui/span/type-binding.stderr b/src/test/ui/span/type-binding.stderr
index 421af67d19c..c3e95455532 100644
--- a/src/test/ui/span/type-binding.stderr
+++ b/src/test/ui/span/type-binding.stderr
@@ -2,7 +2,7 @@ error[E0220]: associated type `Trget` not found for `std::ops::Deref`
   --> $DIR/type-binding.rs:6:20
    |
 LL | fn homura<T: Deref<Trget = i32>>(_: T) {}
-   |                    ^^^^^^^^^^^ associated type `Trget` not found
+   |                    ^^^^^^^^^^^ help: there is an associated type with a similar name: `Target`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/str/str-concat-on-double-ref.rs b/src/test/ui/str/str-concat-on-double-ref.rs
index a671b6e191e..23e5f892062 100644
--- a/src/test/ui/str/str-concat-on-double-ref.rs
+++ b/src/test/ui/str/str-concat-on-double-ref.rs
@@ -2,6 +2,6 @@ fn main() {
     let a: &String = &"1".to_owned();
     let b: &str = &"2";
     let c = a + b;
-    //~^ ERROR binary operation `+` cannot be applied to type `&std::string::String`
+    //~^ ERROR cannot add `&str` to `&std::string::String`
     println!("{:?}", c);
 }
diff --git a/src/test/ui/str/str-concat-on-double-ref.stderr b/src/test/ui/str/str-concat-on-double-ref.stderr
index d193955af4b..d77e0d8f242 100644
--- a/src/test/ui/str/str-concat-on-double-ref.stderr
+++ b/src/test/ui/str/str-concat-on-double-ref.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `&std::string::String`
+error[E0369]: cannot add `&str` to `&std::string::String`
   --> $DIR/str-concat-on-double-ref.rs:4:15
    |
 LL |     let c = a + b;
diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs
index cc94680530c..1989ea88635 100644
--- a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs
+++ b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.rs
@@ -3,5 +3,5 @@
 fn main() {
     let unicode_is_fun = "؁‱ஹ௸௵꧄.ဪ꧅⸻𒈙𒐫﷽𒌄𒈟𒍼𒁎𒀱𒌧𒅃 𒈓𒍙𒊎𒄡𒅌𒁏𒀰𒐪𒐩𒈙𒐫𪚥";
     let _ = "ༀ༁༂༃༄༅༆༇༈༉༊་༌།༎༏༐༑༒༓༔༕༖༗༘༙༚༛༜༝༞༟༠༡༢༣༤༥༦༧༨༩༪༫༬༭༮༯༰༱༲༳༴༵༶༷༸༹༺༻༼༽༾༿ཀཁགགྷངཅཆཇ཈ཉཊཋཌཌྷཎཏཐདདྷནཔཕབབྷམཙཚཛཛྷཝཞཟའཡརལཤཥསཧཨཀྵཪཫཬ཭཮཯཰ཱཱཱིིུུྲྀཷླྀཹེཻོཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇࿈࿉࿊࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!";
-    //~^ ERROR binary operation `+` cannot be applied to type `&str`
+    //~^ ERROR cannot add `&str` to `&str`
 }
diff --git a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr
index 9f0f990670f..69daa93412a 100644
--- a/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr
+++ b/src/test/ui/terminal-width/non-1-width-unicode-multiline-label.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `&str`
+error[E0369]: cannot add `&str` to `&str`
   --> $DIR/non-1-width-unicode-multiline-label.rs:5:260
    |
 LL | ...ཽཾཿ྄ཱྀྀྂྃ྅྆྇ྈྉྊྋྌྍྎྏྐྑྒྒྷྔྕྖྗ྘ྙྚྛྜྜྷྞྟྠྡྡྷྣྤྥྦྦྷྨྩྪྫྫྷྭྮྯྰྱྲླྴྵྶྷྸྐྵྺྻྼ྽྾྿࿀࿁࿂࿃࿄࿅࿆࿇...࿋࿌࿍࿎࿏࿐࿑࿒࿓࿔࿕࿖࿗࿘࿙࿚"; let _a = unicode_is_fun + " really fun!";
diff --git a/src/test/ui/traits/trait-resolution-in-overloaded-op.rs b/src/test/ui/traits/trait-resolution-in-overloaded-op.rs
index 96f81a21a3b..28677698516 100644
--- a/src/test/ui/traits/trait-resolution-in-overloaded-op.rs
+++ b/src/test/ui/traits/trait-resolution-in-overloaded-op.rs
@@ -5,7 +5,7 @@ trait MyMul<Rhs, Res> {
 }
 
 fn foo<T: MyMul<f64, f64>>(a: &T, b: f64) -> f64 {
-    a * b //~ ERROR binary operation `*` cannot be applied to type `&T`
+    a * b //~ ERROR cannot multiply `f64` to `&T`
 }
 
 fn main() {}
diff --git a/src/test/ui/traits/trait-resolution-in-overloaded-op.stderr b/src/test/ui/traits/trait-resolution-in-overloaded-op.stderr
index d11562e2a00..8d7ba36c665 100644
--- a/src/test/ui/traits/trait-resolution-in-overloaded-op.stderr
+++ b/src/test/ui/traits/trait-resolution-in-overloaded-op.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `*` cannot be applied to type `&T`
+error[E0369]: cannot multiply `f64` to `&T`
   --> $DIR/trait-resolution-in-overloaded-op.rs:8:7
    |
 LL |     a * b
diff --git a/src/test/ui/type/type-check/missing_trait_impl.rs b/src/test/ui/type/type-check/missing_trait_impl.rs
index dcca96b509b..f61ada3f63f 100644
--- a/src/test/ui/type/type-check/missing_trait_impl.rs
+++ b/src/test/ui/type/type-check/missing_trait_impl.rs
@@ -2,7 +2,7 @@ fn main() {
 }
 
 fn foo<T>(x: T, y: T) {
-    let z = x + y; //~ ERROR binary operation `+` cannot be applied to type `T`
+    let z = x + y; //~ ERROR cannot add `T` to `T`
 }
 
 fn bar<T>(x: T) {
diff --git a/src/test/ui/type/type-check/missing_trait_impl.stderr b/src/test/ui/type/type-check/missing_trait_impl.stderr
index 2a158ab8564..7186d6a542d 100644
--- a/src/test/ui/type/type-check/missing_trait_impl.stderr
+++ b/src/test/ui/type/type-check/missing_trait_impl.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `T`
+error[E0369]: cannot add `T` to `T`
   --> $DIR/missing_trait_impl.rs:5:15
    |
 LL |     let z = x + y;
diff --git a/src/test/ui/vec/vec-res-add.rs b/src/test/ui/vec/vec-res-add.rs
index ea2aa6cda24..4785178fb25 100644
--- a/src/test/ui/vec/vec-res-add.rs
+++ b/src/test/ui/vec/vec-res-add.rs
@@ -14,6 +14,6 @@ fn main() {
     let i = vec![r(0)];
     let j = vec![r(1)];
     let k = i + j;
-    //~^ ERROR binary operation `+` cannot be applied to type
+    //~^ ERROR cannot add `std::vec::Vec<R>` to `std::vec::Vec<R>`
     println!("{:?}", j);
 }
diff --git a/src/test/ui/vec/vec-res-add.stderr b/src/test/ui/vec/vec-res-add.stderr
index 78b70f09e90..1cc12a222e5 100644
--- a/src/test/ui/vec/vec-res-add.stderr
+++ b/src/test/ui/vec/vec-res-add.stderr
@@ -1,4 +1,4 @@
-error[E0369]: binary operation `+` cannot be applied to type `std::vec::Vec<R>`
+error[E0369]: cannot add `std::vec::Vec<R>` to `std::vec::Vec<R>`
   --> $DIR/vec-res-add.rs:16:15
    |
 LL |     let k = i + j;