summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-06-01 20:38:24 +0000
committerbors <bors@rust-lang.org>2018-06-01 20:38:24 +0000
commit594fb253c2b02b320c728391a425d028e6dc7a09 (patch)
tree774dd13bd4cdf23d042ba7c005a4a3f55ac48382
parent827013a31b88e536e85b8e6ceb5b9988042ec335 (diff)
parent7093b11690486e5fd3502b299b5477a83fd3b001 (diff)
Auto merge of #51258 - Mark-Simulacrum:stable-next, r=nikomatsakis1.26.2
1.26.2 release This includes a backport of #51235 which fixes #51117 on stable. It has not been tested. r? @nikomatsakis since the backport was not clean. cc @rust-lang/core @rust-lang/release
-rw-r--r--RELEASES.md10
-rw-r--r--src/bootstrap/channel.rs2
-rw-r--r--src/librustc/middle/expr_use_visitor.rs11
-rw-r--r--src/librustc/middle/mem_categorization.rs94
-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.rs25
-rw-r--r--src/test/ui/borrowck/issue-51117.stderr14
14 files changed, 139 insertions, 71 deletions
diff --git a/RELEASES.md b/RELEASES.md
index 758de62a848..0403a2ac1fe 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,13 @@
+Version 1.26.2 (2018-06-05)
+==========================
+
+Compatibility Notes
+-------------------
+
+- [The borrow checker was fixed to avoid unsoundness when using match ergonomics][51117]
+
+[51117]: https://github.com/rust-lang/rust/issues/51117
+
Version 1.26.1 (2018-05-29)
==========================
diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs
index 6b25a130ae0..fae79730669 100644
--- a/src/bootstrap/channel.rs
+++ b/src/bootstrap/channel.rs
@@ -24,7 +24,7 @@ use Build;
use config::Config;
// The version number
-pub const CFG_RELEASE_NUM: &str = "1.26.1";
+pub const CFG_RELEASE_NUM: &str = "1.26.2";
pub struct GitInfo {
inner: Option<Info>,
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 28524678e99..a7e68d807d0 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -845,17 +845,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 5875e5e4097..4aaa791cc2e 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
@@ -161,6 +158,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
}
@@ -224,8 +222,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) =>
@@ -321,7 +318,7 @@ impl MutabilityCategory {
Unique => {
base_mutbl.inherit()
}
- BorrowedPtr(borrow_kind, _) | Implicit(borrow_kind, _) => {
+ BorrowedPtr(borrow_kind, _) => {
MutabilityCategory::from_borrow_kind(borrow_kind)
}
UnsafePtr(m) => {
@@ -610,7 +607,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 |
@@ -633,10 +630,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 = self.cat_expr(&e_base)?;
- self.cat_deref(expr, base_cmt, false)
+ self.cat_deref(expr, base_cmt, NoteNone)
}
}
@@ -661,7 +658,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 = self.cat_expr(&base)?;
self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index)
@@ -1012,12 +1009,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
@@ -1037,14 +1040,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
});
let base_cmt = 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;
@@ -1060,9 +1064,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
let ptr = match base_cmt.ty.sty {
ty::TyAdt(def, ..) if def.is_box() => Unique,
ty::TyRawPtr(ref mt) => UnsafePtr(mt.mutbl),
- ty::TyRef(r, mt) => {
- let bk = ty::BorrowKind::from_mutbl(mt.mutbl);
- if implicit { Implicit(bk, r) } else { BorrowedPtr(bk, r) }
+ ty::TyRef(r, ty) => {
+ let bk = ty::BorrowKind::from_mutbl(ty.mutbl);
+ BorrowedPtr(bk, r)
}
ref ty => bug!("unexpected type in cat_deref: {:?}", ty)
};
@@ -1073,7 +1077,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)
@@ -1207,7 +1211,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
@@ -1245,10 +1249,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
.pat_adjustments()
.get(pat.hir_id)
.map(|v| v.len())
- .unwrap_or(0) {
- cmt = self.cat_deref(pat, cmt, true /* implicit */)?;
+ .unwrap_or(0)
+ {
+ debug!("cat_pattern: applying adjustment to cmt={:?}", cmt);
+ cmt = 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.
//
@@ -1342,7 +1349,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 = self.cat_deref(pat, cmt, false)?;
+ let subcmt = self.cat_deref(pat, cmt, NoteNone)?;
self.cat_pattern_(subcmt, &subpat, op)?;
}
@@ -1403,7 +1410,6 @@ impl<'tcx> cmt_<'tcx> {
Categorization::Local(..) |
Categorization::Deref(_, UnsafePtr(..)) |
Categorization::Deref(_, BorrowedPtr(..)) |
- Categorization::Deref(_, Implicit(..)) |
Categorization::Upvar(..) => {
Rc::new((*self).clone())
}
@@ -1423,9 +1429,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, _) => {
@@ -1448,8 +1452,7 @@ impl<'tcx> cmt_<'tcx> {
}
}
- Categorization::Deref(_, BorrowedPtr(ty::ImmBorrow, _)) |
- Categorization::Deref(_, Implicit(ty::ImmBorrow, _)) => {
+ Categorization::Deref(_, BorrowedPtr(ty::ImmBorrow, _)) => {
FreelyAliasable(AliasableBorrowed)
}
}
@@ -1471,7 +1474,7 @@ impl<'tcx> cmt_<'tcx> {
_ => bug!()
})
}
- NoteNone => None
+ NoteIndex | NoteNone => None
}
}
@@ -1500,9 +1503,6 @@ impl<'tcx> cmt_<'tcx> {
Some(_) => bug!(),
None => {
match pk {
- Implicit(..) => {
- format!("indexed content")
- }
Unique => {
format!("`Box` content")
}
@@ -1510,7 +1510,10 @@ impl<'tcx> cmt_<'tcx> {
format!("dereference of raw pointer")
}
BorrowedPtr(..) => {
- format!("borrowed content")
+ match self.note {
+ NoteIndex => format!("indexed content"),
+ _ => format!("borrowed content"),
+ }
}
}
}
@@ -1541,12 +1544,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 de336c29229..441089250a1 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 465457f5ab3..766c38160ee 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
@@ -181,7 +181,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 97fa94b5e5c..d7bd4762e1a 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
@@ -75,7 +75,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))
}
@@ -123,8 +122,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 5cfbe49f77f..fc502978685 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs
@@ -147,7 +147,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 ae373fbad22..35870432d82 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -236,6 +236,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 9ed4ab45a1b..4e9dbd52e5e 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -1114,7 +1114,6 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
borrow_kind,
borrow_cmt);
match borrow_cmt.cat.clone() {
- 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 4fc3344dab2..56e088fcb22 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -328,8 +328,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
@@ -367,7 +366,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> {
var_name(tcx, upvar_id.var_id),
);
}
- mc::NoteNone => {}
+ mc::NoteIndex | mc::NoteNone => {}
}
}
_ => {}
@@ -389,8 +388,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
@@ -422,8 +420,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
@@ -481,7 +478,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.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`.