@@ -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,26 +132,27 @@ 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 {
155
+ self . signalled_error = SignalledError :: SawSomeError ;
153
156
if !self . tcx . features ( ) . bind_by_move_pattern_guards {
154
157
check_for_mutation_in_guard ( self , & guard) ;
155
158
}
@@ -548,7 +551,7 @@ fn maybe_point_at_variant(
548
551
549
552
// Legality of move bindings checking
550
553
fn check_legality_of_move_bindings(
551
- cx : & MatchVisitor < ' _ , ' _ > ,
554
+ cx : & mut MatchVisitor < ' _ , ' _ > ,
552
555
has_guard : bool ,
553
556
pats : & [ P < Pat > ] ,
554
557
) {
@@ -565,7 +568,12 @@ fn check_legality_of_move_bindings(
565
568
} )
566
569
}
567
570
let span_vec = & mut Vec :: new ( ) ;
568
- let check_move = |p : & Pat , sub : Option < & Pat > , span_vec : & mut Vec < Span > | {
571
+ let check_move = |
572
+ cx : & mut MatchVisitor < ' _ , ' _ > ,
573
+ p : & Pat ,
574
+ sub : Option < & Pat > ,
575
+ span_vec : & mut Vec < Span > ,
576
+ | {
569
577
// check legality of moving out of the enum
570
578
571
579
// x @ Foo(..) is legal, but x @ Foo(y) isn't.
@@ -574,15 +582,17 @@ fn check_legality_of_move_bindings(
574
582
"cannot bind by-move with sub-bindings" )
575
583
. span_label( p. span, "binds an already bound by-move value by moving it" )
576
584
. 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") ;
585
+ } else if has_guard {
586
+ if !cx. tcx. features( ) . bind_by_move_pattern_guards {
587
+ let mut err = struct_span_err!( cx. tcx. sess, p. span, E0008 ,
588
+ "cannot bind by-move into a pattern guard" ) ;
589
+ err. span_label( p. span, "moves value into pattern guard" ) ;
590
+ if cx. tcx. sess. opts. unstable_features. is_nightly_build( ) {
591
+ err. help( "add `#![feature(bind_by_move_pattern_guards)]` to the \
592
+ crate attributes to enable") ;
593
+ }
594
+ err. emit( ) ;
584
595
}
585
- err. emit ( ) ;
586
596
} else if let Some ( _by_ref_span) = by_ref_span {
587
597
span_vec. push( p. span) ;
588
598
}
@@ -596,7 +606,7 @@ fn check_legality_of_move_bindings(
596
606
ty:: BindByValue ( ..) => {
597
607
let pat_ty = cx. tables. node_type( p. hir_id) ;
598
608
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) ;
609
+ check_move( cx , p, sub. as_ref( ) . map( |p| & * * p) , span_vec) ;
600
610
}
601
611
}
602
612
_ => { }
0 commit comments