Skip to content

Commit f64b66a

Browse files
committed
Do not downgrade NLL errors for bind_by_move_pattern_guards when AST says it is OK.
1 parent 04b88a9 commit f64b66a

File tree

4 files changed

+47
-27
lines changed

4 files changed

+47
-27
lines changed

src/librustc/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ rustc_queries! {
461461
}
462462

463463
TypeChecking {
464-
query check_match(key: DefId) -> () {
464+
query check_match(key: DefId) -> SignalledError {
465465
cache_on_disk_if { key.is_local() }
466466
}
467467

src/librustc/ty/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::hir::def::{DefKind, Export};
44
use crate::hir::{self, TraitCandidate, ItemLocalId, CodegenFnAttrs};
55
use crate::infer::canonical::{self, Canonical};
66
use crate::lint;
7-
use crate::middle::borrowck::BorrowCheckResult;
7+
use crate::middle::borrowck::{BorrowCheckResult, SignalledError};
88
use crate::middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary, ForeignModule};
99
use crate::middle::cstore::{NativeLibraryKind, DepKind, CrateSource};
1010
use crate::middle::privacy::AccessLevels;

src/librustc_ast_borrowck/borrowck/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ fn borrowck(tcx: TyCtxt<'_>, owner_def_id: DefId) -> &BorrowCheckResult {
6666

6767
debug!("borrowck(body_owner_def_id={:?})", owner_def_id);
6868

69+
let signalled_error = tcx.check_match(owner_def_id);
70+
if let SignalledError::SawSomeError = signalled_error {
71+
return tcx.arena.alloc(BorrowCheckResult {
72+
signalled_any_error: SignalledError::SawSomeError,
73+
})
74+
}
75+
6976
let owner_id = tcx.hir().as_local_hir_id(owner_def_id).unwrap();
7077

7178
match tcx.hir().get(owner_id) {

src/librustc_mir/hair/pattern/check_match.rs

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use super::_match::WitnessPreference::*;
44

55
use super::{Pattern, PatternContext, PatternError, PatternKind};
66

7+
use rustc::middle::borrowck::SignalledError;
78
use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
89
use rustc::middle::expr_use_visitor::{LoanCause, MutateMode};
910
use rustc::middle::expr_use_visitor as euv;
@@ -26,21 +27,24 @@ use std::slice;
2627

2728
use syntax_pos::{Span, DUMMY_SP, MultiSpan};
2829

29-
pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
30+
crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) -> SignalledError {
3031
let body_id = if let Some(id) = tcx.hir().as_local_hir_id(def_id) {
3132
tcx.hir().body_owned_by(id)
3233
} else {
33-
return;
34+
return SignalledError::NoErrorsSeen;
3435
};
3536

36-
MatchVisitor {
37+
let mut visitor = MatchVisitor {
3738
tcx,
3839
body_owner: def_id,
3940
tables: tcx.body_tables(body_id),
4041
region_scope_tree: &tcx.region_scope_tree(def_id),
4142
param_env: tcx.param_env(def_id),
4243
identity_substs: InternalSubsts::identity_for_item(tcx, def_id),
43-
}.visit_body(tcx.hir().body(body_id));
44+
signalled_error: SignalledError::NoErrorsSeen,
45+
};
46+
visitor.visit_body(tcx.hir().body(body_id));
47+
visitor.signalled_error
4448
}
4549

4650
fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBuilder<'_> {
@@ -54,6 +58,7 @@ struct MatchVisitor<'a, 'tcx> {
5458
param_env: ty::ParamEnv<'tcx>,
5559
identity_substs: SubstsRef<'tcx>,
5660
region_scope_tree: &'a region::ScopeTree,
61+
signalled_error: SignalledError,
5762
}
5863

5964
impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
@@ -64,11 +69,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
6469
fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
6570
intravisit::walk_expr(self, ex);
6671

67-
match ex.node {
68-
hir::ExprKind::Match(ref scrut, ref arms, source) => {
69-
self.check_match(scrut, arms, source);
70-
}
71-
_ => {}
72+
if let hir::ExprKind::Match(ref scrut, ref arms, source) = ex.node {
73+
self.check_match(scrut, arms, source);
7274
}
7375
}
7476

@@ -130,27 +132,29 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
130132
}
131133

132134
impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
133-
fn check_patterns(&self, has_guard: bool, pats: &[P<Pat>]) {
135+
fn check_patterns(&mut self, has_guard: bool, pats: &[P<Pat>]) {
134136
check_legality_of_move_bindings(self, has_guard, pats);
135137
for pat in pats {
136138
check_legality_of_bindings_in_at_patterns(self, pat);
137139
}
138140
}
139141

140142
fn check_match(
141-
&self,
143+
&mut self,
142144
scrut: &hir::Expr,
143145
arms: &'tcx [hir::Arm],
144-
source: hir::MatchSource)
145-
{
146+
source: hir::MatchSource
147+
) {
146148
for arm in arms {
147149
// First, check legality of move bindings.
148150
self.check_patterns(arm.guard.is_some(), &arm.pats);
149151

150152
// Second, if there is a guard on each arm, make sure it isn't
151153
// assigning or borrowing anything mutably.
152154
if let Some(ref guard) = arm.guard {
153-
if !self.tcx.features().bind_by_move_pattern_guards {
155+
if self.tcx.features().bind_by_move_pattern_guards {
156+
self.signalled_error = SignalledError::SawSomeError;
157+
} else {
154158
check_for_mutation_in_guard(self, &guard);
155159
}
156160
}
@@ -548,7 +552,7 @@ fn maybe_point_at_variant(
548552

549553
// Legality of move bindings checking
550554
fn check_legality_of_move_bindings(
551-
cx: &MatchVisitor<'_, '_>,
555+
cx: &mut MatchVisitor<'_, '_>,
552556
has_guard: bool,
553557
pats: &[P<Pat>],
554558
) {
@@ -565,7 +569,12 @@ fn check_legality_of_move_bindings(
565569
})
566570
}
567571
let span_vec = &mut Vec::new();
568-
let check_move = |p: &Pat, sub: Option<&Pat>, span_vec: &mut Vec<Span>| {
572+
let check_move = |
573+
cx: &mut MatchVisitor<'_, '_>,
574+
p: &Pat,
575+
sub: Option<&Pat>,
576+
span_vec: &mut Vec<Span>,
577+
| {
569578
// check legality of moving out of the enum
570579

571580
// x @ Foo(..) is legal, but x @ Foo(y) isn't.
@@ -574,15 +583,19 @@ fn check_legality_of_move_bindings(
574583
"cannot bind by-move with sub-bindings")
575584
.span_label(p.span, "binds an already bound by-move value by moving it")
576585
.emit();
577-
} else if has_guard && !cx.tcx.features().bind_by_move_pattern_guards {
578-
let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008,
579-
"cannot bind by-move into a pattern guard");
580-
err.span_label(p.span, "moves value into pattern guard");
581-
if cx.tcx.sess.opts.unstable_features.is_nightly_build() {
582-
err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \
583-
crate attributes to enable");
586+
} else if has_guard {
587+
if cx.tcx.features().bind_by_move_pattern_guards {
588+
cx.signalled_error = SignalledError::SawSomeError;
589+
} else {
590+
let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008,
591+
"cannot bind by-move into a pattern guard");
592+
err.span_label(p.span, "moves value into pattern guard");
593+
if cx.tcx.sess.opts.unstable_features.is_nightly_build() {
594+
err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \
595+
crate attributes to enable");
596+
}
597+
err.emit();
584598
}
585-
err.emit();
586599
} else if let Some(_by_ref_span) = by_ref_span {
587600
span_vec.push(p.span);
588601
}
@@ -596,7 +609,7 @@ fn check_legality_of_move_bindings(
596609
ty::BindByValue(..) => {
597610
let pat_ty = cx.tables.node_type(p.hir_id);
598611
if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) {
599-
check_move(p, sub.as_ref().map(|p| &**p), span_vec);
612+
check_move(cx, p, sub.as_ref().map(|p| &**p), span_vec);
600613
}
601614
}
602615
_ => {}

0 commit comments

Comments
 (0)