Skip to content

Commit a72790d

Browse files
committed
When using NLL, implicitly borrow match bindings for any guard,
deref'ing such borrows within that guard. Review feedback: Add comment noting a point where we may or may not need to add a cast when we finish the work on #27282. Review feedback: Pass a newtype'd `ArmHasGuard` rather than a raw boolean. Review feedback: toggle "ref binding in guards" semantics via specific method. (This should ease a follow-up PR that just unconditionally adopts the new semantics.)
1 parent b00db7c commit a72790d

File tree

5 files changed

+373
-38
lines changed

5 files changed

+373
-38
lines changed

src/librustc/ty/context.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1467,6 +1467,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
14671467
self.borrowck_mode().use_mir()
14681468
}
14691469

1470+
/// If true, pattern variables for use in guards on match arms
1471+
/// will be bound as references to the data, and occurrences of
1472+
/// those variables in the guard expression will implicitly
1473+
/// dereference those bindings. (See rust-lang/rust#27282.)
1474+
pub fn all_pat_vars_are_implicit_refs_within_guards(self) -> bool {
1475+
self.borrowck_mode().use_mir()
1476+
}
1477+
14701478
/// If true, we should enable two-phase borrows checks. This is
14711479
/// done with either `-Ztwo-phase-borrows` or with
14721480
/// `#![feature(nll)]`.

src/librustc_mir/build/block.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
// except according to those terms.
1010

1111
use build::{BlockAnd, BlockAndExtension, Builder};
12+
use build::ForGuard::OutsideGuard;
13+
use build::matches::ArmHasGuard;
1214
use hair::*;
1315
use rustc::mir::*;
1416
use rustc::hir;
@@ -113,7 +115,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
113115
// Declare the bindings, which may create a visibility scope.
114116
let remainder_span = remainder_scope.span(this.hir.tcx(),
115117
&this.hir.region_scope_tree);
116-
let scope = this.declare_bindings(None, remainder_span, lint_level, &pattern);
118+
let scope = this.declare_bindings(None, remainder_span, lint_level, &pattern,
119+
ArmHasGuard(false));
117120

118121
// Evaluate the initializer, if present.
119122
if let Some(init) = initializer {
@@ -135,8 +138,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
135138
}
136139

137140
this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| {
138-
this.storage_live_binding(block, node, span);
139-
this.schedule_drop_for_binding(node, span);
141+
this.storage_live_binding(block, node, span, OutsideGuard);
142+
this.schedule_drop_for_binding(node, span, OutsideGuard);
140143
})
141144
}
142145

src/librustc_mir/build/expr/as_place.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//! See docs in build/expr/mod.rs
1212
1313
use build::{BlockAnd, BlockAndExtension, Builder};
14+
use build::ForGuard::{OutsideGuard, WithinGuard};
1415
use build::expr::category::Category;
1516
use hair::*;
1617
use rustc::mir::*;
@@ -86,8 +87,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
8687
block.and(Place::Local(Local::new(1)))
8788
}
8889
ExprKind::VarRef { id } => {
89-
let index = this.var_indices[&id];
90-
block.and(Place::Local(index))
90+
let place = if this.is_bound_var_in_guard(id) {
91+
let index = this.var_local_id(id, WithinGuard);
92+
if this.hir.tcx().all_pat_vars_are_implicit_refs_within_guards() {
93+
Place::Local(index).deref()
94+
} else {
95+
Place::Local(index)
96+
}
97+
} else {
98+
let index = this.var_local_id(id, OutsideGuard);
99+
Place::Local(index)
100+
};
101+
block.and(place)
91102
}
92103
ExprKind::StaticRef { id } => {
93104
block.and(Place::Static(Box::new(Static { def_id: id, ty: expr.ty })))

0 commit comments

Comments
 (0)