@@ -4,6 +4,7 @@ use super::_match::WitnessPreference::*;
4
4
5
5
use super :: { Pattern , PatternContext , PatternError , PatternKind } ;
6
6
7
+ use rustc:: middle:: borrowck:: SignalledError ;
7
8
use rustc:: middle:: expr_use_visitor:: { ConsumeMode , Delegate , ExprUseVisitor } ;
8
9
use rustc:: middle:: expr_use_visitor:: { LoanCause , MutateMode } ;
9
10
use rustc:: middle:: expr_use_visitor as euv;
@@ -26,21 +27,24 @@ use std::slice;
26
27
27
28
use syntax_pos:: { Span , DUMMY_SP , MultiSpan } ;
28
29
29
- pub ( crate ) fn check_match ( tcx : TyCtxt < ' _ > , def_id : DefId ) {
30
+ crate fn check_match ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> SignalledError {
30
31
let body_id = if let Some ( id) = tcx. hir ( ) . as_local_hir_id ( def_id) {
31
32
tcx. hir ( ) . body_owned_by ( id)
32
33
} else {
33
- return ;
34
+ return SignalledError :: NoErrorsSeen ;
34
35
} ;
35
36
36
- MatchVisitor {
37
+ let mut visitor = MatchVisitor {
37
38
tcx,
38
39
body_owner : def_id,
39
40
tables : tcx. body_tables ( body_id) ,
40
41
region_scope_tree : & tcx. region_scope_tree ( def_id) ,
41
42
param_env : tcx. param_env ( def_id) ,
42
43
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
44
48
}
45
49
46
50
fn create_e0004 ( sess : & Session , sp : Span , error_message : String ) -> DiagnosticBuilder < ' _ > {
@@ -54,6 +58,7 @@ struct MatchVisitor<'a, 'tcx> {
54
58
param_env : ty:: ParamEnv < ' tcx > ,
55
59
identity_substs : SubstsRef < ' tcx > ,
56
60
region_scope_tree : & ' a region:: ScopeTree ,
61
+ signalled_error : SignalledError ,
57
62
}
58
63
59
64
impl < ' a , ' tcx > Visitor < ' tcx > for MatchVisitor < ' a , ' tcx > {
@@ -64,11 +69,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> {
64
69
fn visit_expr ( & mut self , ex : & ' tcx hir:: Expr ) {
65
70
intravisit:: walk_expr ( self , ex) ;
66
71
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) ;
72
74
}
73
75
}
74
76
@@ -130,27 +132,29 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
130
132
}
131
133
132
134
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 > ] ) {
134
136
check_legality_of_move_bindings ( self , has_guard, pats) ;
135
137
for pat in pats {
136
138
check_legality_of_bindings_in_at_patterns ( self , pat) ;
137
139
}
138
140
}
139
141
140
142
fn check_match (
141
- & self ,
143
+ & mut self ,
142
144
scrut : & hir:: Expr ,
143
145
arms : & ' tcx [ hir:: Arm ] ,
144
- source : hir:: MatchSource )
145
- {
146
+ source : hir:: MatchSource
147
+ ) {
146
148
for arm in arms {
147
149
// First, check legality of move bindings.
148
150
self . check_patterns ( arm. guard . is_some ( ) , & arm. pats ) ;
149
151
150
152
// Second, if there is a guard on each arm, make sure it isn't
151
153
// assigning or borrowing anything mutably.
152
154
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 {
154
158
check_for_mutation_in_guard ( self , & guard) ;
155
159
}
156
160
}
@@ -548,7 +552,7 @@ fn maybe_point_at_variant(
548
552
549
553
// Legality of move bindings checking
550
554
fn check_legality_of_move_bindings(
551
- cx : & MatchVisitor < ' _ , ' _ > ,
555
+ cx : & mut MatchVisitor < ' _ , ' _ > ,
552
556
has_guard : bool ,
553
557
pats : & [ P < Pat > ] ,
554
558
) {
@@ -565,7 +569,12 @@ fn check_legality_of_move_bindings(
565
569
} )
566
570
}
567
571
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
+ | {
569
578
// check legality of moving out of the enum
570
579
571
580
// x @ Foo(..) is legal, but x @ Foo(y) isn't.
@@ -574,15 +583,19 @@ fn check_legality_of_move_bindings(
574
583
"cannot bind by-move with sub-bindings" )
575
584
. span_label( p. span, "binds an already bound by-move value by moving it" )
576
585
. 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( ) ;
584
598
}
585
- err. emit ( ) ;
586
599
} else if let Some ( _by_ref_span) = by_ref_span {
587
600
span_vec. push( p. span) ;
588
601
}
@@ -596,7 +609,7 @@ fn check_legality_of_move_bindings(
596
609
ty:: BindByValue ( ..) => {
597
610
let pat_ty = cx. tables. node_type( p. hir_id) ;
598
611
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) ;
600
613
}
601
614
}
602
615
_ => { }
0 commit comments