@@ -4,6 +4,7 @@ use super::_match::WitnessPreference::*;
44
55use super :: { Pattern , PatternContext , PatternError , PatternKind } ;
66
7+ use rustc:: middle:: borrowck:: SignalledError ;
78use rustc:: middle:: expr_use_visitor:: { ConsumeMode , Delegate , ExprUseVisitor } ;
89use rustc:: middle:: expr_use_visitor:: { LoanCause , MutateMode } ;
910use rustc:: middle:: expr_use_visitor as euv;
@@ -26,21 +27,24 @@ use std::slice;
2627
2728use 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
4650fn 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
5964impl < ' 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,26 +132,27 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
130132}
131133
132134impl < ' 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 {
155+ self . signalled_error = SignalledError :: SawSomeError ;
153156 if !self . tcx . features ( ) . bind_by_move_pattern_guards {
154157 check_for_mutation_in_guard ( self , & guard) ;
155158 }
@@ -548,7 +551,7 @@ fn maybe_point_at_variant(
548551
549552// Legality of move bindings checking
550553fn check_legality_of_move_bindings(
551- cx : & MatchVisitor < ' _ , ' _ > ,
554+ cx : & mut MatchVisitor < ' _ , ' _ > ,
552555 has_guard : bool ,
553556 pats : & [ P < Pat > ] ,
554557) {
@@ -565,7 +568,12 @@ fn check_legality_of_move_bindings(
565568 } )
566569 }
567570 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+ | {
569577 // check legality of moving out of the enum
570578
571579 // x @ Foo(..) is legal, but x @ Foo(y) isn't.
@@ -574,15 +582,17 @@ fn check_legality_of_move_bindings(
574582 "cannot bind by-move with sub-bindings" )
575583 . span_label( p. span, "binds an already bound by-move value by moving it" )
576584 . 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( ) ;
584595 }
585- err. emit ( ) ;
586596 } else if let Some ( _by_ref_span) = by_ref_span {
587597 span_vec. push( p. span) ;
588598 }
@@ -596,7 +606,7 @@ fn check_legality_of_move_bindings(
596606 ty:: BindByValue ( ..) => {
597607 let pat_ty = cx. tables. node_type( p. hir_id) ;
598608 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) ;
600610 }
601611 }
602612 _ => { }
0 commit comments