about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-05-31 10:17:51 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-05-31 10:17:51 -0400
commit8a624b737a772ecc6840870bbf895950602b2920 (patch)
treeac778ddc920a75d3fefbc1b44550a959df5a3fbc
parent5d0631a6438cf30cac236b7176371663e35c8d07 (diff)
downloadrust-8a624b737a772ecc6840870bbf895950602b2920.tar.gz
rust-8a624b737a772ecc6840870bbf895950602b2920.zip
change `PointerKind::Implicit` to a note
`PointerKind` is included in `LoanPath` and hence forms part of the
equality check; this led to having two unequal paths that both
represent `*x`, depending on whether the `*` was inserted
automatically or explicitly. Bad mojo. The `note` field, in contrast,
is intended more-or-less primarily for this purpose of adding extra
data.
-rw-r--r--src/librustc/middle/expr_use_visitor.rs11
-rw-r--r--src/librustc/middle/mem_categorization.rs90
-rw-r--r--src/librustc/traits/project.rs31
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs1
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/lifetime.rs4
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/move_error.rs1
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/restrictions.rs2
-rw-r--r--src/librustc_typeck/check/_match.rs1
-rw-r--r--src/librustc_typeck/check/regionck.rs1
-rw-r--r--src/librustc_typeck/check/upvar.rs13
-rw-r--r--src/test/ui/borrowck/issue-51117.nll.stderr13
-rw-r--r--src/test/ui/borrowck/issue-51117.rs25
-rw-r--r--src/test/ui/borrowck/issue-51117.stderr14
13 files changed, 139 insertions, 68 deletions
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index ddbc03292f6..9fb7d31ed6f 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -837,17 +837,24 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
     /// established up front, e.g. via `determine_pat_move_mode` (see
     /// also `walk_irrefutable_pat` for patterns that stand alone).
     fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) {
-        debug!("walk_pat cmt_discr={:?} pat={:?}", cmt_discr, pat);
+        debug!("walk_pat(cmt_discr={:?}, pat={:?})", cmt_discr, pat);
 
         let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self;
         return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| {
             if let PatKind::Binding(_, canonical_id, ..) = pat.node {
-                debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode);
+                debug!(
+                    "walk_pat: binding cmt_pat={:?} pat={:?} match_mode={:?}",
+                    cmt_pat,
+                    pat,
+                    match_mode,
+                );
                 let bm = *mc.tables.pat_binding_modes().get(pat.hir_id)
                                                      .expect("missing binding mode");
+                debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
 
                 // pat_ty: the type of the binding being produced.
                 let pat_ty = return_if_err!(mc.node_ty(pat.hir_id));
+                debug!("walk_pat: pat_ty={:?}", pat_ty);
 
                 // Each match binding is effectively an assignment to the
                 // binding being produced.
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 37732708733..f2120d97868 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -95,7 +95,7 @@ pub enum Categorization<'tcx> {
     StaticItem,
     Upvar(Upvar),                          // upvar referenced by closure env
     Local(ast::NodeId),                    // local variable
-    Deref(cmt<'tcx>, PointerKind<'tcx>),   // deref of a ptr
+    Deref(cmt<'tcx>, PointerKind<'tcx>), // deref of a ptr
     Interior(cmt<'tcx>, InteriorKind),     // something interior: field, tuple, etc
     Downcast(cmt<'tcx>, DefId),            // selects a particular enum variant (*1)
 
@@ -120,9 +120,6 @@ pub enum PointerKind<'tcx> {
 
     /// `*T`
     UnsafePtr(hir::Mutability),
-
-    /// Implicit deref of the `&T` that results from an overloaded index `[]`.
-    Implicit(ty::BorrowKind, ty::Region<'tcx>),
 }
 
 // We use the term "interior" to mean "something reachable from the
@@ -172,6 +169,7 @@ pub enum MutabilityCategory {
 pub enum Note {
     NoteClosureEnv(ty::UpvarId), // Deref through closure env
     NoteUpvarRef(ty::UpvarId),   // Deref through by-ref upvar
+    NoteIndex,                   // Deref as part of desugaring `x[]` into its two components
     NoteNone                     // Nothing special
 }
 
@@ -231,8 +229,7 @@ impl<'tcx> cmt_<'tcx> {
 
     pub fn immutability_blame(&self) -> Option<ImmutabilityBlame<'tcx>> {
         match self.cat {
-            Categorization::Deref(ref base_cmt, BorrowedPtr(ty::ImmBorrow, _)) |
-            Categorization::Deref(ref base_cmt, Implicit(ty::ImmBorrow, _)) => {
+            Categorization::Deref(ref base_cmt, BorrowedPtr(ty::ImmBorrow, _)) => {
                 // try to figure out where the immutable reference came from
                 match base_cmt.cat {
                     Categorization::Local(node_id) =>
@@ -328,7 +325,7 @@ impl MutabilityCategory {
             Unique => {
                 base_mutbl.inherit()
             }
-            BorrowedPtr(borrow_kind, _) | Implicit(borrow_kind, _) => {
+            BorrowedPtr(borrow_kind, _) => {
                 MutabilityCategory::from_borrow_kind(borrow_kind)
             }
             UnsafePtr(m) => {
@@ -617,7 +614,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                 } else {
                     previous()?
                 });
-                self.cat_deref(expr, base, false)
+                self.cat_deref(expr, base, NoteNone)
             }
 
             adjustment::Adjust::NeverToAny |
@@ -640,10 +637,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         match expr.node {
           hir::ExprUnary(hir::UnDeref, ref e_base) => {
             if self.tables.is_method_call(expr) {
-                self.cat_overloaded_place(expr, e_base, false)
+                self.cat_overloaded_place(expr, e_base, NoteNone)
             } else {
                 let base_cmt = Rc::new(self.cat_expr(&e_base)?);
-                self.cat_deref(expr, base_cmt, false)
+                self.cat_deref(expr, base_cmt, NoteNone)
             }
           }
 
@@ -664,7 +661,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                 // The call to index() returns a `&T` value, which
                 // is an rvalue. That is what we will be
                 // dereferencing.
-                self.cat_overloaded_place(expr, base, true)
+                self.cat_overloaded_place(expr, base, NoteIndex)
             } else {
                 let base_cmt = Rc::new(self.cat_expr(&base)?);
                 self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index)
@@ -999,12 +996,18 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         ret
     }
 
-    fn cat_overloaded_place(&self,
-                             expr: &hir::Expr,
-                             base: &hir::Expr,
-                             implicit: bool)
-                             -> McResult<cmt_<'tcx>> {
-        debug!("cat_overloaded_place: implicit={}", implicit);
+    fn cat_overloaded_place(
+        &self,
+        expr: &hir::Expr,
+        base: &hir::Expr,
+        note: Note,
+    ) -> McResult<cmt_<'tcx>> {
+        debug!(
+            "cat_overloaded_place(expr={:?}, base={:?}, note={:?})",
+            expr,
+            base,
+            note,
+        );
 
         // Reconstruct the output assuming it's a reference with the
         // same region and mutability as the receiver. This holds for
@@ -1024,14 +1027,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         });
 
         let base_cmt = Rc::new(self.cat_rvalue_node(expr.id, expr.span, ref_ty));
-        self.cat_deref(expr, base_cmt, implicit)
+        self.cat_deref(expr, base_cmt, note)
     }
 
-    pub fn cat_deref<N:ast_node>(&self,
-                                 node: &N,
-                                 base_cmt: cmt<'tcx>,
-                                 implicit: bool)
-                                 -> McResult<cmt_<'tcx>> {
+    pub fn cat_deref(
+        &self,
+        node: &impl ast_node,
+        base_cmt: cmt<'tcx>,
+        note: Note,
+    ) -> McResult<cmt_<'tcx>> {
         debug!("cat_deref: base_cmt={:?}", base_cmt);
 
         let base_cmt_ty = base_cmt.ty;
@@ -1049,7 +1053,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             ty::TyRawPtr(ref mt) => UnsafePtr(mt.mutbl),
             ty::TyRef(r, _, mutbl) => {
                 let bk = ty::BorrowKind::from_mutbl(mutbl);
-                if implicit { Implicit(bk, r) } else { BorrowedPtr(bk, r) }
+                BorrowedPtr(bk, r)
             }
             ref ty => bug!("unexpected type in cat_deref: {:?}", ty)
         };
@@ -1060,7 +1064,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             mutbl: MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr),
             cat: Categorization::Deref(base_cmt, ptr),
             ty: deref_ty,
-            note: NoteNone
+            note: note,
         };
         debug!("cat_deref ret {:?}", ret);
         Ok(ret)
@@ -1193,7 +1197,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
         // step out of sync again. So you'll see below that we always
         // get the type of the *subpattern* and use that.
 
-        debug!("cat_pattern: {:?} cmt={:?}", pat, cmt);
+        debug!("cat_pattern(pat={:?}, cmt={:?})", pat, cmt);
 
         // If (pattern) adjustments are active for this pattern, adjust the `cmt` correspondingly.
         // `cmt`s are constructed differently from patterns. For example, in
@@ -1231,10 +1235,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
                         .pat_adjustments()
                         .get(pat.hir_id)
                         .map(|v| v.len())
-                        .unwrap_or(0) {
-            cmt = Rc::new(self.cat_deref(pat, cmt, true /* implicit */)?);
+                        .unwrap_or(0)
+        {
+            debug!("cat_pattern: applying adjustment to cmt={:?}", cmt);
+            cmt = Rc::new(self.cat_deref(pat, cmt, NoteNone)?);
         }
         let cmt = cmt; // lose mutability
+        debug!("cat_pattern: applied adjustment derefs to get cmt={:?}", cmt);
 
         // Invoke the callback, but only now, after the `cmt` has adjusted.
         //
@@ -1330,7 +1337,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
             // box p1, &p1, &mut p1.  we can ignore the mutability of
             // PatKind::Ref since that information is already contained
             // in the type.
-            let subcmt = Rc::new(self.cat_deref(pat, cmt, false)?);
+            let subcmt = Rc::new(self.cat_deref(pat, cmt, NoteNone)?);
             self.cat_pattern_(subcmt, &subpat, op)?;
           }
 
@@ -1391,7 +1398,6 @@ impl<'tcx> cmt_<'tcx> {
             Categorization::Local(..) |
             Categorization::Deref(_, UnsafePtr(..)) |
             Categorization::Deref(_, BorrowedPtr(..)) |
-            Categorization::Deref(_, Implicit(..)) |
             Categorization::Upvar(..) => {
                 (*self).clone()
             }
@@ -1411,9 +1417,7 @@ impl<'tcx> cmt_<'tcx> {
 
         match self.cat {
             Categorization::Deref(ref b, BorrowedPtr(ty::MutBorrow, _)) |
-            Categorization::Deref(ref b, Implicit(ty::MutBorrow, _)) |
             Categorization::Deref(ref b, BorrowedPtr(ty::UniqueImmBorrow, _)) |
-            Categorization::Deref(ref b, Implicit(ty::UniqueImmBorrow, _)) |
             Categorization::Deref(ref b, Unique) |
             Categorization::Downcast(ref b, _) |
             Categorization::Interior(ref b, _) => {
@@ -1436,8 +1440,7 @@ impl<'tcx> cmt_<'tcx> {
                 }
             }
 
-            Categorization::Deref(_, BorrowedPtr(ty::ImmBorrow, _)) |
-            Categorization::Deref(_, Implicit(ty::ImmBorrow, _)) => {
+            Categorization::Deref(_, BorrowedPtr(ty::ImmBorrow, _)) => {
                 FreelyAliasable(AliasableBorrowed)
             }
         }
@@ -1460,7 +1463,7 @@ impl<'tcx> cmt_<'tcx> {
                     _ => bug!()
                 })
             }
-            NoteNone => None
+            NoteIndex | NoteNone => None
         }
     }
 
@@ -1487,9 +1490,6 @@ impl<'tcx> cmt_<'tcx> {
                     Some(_) => bug!(),
                     None => {
                         match pk {
-                            Implicit(..) => {
-                                format!("indexed content")
-                            }
                             Unique => {
                                 format!("`Box` content")
                             }
@@ -1497,7 +1497,10 @@ impl<'tcx> cmt_<'tcx> {
                                 format!("dereference of raw pointer")
                             }
                             BorrowedPtr(..) => {
-                                format!("borrowed content")
+                                match self.note {
+                                    NoteIndex => format!("indexed content"),
+                                    _ => format!("borrowed content"),
+                                }
                             }
                         }
                     }
@@ -1525,12 +1528,9 @@ impl<'tcx> cmt_<'tcx> {
 pub fn ptr_sigil(ptr: PointerKind) -> &'static str {
     match ptr {
         Unique => "Box",
-        BorrowedPtr(ty::ImmBorrow, _) |
-        Implicit(ty::ImmBorrow, _) => "&",
-        BorrowedPtr(ty::MutBorrow, _) |
-        Implicit(ty::MutBorrow, _) => "&mut",
-        BorrowedPtr(ty::UniqueImmBorrow, _) |
-        Implicit(ty::UniqueImmBorrow, _) => "&unique",
+        BorrowedPtr(ty::ImmBorrow, _) => "&",
+        BorrowedPtr(ty::MutBorrow, _) => "&mut",
+        BorrowedPtr(ty::UniqueImmBorrow, _) => "&unique",
         UnsafePtr(_) => "*",
     }
 }
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 174c35d1d69..c6b1d94e597 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -137,17 +137,30 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
     fn push_candidate(&mut self, candidate: ProjectionTyCandidate<'tcx>) -> bool {
         use self::ProjectionTyCandidateSet::*;
         use self::ProjectionTyCandidate::*;
+
+        // This wacky variable is just used to try and
+        // make code readable and avoid confusing paths.
+        // It is assigned a "value" of `()` only on those
+        // paths in which we wish to convert `*self` to
+        // ambiguous (and return false, because the candidate
+        // was not used). On other paths, it is not assigned,
+        // and hence if those paths *could* reach the code that
+        // comes after the match, this fn would not compile.
+        let convert_to_ambigious;
+
         match self {
             None => {
                 *self = Single(candidate);
-                true
+                return true;
             }
+
             Single(current) => {
                 // Duplicates can happen inside ParamEnv. In the case, we
                 // perform a lazy deduplication.
                 if current == &candidate {
                     return false;
                 }
+
                 // Prefer where-clauses. As in select, if there are multiple
                 // candidates, we prefer where-clause candidates over impls.  This
                 // may seem a bit surprising, since impls are the source of
@@ -156,17 +169,23 @@ impl<'tcx> ProjectionTyCandidateSet<'tcx> {
                 // clauses are the safer choice. See the comment on
                 // `select::SelectionCandidate` and #21974 for more details.
                 match (current, candidate) {
-                    (ParamEnv(..), ParamEnv(..)) => { *self = Ambiguous; }
-                    (ParamEnv(..), _) => {}
+                    (ParamEnv(..), ParamEnv(..)) => convert_to_ambigious = (),
+                    (ParamEnv(..), _) => return false,
                     (_, ParamEnv(..)) => { unreachable!(); }
-                    (_, _) => { *self = Ambiguous; }
+                    (_, _) => convert_to_ambigious = (),
                 }
-                false
             }
+
             Ambiguous | Error(..) => {
-                false
+                return false;
             }
         }
+
+        // We only ever get here when we moved from a single candidate
+        // to ambiguous.
+        let () = convert_to_ambigious;
+        *self = Ambiguous;
+        false
     }
 }
 
diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
index ac905d6de5d..fa9bb57275a 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
@@ -180,7 +180,6 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                                -> Option<mc::cmt_<'tcx>> {
     match cmt.cat {
         Categorization::Deref(_, mc::BorrowedPtr(..)) |
-        Categorization::Deref(_, mc::Implicit(..)) |
         Categorization::Deref(_, mc::UnsafePtr(..)) |
         Categorization::StaticItem => {
             Some(cmt.clone())
diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
index 6d73500d318..323e0997e3e 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
@@ -74,7 +74,6 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
             Categorization::Local(..) |                     // L-Local
             Categorization::Upvar(..) |
             Categorization::Deref(_, mc::BorrowedPtr(..)) | // L-Deref-Borrowed
-            Categorization::Deref(_, mc::Implicit(..)) |
             Categorization::Deref(_, mc::UnsafePtr(..)) => {
                 self.check_scope(self.scope(cmt))
             }
@@ -122,8 +121,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
             Categorization::Deref(_, mc::UnsafePtr(..)) => {
                 self.bccx.tcx.types.re_static
             }
-            Categorization::Deref(_, mc::BorrowedPtr(_, r)) |
-            Categorization::Deref(_, mc::Implicit(_, r)) => {
+            Categorization::Deref(_, mc::BorrowedPtr(_, r)) => {
                 r
             }
             Categorization::Downcast(ref cmt, _) |
diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
index 1f2b917bdb9..18026a14259 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
@@ -140,7 +140,6 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &'a BorrowckCtxt<'a, 'tcx>,
                                        -> DiagnosticBuilder<'a> {
     match move_from.cat {
         Categorization::Deref(_, mc::BorrowedPtr(..)) |
-        Categorization::Deref(_, mc::Implicit(..)) |
         Categorization::Deref(_, mc::UnsafePtr(..)) |
         Categorization::StaticItem => {
             bccx.cannot_move_out_of(
diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
index 408ab44cde6..e332f683275 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
@@ -149,7 +149,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> {
                         let result = self.restrict(&cmt_base);
                         self.extend(result, &cmt, LpDeref(pk))
                     }
-                    mc::Implicit(bk, lt) | mc::BorrowedPtr(bk, lt) => {
+                    mc::BorrowedPtr(bk, lt) => {
                         // R-Deref-[Mut-]Borrowed
                         if !self.bccx.is_subregion_of(self.loan_region, lt) {
                             self.bccx.report(
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 439c0e2d610..f0f920966da 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -234,6 +234,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                     .borrow_mut()
                     .pat_binding_modes_mut()
                     .insert(pat.hir_id, bm);
+                debug!("check_pat_walk: pat.hir_id={:?} bm={:?}", pat.hir_id, bm);
                 let typ = self.local_ty(pat.span, pat.id);
                 match bm {
                     ty::BindByReference(mutbl) => {
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index fa8045d7032..f6fcf2fcd48 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -1111,7 +1111,6 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
                    borrow_kind,
                    borrow_cmt);
             match borrow_cmt_cat {
-                Categorization::Deref(ref_cmt, mc::Implicit(ref_kind, ref_region)) |
                 Categorization::Deref(ref_cmt, mc::BorrowedPtr(ref_kind, ref_region)) => {
                     match self.link_reborrowed_region(span,
                                                       borrow_region, borrow_kind,
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 6bede52b239..cfb9c2a5062 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -332,8 +332,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
             guarantor.cat
         );
         match guarantor.cat {
-            Categorization::Deref(_, mc::BorrowedPtr(..)) |
-            Categorization::Deref(_, mc::Implicit(..)) => {
+            Categorization::Deref(_, mc::BorrowedPtr(..)) => {
                 debug!(
                     "adjust_upvar_borrow_kind_for_consume: found deref with note {:?}",
                     cmt.note
@@ -371,7 +370,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
                             var_name(tcx, upvar_id.var_id),
                         );
                     }
-                    mc::NoteNone => {}
+                    mc::NoteIndex | mc::NoteNone => {}
                 }
             }
             _ => {}
@@ -393,8 +392,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
                 self.adjust_upvar_borrow_kind_for_mut(&base);
             }
 
-            Categorization::Deref(base, mc::BorrowedPtr(..)) |
-            Categorization::Deref(base, mc::Implicit(..)) => {
+            Categorization::Deref(base, mc::BorrowedPtr(..)) => {
                 if !self.try_adjust_upvar_deref(cmt, ty::MutBorrow) {
                     // assignment to deref of an `&mut`
                     // borrowed pointer implies that the
@@ -426,8 +424,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
                 self.adjust_upvar_borrow_kind_for_unique(&base);
             }
 
-            Categorization::Deref(base, mc::BorrowedPtr(..)) |
-            Categorization::Deref(base, mc::Implicit(..)) => {
+            Categorization::Deref(base, mc::BorrowedPtr(..)) => {
                 if !self.try_adjust_upvar_deref(cmt, ty::UniqueImmBorrow) {
                     // for a borrowed pointer to be unique, its
                     // base must be unique
@@ -487,7 +484,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
 
                 true
             }
-            mc::NoteNone => false,
+            mc::NoteIndex | mc::NoteNone => false,
         }
     }
 
diff --git a/src/test/ui/borrowck/issue-51117.nll.stderr b/src/test/ui/borrowck/issue-51117.nll.stderr
new file mode 100644
index 00000000000..1ddca213202
--- /dev/null
+++ b/src/test/ui/borrowck/issue-51117.nll.stderr
@@ -0,0 +1,13 @@
+error[E0499]: cannot borrow `*bar` as mutable more than once at a time
+  --> $DIR/issue-51117.rs:20:13
+   |
+LL |         Some(baz) => {
+   |              --- first mutable borrow occurs here
+LL |             bar.take(); //~ ERROR cannot borrow
+   |             ^^^ second mutable borrow occurs here
+LL |             drop(baz);
+   |                  --- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/src/test/ui/borrowck/issue-51117.rs b/src/test/ui/borrowck/issue-51117.rs
new file mode 100644
index 00000000000..0a1e672b577
--- /dev/null
+++ b/src/test/ui/borrowck/issue-51117.rs
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #51117 in borrowck interaction with match
+// default bindings. The borrow of `*bar` created by `baz` was failing
+// to register as a conflict with `bar.take()`.
+
+fn main() {
+    let mut foo = Some("foo".to_string());
+    let bar = &mut foo;
+    match bar {
+        Some(baz) => {
+            bar.take(); //~ ERROR cannot borrow
+            drop(baz);
+        },
+        None => unreachable!(),
+    }
+}
diff --git a/src/test/ui/borrowck/issue-51117.stderr b/src/test/ui/borrowck/issue-51117.stderr
new file mode 100644
index 00000000000..cb434f9b322
--- /dev/null
+++ b/src/test/ui/borrowck/issue-51117.stderr
@@ -0,0 +1,14 @@
+error[E0499]: cannot borrow `*bar` as mutable more than once at a time
+  --> $DIR/issue-51117.rs:20:13
+   |
+LL |         Some(baz) => {
+   |              --- first mutable borrow occurs here
+LL |             bar.take(); //~ ERROR cannot borrow
+   |             ^^^ second mutable borrow occurs here
+...
+LL |     }
+   |     - first borrow ends here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0499`.