about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs153
-rw-r--r--src/librustc_mir/borrow_check/move_errors.rs129
-rw-r--r--src/librustc_mir/borrow_check/mutability_errors.rs97
-rw-r--r--src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.rs13
-rw-r--r--src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr84
-rw-r--r--src/test/ui/borrowck/borrowck-borrow-overloaded-deref.rs13
-rw-r--r--src/test/ui/borrowck/borrowck-borrow-overloaded-deref.stderr42
-rw-r--r--src/test/ui/borrowck/borrowck-overloaded-index-ref-index.rs2
-rw-r--r--src/test/ui/borrowck/borrowck-overloaded-index-ref-index.stderr4
-rw-r--r--src/test/ui/borrowck/index-mut-help-with-impl.stderr2
-rw-r--r--src/test/ui/borrowck/index-mut-help.stderr8
-rw-r--r--src/test/ui/issues/issue-41726.rs2
-rw-r--r--src/test/ui/issues/issue-41726.stderr2
13 files changed, 282 insertions, 269 deletions
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 10c9a439bf7..5f61ed151c0 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -4,9 +4,9 @@ use rustc::hir::def_id::DefId;
 use rustc::mir::{
     AggregateKind, Constant, Field, Local, LocalKind, Location, Operand,
     Place, PlaceBase, ProjectionElem, Rvalue, Statement, StatementKind, Static,
-    StaticKind, TerminatorKind,
+    StaticKind, Terminator, TerminatorKind,
 };
-use rustc::ty::{self, DefIdTree, Ty};
+use rustc::ty::{self, DefIdTree, Ty, TyCtxt};
 use rustc::ty::layout::VariantIdx;
 use rustc::ty::print::Print;
 use rustc_errors::DiagnosticBuilder;
@@ -15,6 +15,7 @@ use syntax::symbol::sym;
 
 use super::borrow_set::BorrowData;
 use super::{MirBorrowckCtxt};
+use crate::dataflow::move_paths::{InitLocation, LookupResult};
 
 pub(super) struct IncludingDowncast(pub(super) bool);
 
@@ -401,6 +402,70 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             err.note(&message);
         }
     }
+
+    pub(super) fn borrowed_content_source(
+        &self,
+        deref_base: &Place<'tcx>,
+    ) -> BorrowedContentSource<'tcx> {
+        let tcx = self.infcx.tcx;
+
+        // Look up the provided place and work out the move path index for it,
+        // we'll use this to check whether it was originally from an overloaded
+        // operator.
+        match self.move_data.rev_lookup.find(deref_base) {
+            LookupResult::Exact(mpi) | LookupResult::Parent(Some(mpi)) => {
+                debug!("borrowed_content_source: mpi={:?}", mpi);
+
+                for i in &self.move_data.init_path_map[mpi] {
+                    let init = &self.move_data.inits[*i];
+                    debug!("borrowed_content_source: init={:?}", init);
+                    // We're only interested in statements that initialized a value, not the
+                    // initializations from arguments.
+                    let loc = match init.location {
+                        InitLocation::Statement(stmt) => stmt,
+                        _ => continue,
+                    };
+
+                    let bbd = &self.body[loc.block];
+                    let is_terminator = bbd.statements.len() == loc.statement_index;
+                    debug!(
+                        "borrowed_content_source: loc={:?} is_terminator={:?}",
+                        loc,
+                        is_terminator,
+                    );
+                    if !is_terminator {
+                        continue;
+                    } else if let Some(Terminator {
+                        kind: TerminatorKind::Call {
+                            ref func,
+                            from_hir_call: false,
+                            ..
+                        },
+                        ..
+                    }) = bbd.terminator {
+                        if let Some(source)
+                            = BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx)
+                        {
+                            return source;
+                        }
+                    }
+                }
+            }
+            // Base is a `static` so won't be from an overloaded operator
+            _ => (),
+        };
+
+        // If we didn't find an overloaded deref or index, then assume it's a
+        // built in deref and check the type of the base.
+        let base_ty = deref_base.ty(self.body, tcx).ty;
+        if base_ty.is_unsafe_ptr() {
+            BorrowedContentSource::DerefRawPointer
+        } else if base_ty.is_mutable_pointer() {
+            BorrowedContentSource::DerefMutableRef
+        } else {
+            BorrowedContentSource::DerefSharedRef
+        }
+    }
 }
 
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
@@ -547,6 +612,90 @@ impl UseSpans {
     }
 }
 
+pub(super) enum BorrowedContentSource<'tcx> {
+    DerefRawPointer,
+    DerefMutableRef,
+    DerefSharedRef,
+    OverloadedDeref(Ty<'tcx>),
+    OverloadedIndex(Ty<'tcx>),
+}
+
+impl BorrowedContentSource<'tcx> {
+    pub(super) fn describe_for_unnamed_place(&self) -> String {
+        match *self {
+            BorrowedContentSource::DerefRawPointer => format!("a raw pointer"),
+            BorrowedContentSource::DerefSharedRef => format!("a shared reference"),
+            BorrowedContentSource::DerefMutableRef => {
+                format!("a mutable reference")
+            }
+            BorrowedContentSource::OverloadedDeref(ty) => {
+                if ty.is_rc() {
+                   format!("an `Rc`")
+                } else if ty.is_arc() {
+                    format!("an `Arc`")
+                } else {
+                    format!("dereference of `{}`", ty)
+                }
+            }
+            BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty),
+        }
+    }
+
+    pub(super) fn describe_for_named_place(&self) -> Option<&'static str> {
+        match *self {
+            BorrowedContentSource::DerefRawPointer => Some("raw pointer"),
+            BorrowedContentSource::DerefSharedRef => Some("shared reference"),
+            BorrowedContentSource::DerefMutableRef => Some("mutable reference"),
+            // Overloaded deref and index operators should be evaluated into a
+            // temporary. So we don't need a description here.
+            BorrowedContentSource::OverloadedDeref(_)
+            | BorrowedContentSource::OverloadedIndex(_) => None
+        }
+    }
+
+    pub(super) fn describe_for_immutable_place(&self) -> String {
+        match *self {
+            BorrowedContentSource::DerefRawPointer => format!("a `*const` pointer"),
+            BorrowedContentSource::DerefSharedRef => format!("a `&` reference"),
+            BorrowedContentSource::DerefMutableRef => {
+                 bug!("describe_for_immutable_place: DerefMutableRef isn't immutable")
+            },
+            BorrowedContentSource::OverloadedDeref(ty) => {
+                if ty.is_rc() {
+                   format!("an `Rc`")
+                } else if ty.is_arc() {
+                    format!("an `Arc`")
+                } else {
+                    format!("a dereference of `{}`", ty)
+                }
+            }
+            BorrowedContentSource::OverloadedIndex(ty) => format!("an index of `{}`", ty),
+        }
+    }
+
+    fn from_call(func: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<Self> {
+        match func.sty {
+            ty::FnDef(def_id, substs) => {
+                let trait_id = tcx.trait_of_item(def_id)?;
+
+                let lang_items = tcx.lang_items();
+                if Some(trait_id) == lang_items.deref_trait()
+                    || Some(trait_id) == lang_items.deref_mut_trait()
+                {
+                    Some(BorrowedContentSource::OverloadedDeref(substs.type_at(0)))
+                } else if Some(trait_id) == lang_items.index_trait()
+                    || Some(trait_id) == lang_items.index_mut_trait()
+                {
+                    Some(BorrowedContentSource::OverloadedIndex(substs.type_at(0)))
+                } else {
+                    None
+                }
+            }
+            _ => None,
+        }
+    }
+}
+
 impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     /// Finds the spans associated to a move or copy of move_place at location.
     pub(super) fn move_spans(
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index d1522936725..3130b7cec5b 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -1,7 +1,7 @@
 use core::unicode::property::Pattern_White_Space;
 
 use rustc::mir::*;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty;
 use rustc_errors::{DiagnosticBuilder,Applicability};
 use syntax_pos::Span;
 
@@ -9,7 +9,7 @@ use crate::borrow_check::MirBorrowckCtxt;
 use crate::borrow_check::prefixes::PrefixSet;
 use crate::borrow_check::error_reporting::UseSpans;
 use crate::dataflow::move_paths::{
-    IllegalMoveOrigin, IllegalMoveOriginKind, InitLocation,
+    IllegalMoveOrigin, IllegalMoveOriginKind,
     LookupResult, MoveError, MovePathIndex,
 };
 use crate::util::borrowck_errors::{BorrowckErrors, Origin};
@@ -55,70 +55,6 @@ enum GroupedMoveError<'tcx> {
     },
 }
 
-enum BorrowedContentSource<'tcx> {
-    DerefRawPointer,
-    DerefMutableRef,
-    DerefSharedRef,
-    OverloadedDeref(Ty<'tcx>),
-    OverloadedIndex(Ty<'tcx>),
-}
-
-impl BorrowedContentSource<'tcx> {
-    fn describe_for_unnamed_place(&self) -> String {
-        match *self {
-            BorrowedContentSource::DerefRawPointer => format!("a raw pointer"),
-            BorrowedContentSource::DerefSharedRef => format!("a shared reference"),
-            BorrowedContentSource::DerefMutableRef => {
-                format!("a mutable reference")
-            }
-            BorrowedContentSource::OverloadedDeref(ty) => {
-                if ty.is_rc() {
-                   format!("an `Rc`")
-                } else if ty.is_arc() {
-                    format!("an `Arc`")
-                } else {
-                    format!("dereference of `{}`", ty)
-                }
-            }
-            BorrowedContentSource::OverloadedIndex(ty) => format!("index of `{}`", ty),
-        }
-    }
-
-    fn describe_for_named_place(&self) -> Option<&'static str> {
-        match *self {
-            BorrowedContentSource::DerefRawPointer => Some("raw pointer"),
-            BorrowedContentSource::DerefSharedRef => Some("shared reference"),
-            BorrowedContentSource::DerefMutableRef => Some("mutable reference"),
-            // Overloaded deref and index operators should be evaluated into a
-            // temporary. So we don't need a description here.
-            BorrowedContentSource::OverloadedDeref(_)
-            | BorrowedContentSource::OverloadedIndex(_) => None
-        }
-    }
-
-    fn from_call(func: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<Self> {
-        match func.sty {
-            ty::FnDef(def_id, substs) => {
-                let trait_id = tcx.trait_of_item(def_id)?;
-
-                let lang_items = tcx.lang_items();
-                if Some(trait_id) == lang_items.deref_trait()
-                    || Some(trait_id) == lang_items.deref_mut_trait()
-                {
-                    Some(BorrowedContentSource::OverloadedDeref(substs.type_at(0)))
-                } else if Some(trait_id) == lang_items.index_trait()
-                    || Some(trait_id) == lang_items.index_mut_trait()
-                {
-                    Some(BorrowedContentSource::OverloadedIndex(substs.type_at(0)))
-                } else {
-                    None
-                }
-            }
-            _ => None,
-        }
-    }
-}
-
 impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
     pub(crate) fn report_move_errors(&mut self, move_errors: Vec<(Place<'tcx>, MoveError<'tcx>)>) {
         let grouped_errors = self.group_move_errors(move_errors);
@@ -646,65 +582,4 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             );
         }
     }
-
-    fn borrowed_content_source(&self, deref_base: &Place<'tcx>) -> BorrowedContentSource<'tcx> {
-        let tcx = self.infcx.tcx;
-
-        // Look up the provided place and work out the move path index for it,
-        // we'll use this to check whether it was originally from an overloaded
-        // operator.
-        match self.move_data.rev_lookup.find(deref_base) {
-            LookupResult::Exact(mpi) | LookupResult::Parent(Some(mpi)) => {
-                debug!("borrowed_content_source: mpi={:?}", mpi);
-
-                for i in &self.move_data.init_path_map[mpi] {
-                    let init = &self.move_data.inits[*i];
-                    debug!("borrowed_content_source: init={:?}", init);
-                    // We're only interested in statements that initialized a value, not the
-                    // initializations from arguments.
-                    let loc = match init.location {
-                        InitLocation::Statement(stmt) => stmt,
-                        _ => continue,
-                    };
-
-                    let bbd = &self.body[loc.block];
-                    let is_terminator = bbd.statements.len() == loc.statement_index;
-                    debug!(
-                        "borrowed_content_source: loc={:?} is_terminator={:?}",
-                        loc,
-                        is_terminator,
-                    );
-                    if !is_terminator {
-                        continue;
-                    } else if let Some(Terminator {
-                        kind: TerminatorKind::Call {
-                            ref func,
-                            from_hir_call: false,
-                            ..
-                        },
-                        ..
-                    }) = bbd.terminator {
-                        if let Some(source)
-                            = BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx)
-                        {
-                            return source;
-                        }
-                    }
-                }
-            }
-            // Base is a `static` so won't be from an overloaded operator
-            _ => (),
-        };
-
-        // If we didn't find an overloaded deref or index, then assume it's a
-        // built in deref and check the type of the base.
-        let base_ty = deref_base.ty(self.body, tcx).ty;
-        if base_ty.is_unsafe_ptr() {
-            BorrowedContentSource::DerefRawPointer
-        } else if base_ty.is_mutable_pointer() {
-            BorrowedContentSource::DerefMutableRef
-        } else {
-            BorrowedContentSource::DerefSharedRef
-        }
-    }
 }
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 92c2e4e01f7..04814a15c62 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -1,17 +1,14 @@
 use rustc::hir;
 use rustc::hir::Node;
-use rustc::mir::{self, BindingForm, Constant, ClearCrossCrate, Local, Location, Body};
-use rustc::mir::{
-    Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static, StaticKind,
-};
-use rustc::mir::{Terminator, TerminatorKind};
-use rustc::ty::{self, Const, DefIdTree, Ty, TyS, TyCtxt};
+use rustc::mir::{self, BindingForm, ClearCrossCrate, Local, Location, Body};
+use rustc::mir::{Mutability, Place, PlaceBase, Projection, ProjectionElem, Static, StaticKind};
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
 use syntax_pos::symbol::kw;
 
-use crate::dataflow::move_paths::InitLocation;
 use crate::borrow_check::MirBorrowckCtxt;
+use crate::borrow_check::error_reporting::BorrowedContentSource;
 use crate::util::borrowck_errors::{BorrowckErrors, Origin};
 use crate::util::collect_writes::FindAssignments;
 use crate::util::suggest_ref_mut;
@@ -43,6 +40,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let mut err;
         let item_msg;
         let reason;
+        let mut opt_source = None;
         let access_place_desc = self.describe_place(access_place);
         debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
 
@@ -103,23 +101,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                     item_msg = format!("`{}`", access_place_desc.unwrap());
                     reason = ", as it is immutable for the pattern guard".to_string();
                 } else {
-                    let pointer_type =
-                        if base.ty(self.body, self.infcx.tcx).ty.is_region_ptr() {
-                            "`&` reference"
-                        } else {
-                            "`*const` pointer"
-                        };
+                    let source = self.borrowed_content_source(base);
+                    let pointer_type = source.describe_for_immutable_place();
+                    opt_source = Some(source);
                     if let Some(desc) = access_place_desc {
                         item_msg = format!("`{}`", desc);
                         reason = match error_access {
                             AccessKind::Move |
-                            AccessKind::Mutate => format!(" which is behind a {}", pointer_type),
+                            AccessKind::Mutate => format!(" which is behind {}", pointer_type),
                             AccessKind::MutableBorrow => {
-                                format!(", as it is behind a {}", pointer_type)
+                                format!(", as it is behind {}", pointer_type)
                             }
                         }
                     } else {
-                        item_msg = format!("data in a {}", pointer_type);
+                        item_msg = format!("data in {}", pointer_type);
                         reason = String::new();
                     }
                 }
@@ -457,59 +452,31 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             }
 
             Place::Projection(box Projection {
-                base: Place::Base(PlaceBase::Local(local)),
+                base: _,
                 elem: ProjectionElem::Deref,
-            })  if error_access == AccessKind::MutableBorrow => {
+            }) => {
                 err.span_label(span, format!("cannot {ACT}", ACT = act));
 
-                let mpi = self.move_data.rev_lookup.find_local(*local);
-                for i in self.move_data.init_path_map[mpi].iter() {
-                    if let InitLocation::Statement(location) = self.move_data.inits[*i].location {
-                        if let Some(
-                            Terminator {
-                                kind: TerminatorKind::Call {
-                                    func: Operand::Constant(box Constant {
-                                        literal: Const {
-                                            ty: &TyS {
-                                                sty: ty::FnDef(id, substs),
-                                                ..
-                                            },
-                                            ..
-                                        },
-                                        ..
-                                    }),
-                                    ..
-                                },
-                                ..
-                            }
-                        ) = &self.body.basic_blocks()[location.block].terminator {
-                            let index_trait = self.infcx.tcx.lang_items().index_trait();
-                            if self.infcx.tcx.parent(id) == index_trait {
-                                let mut found = false;
-                                self.infcx.tcx.for_each_relevant_impl(
-                                    self.infcx.tcx.lang_items().index_mut_trait().unwrap(),
-                                    substs.type_at(0),
-                                    |_relevant_impl| {
-                                        found = true;
-                                    }
-                                );
-
-                                let extra = if found {
-                                    String::new()
-                                } else {
-                                    format!(", but it is not implemented for `{}`",
-                                            substs.type_at(0))
-                                };
-
-                                err.help(
-                                    &format!(
-                                        "trait `IndexMut` is required to modify indexed content{}",
-                                         extra,
-                                    ),
-                                );
-                            }
-                        }
+                match opt_source {
+                    Some(BorrowedContentSource::OverloadedDeref(ty)) => {
+                        err.help(
+                            &format!(
+                                "trait `DerefMut` is required to modify through a dereference, \
+                                but it is not implemented for `{}`",
+                                ty,
+                            ),
+                        );
+                    },
+                    Some(BorrowedContentSource::OverloadedIndex(ty)) => {
+                        err.help(
+                            &format!(
+                                "trait `IndexMut` is required to modify indexed content, \
+                                but it is not implemented for `{}`",
+                                ty,
+                            ),
+                        );
                     }
+                    _ => (),
                 }
             }
 
diff --git a/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.rs b/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.rs
index 01dc0af8550..83eab7fdeab 100644
--- a/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.rs
+++ b/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.rs
@@ -2,18 +2,7 @@
 // Deref and not DerefMut is implemented.
 
 use std::ops::Deref;
-
-struct Rc<T> {
-    value: *const T
-}
-
-impl<T> Deref for Rc<T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        unsafe { &*self.value }
-    }
-}
+use std::rc::Rc;
 
 struct Point {
     x: isize,
diff --git a/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr b/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr
index dc52685363e..d262c578843 100644
--- a/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr
+++ b/src/test/ui/borrowck/borrowck-borrow-overloaded-auto-deref.stderr
@@ -1,86 +1,114 @@
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:47:19
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:36:19
    |
 LL |     let __isize = &mut x.y;
    |                   ^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:51:19
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:40:19
    |
 LL |     let __isize = &mut x.y;
    |                   ^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:59:5
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:48:5
    |
 LL |     &mut x.y
    |     ^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:63:5
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:52:5
    |
 LL |     &mut x.y
    |     ^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0594]: cannot assign to data in a `&` reference
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:67:5
+error[E0594]: cannot assign to data in an `Rc`
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:56:5
    |
 LL |     x.y = 3;
    |     ^^^^^^^ cannot assign
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0594]: cannot assign to data in a `&` reference
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:71:5
+error[E0594]: cannot assign to data in an `Rc`
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:60:5
    |
 LL |     x.y = 3;
    |     ^^^^^^^ cannot assign
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0594]: cannot assign to data in a `&` reference
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:75:5
+error[E0594]: cannot assign to data in an `Rc`
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:64:5
    |
 LL |     x.y = 3;
    |     ^^^^^^^ cannot assign
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:83:5
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:72:5
    |
 LL |     x.set(0, 0);
    |     ^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:87:5
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:76:5
    |
 LL |     x.set(0, 0);
    |     ^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:95:5
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:84:5
    |
 LL |     x.y_mut()
    |     ^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:99:5
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:88:5
    |
 LL |     x.y_mut()
    |     ^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:103:6
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:92:6
    |
 LL |     *x.y_mut() = 3;
    |      ^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:107:6
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:96:6
    |
 LL |     *x.y_mut() = 3;
    |      ^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:111:6
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-auto-deref.rs:100:6
    |
 LL |     *x.y_mut() = 3;
    |      ^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<Point>`
 
 error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.rs b/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.rs
index 39fa70c4e59..2b98a7b9483 100644
--- a/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.rs
+++ b/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.rs
@@ -2,18 +2,7 @@
 // Deref and not DerefMut is implemented.
 
 use std::ops::Deref;
-
-struct Rc<T> {
-    value: *const T
-}
-
-impl<T> Deref for Rc<T> {
-    type Target = T;
-
-    fn deref<'a>(&'a self) -> &'a T {
-        unsafe { &*self.value }
-    }
-}
+use std::rc::Rc;
 
 fn deref_imm(x: Rc<isize>) {
     let __isize = &*x;
diff --git a/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.stderr b/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.stderr
index 1755b22f59d..8cacc29414d 100644
--- a/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.stderr
+++ b/src/test/ui/borrowck/borrowck-borrow-overloaded-deref.stderr
@@ -1,44 +1,58 @@
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-deref.rs:23:19
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:12:19
    |
 LL |     let __isize = &mut *x;
    |                   ^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-deref.rs:27:19
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:16:19
    |
 LL |     let __isize = &mut *x;
    |                   ^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-deref.rs:35:5
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:24:5
    |
 LL |     &mut **x
    |     ^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-borrow-overloaded-deref.rs:39:5
+error[E0596]: cannot borrow data in an `Rc` as mutable
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:28:5
    |
 LL |     &mut **x
    |     ^^^^^^^^ cannot borrow as mutable
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
 
-error[E0594]: cannot assign to data in a `&` reference
-  --> $DIR/borrowck-borrow-overloaded-deref.rs:43:5
+error[E0594]: cannot assign to data in an `Rc`
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:32:5
    |
 LL |     *x = 3;
    |     ^^^^^^ cannot assign
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
 
-error[E0594]: cannot assign to data in a `&` reference
-  --> $DIR/borrowck-borrow-overloaded-deref.rs:47:5
+error[E0594]: cannot assign to data in an `Rc`
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:36:5
    |
 LL |     **x = 3;
    |     ^^^^^^^ cannot assign
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
 
-error[E0594]: cannot assign to data in a `&` reference
-  --> $DIR/borrowck-borrow-overloaded-deref.rs:51:5
+error[E0594]: cannot assign to data in an `Rc`
+  --> $DIR/borrowck-borrow-overloaded-deref.rs:40:5
    |
 LL |     **x = 3;
    |     ^^^^^^^ cannot assign
+   |
+   = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `std::rc::Rc<isize>`
 
 error: aborting due to 7 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.rs b/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.rs
index cb20873432b..8adafaa8e93 100644
--- a/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.rs
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.rs
@@ -54,6 +54,6 @@ fn main() {
         x: 1,
     };
     s[2] = 20;
-    //~^ ERROR cannot assign to data in a `&` reference
+    //~^ ERROR cannot assign to data in an index of `Bar`
     drop(rs);
 }
diff --git a/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.stderr b/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.stderr
index fcbfe72a34b..84fe17d8544 100644
--- a/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.stderr
+++ b/src/test/ui/borrowck/borrowck-overloaded-index-ref-index.stderr
@@ -21,11 +21,13 @@ LL |     f[&s] = 10;
 LL |     drop(rs);
    |          -- mutable borrow later used here
 
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to data in an index of `Bar`
   --> $DIR/borrowck-overloaded-index-ref-index.rs:56:5
    |
 LL |     s[2] = 20;
    |     ^^^^^^^^^ cannot assign
+   |
+   = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `Bar`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/index-mut-help-with-impl.stderr b/src/test/ui/borrowck/index-mut-help-with-impl.stderr
index 4b29beb02b3..89391f4099a 100644
--- a/src/test/ui/borrowck/index-mut-help-with-impl.stderr
+++ b/src/test/ui/borrowck/index-mut-help-with-impl.stderr
@@ -3,8 +3,6 @@ error[E0596]: cannot borrow data in a `&` reference as mutable
    |
 LL |     Index::index(&v, 1..2).make_ascii_uppercase();
    |     ^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
-   |
-   = help: trait `IndexMut` is required to modify indexed content
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/index-mut-help.stderr b/src/test/ui/borrowck/index-mut-help.stderr
index fbc427a6e6d..47f2171f88c 100644
--- a/src/test/ui/borrowck/index-mut-help.stderr
+++ b/src/test/ui/borrowck/index-mut-help.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow data in a `&` reference as mutable
+error[E0596]: cannot borrow data in an index of `std::collections::HashMap<&str, std::string::String>` as mutable
   --> $DIR/index-mut-help.rs:11:5
    |
 LL |     map["peter"].clear();
@@ -6,13 +6,15 @@ LL |     map["peter"].clear();
    |
    = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<&str, std::string::String>`
 
-error[E0594]: cannot assign to data in a `&` reference
+error[E0594]: cannot assign to data in an index of `std::collections::HashMap<&str, std::string::String>`
   --> $DIR/index-mut-help.rs:12:5
    |
 LL |     map["peter"] = "0".to_string();
    |     ^^^^^^^^^^^^ cannot assign
+   |
+   = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::collections::HashMap<&str, std::string::String>`
 
-error[E0596]: cannot borrow data in a `&` reference as mutable
+error[E0596]: cannot borrow data in an index of `std::collections::HashMap<&str, std::string::String>` as mutable
   --> $DIR/index-mut-help.rs:13:13
    |
 LL |     let _ = &mut map["peter"];
diff --git a/src/test/ui/issues/issue-41726.rs b/src/test/ui/issues/issue-41726.rs
index ed056293890..39631912c00 100644
--- a/src/test/ui/issues/issue-41726.rs
+++ b/src/test/ui/issues/issue-41726.rs
@@ -2,6 +2,6 @@ use std::collections::HashMap;
 fn main() {
     let things: HashMap<String, Vec<String>> = HashMap::new();
     for src in things.keys() {
-        things[src.as_str()].sort(); //~ ERROR cannot borrow data in a `&` reference as mutable
+        things[src.as_str()].sort(); //~ ERROR cannot borrow data in an index of
     }
 }
diff --git a/src/test/ui/issues/issue-41726.stderr b/src/test/ui/issues/issue-41726.stderr
index c92753d6e3d..aa7f23511dd 100644
--- a/src/test/ui/issues/issue-41726.stderr
+++ b/src/test/ui/issues/issue-41726.stderr
@@ -1,4 +1,4 @@
-error[E0596]: cannot borrow data in a `&` reference as mutable
+error[E0596]: cannot borrow data in an index of `std::collections::HashMap<std::string::String, std::vec::Vec<std::string::String>>` as mutable
   --> $DIR/issue-41726.rs:5:9
    |
 LL |         things[src.as_str()].sort();