@@ -28,14 +28,15 @@ use std::iter::{range_inclusive, AdditiveIterator, FromIterator, repeat};
28
28
use std:: num:: Float ;
29
29
use std:: slice;
30
30
use syntax:: ast:: { self , DUMMY_NODE_ID , NodeId , Pat } ;
31
- use syntax:: ast_util:: walk_pat ;
31
+ use syntax:: ast_util;
32
32
use syntax:: codemap:: { Span , Spanned , DUMMY_SP } ;
33
33
use syntax:: fold:: { Folder , noop_fold_pat} ;
34
34
use syntax:: print:: pprust:: pat_to_string;
35
35
use syntax:: parse:: token;
36
36
use syntax:: ptr:: P ;
37
37
use syntax:: visit:: { self , Visitor , FnKind } ;
38
38
use util:: ppaux:: ty_to_string;
39
+ use util:: nodemap:: FnvHashMap ;
39
40
40
41
pub const DUMMY_WILD_PAT : & ' static Pat = & Pat {
41
42
id : DUMMY_NODE_ID ,
@@ -171,7 +172,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
171
172
}
172
173
}
173
174
174
- let mut static_inliner = StaticInliner :: new ( cx. tcx ) ;
175
+ let mut static_inliner = StaticInliner :: new ( cx. tcx , None ) ;
175
176
let inlined_arms = arms. iter ( ) . map ( |arm| {
176
177
( arm. pats . iter ( ) . map ( |pat| {
177
178
static_inliner. fold_pat ( ( * pat) . clone ( ) )
@@ -235,7 +236,7 @@ fn is_expr_const_nan(tcx: &ty::ctxt, expr: &ast::Expr) -> bool {
235
236
}
236
237
237
238
fn check_for_bindings_named_the_same_as_variants ( cx : & MatchCheckCtxt , pat : & Pat ) {
238
- walk_pat ( pat, |p| {
239
+ ast_util :: walk_pat ( pat, |p| {
239
240
match p. node {
240
241
ast:: PatIdent ( ast:: BindByValue ( ast:: MutImmutable ) , ident, None ) => {
241
242
let pat_ty = ty:: pat_ty ( cx. tcx , p) ;
@@ -266,7 +267,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
266
267
267
268
// Check that we do not match against a static NaN (#6804)
268
269
fn check_for_static_nan ( cx : & MatchCheckCtxt , pat : & Pat ) {
269
- walk_pat ( pat, |p| {
270
+ ast_util :: walk_pat ( pat, |p| {
270
271
match p. node {
271
272
ast:: PatLit ( ref expr) if is_expr_const_nan ( cx. tcx , & * * expr) => {
272
273
span_warn ! ( cx. tcx. sess, p. span, E0003 ,
@@ -399,28 +400,50 @@ fn const_val_to_expr(value: &const_val) -> P<ast::Expr> {
399
400
400
401
pub struct StaticInliner < ' a , ' tcx : ' a > {
401
402
pub tcx : & ' a ty:: ctxt < ' tcx > ,
402
- pub failed : bool
403
+ pub failed : bool ,
404
+ pub renaming_map : Option < & ' a mut FnvHashMap < ( NodeId , Span ) , NodeId > > ,
403
405
}
404
406
405
407
impl < ' a , ' tcx > StaticInliner < ' a , ' tcx > {
406
- pub fn new < ' b > ( tcx : & ' b ty:: ctxt < ' tcx > ) -> StaticInliner < ' b , ' tcx > {
408
+ pub fn new < ' b > ( tcx : & ' b ty:: ctxt < ' tcx > ,
409
+ renaming_map : Option < & ' b mut FnvHashMap < ( NodeId , Span ) , NodeId > > )
410
+ -> StaticInliner < ' b , ' tcx > {
407
411
StaticInliner {
408
412
tcx : tcx,
409
- failed : false
413
+ failed : false ,
414
+ renaming_map : renaming_map
410
415
}
411
416
}
412
417
}
413
418
419
+ struct RenamingRecorder < ' map > {
420
+ substituted_node_id : NodeId ,
421
+ origin_span : Span ,
422
+ renaming_map : & ' map mut FnvHashMap < ( NodeId , Span ) , NodeId >
423
+ }
424
+
425
+ impl < ' map > ast_util:: IdVisitingOperation for RenamingRecorder < ' map > {
426
+ fn visit_id ( & mut self , node_id : NodeId ) {
427
+ let key = ( node_id, self . origin_span ) ;
428
+ self . renaming_map . insert ( key, self . substituted_node_id ) ;
429
+ }
430
+ }
431
+
414
432
impl < ' a , ' tcx > Folder for StaticInliner < ' a , ' tcx > {
415
433
fn fold_pat ( & mut self , pat : P < Pat > ) -> P < Pat > {
416
- match pat. node {
434
+ return match pat. node {
417
435
ast:: PatIdent ( ..) | ast:: PatEnum ( ..) => {
418
436
let def = self . tcx . def_map . borrow ( ) . get ( & pat. id ) . cloned ( ) ;
419
437
match def {
420
438
Some ( DefConst ( did) ) => match lookup_const_by_id ( self . tcx , did) {
421
439
Some ( const_expr) => {
422
- const_expr_to_pat ( self . tcx , const_expr) . map ( |mut new_pat| {
423
- new_pat. span = pat. span ;
440
+ const_expr_to_pat ( self . tcx , const_expr, pat. span ) . map ( |new_pat| {
441
+
442
+ if let Some ( ref mut renaming_map) = self . renaming_map {
443
+ // Record any renamings we do here
444
+ record_renamings ( const_expr, & pat, renaming_map) ;
445
+ }
446
+
424
447
new_pat
425
448
} )
426
449
}
@@ -435,6 +458,24 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
435
458
}
436
459
}
437
460
_ => noop_fold_pat ( pat, self )
461
+ } ;
462
+
463
+ fn record_renamings ( const_expr : & ast:: Expr ,
464
+ substituted_pat : & ast:: Pat ,
465
+ renaming_map : & mut FnvHashMap < ( NodeId , Span ) , NodeId > ) {
466
+ let mut renaming_recorder = RenamingRecorder {
467
+ substituted_node_id : substituted_pat. id ,
468
+ origin_span : substituted_pat. span ,
469
+ renaming_map : renaming_map,
470
+ } ;
471
+
472
+ let mut id_visitor = ast_util:: IdVisitor {
473
+ operation : & mut renaming_recorder,
474
+ pass_through_items : true ,
475
+ visited_outermost : false ,
476
+ } ;
477
+
478
+ id_visitor. visit_expr ( const_expr) ;
438
479
}
439
480
}
440
481
}
@@ -953,7 +994,7 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &ast::Local) {
953
994
ast:: LocalFor => "`for` loop"
954
995
} ;
955
996
956
- let mut static_inliner = StaticInliner :: new ( cx. tcx ) ;
997
+ let mut static_inliner = StaticInliner :: new ( cx. tcx , None ) ;
957
998
is_refutable ( cx, & * static_inliner. fold_pat ( loc. pat . clone ( ) ) , |pat| {
958
999
span_err ! ( cx. tcx. sess, loc. pat. span, E0005 ,
959
1000
"refutable pattern in {} binding: `{}` not covered" ,
@@ -1040,7 +1081,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
1040
1081
} ;
1041
1082
1042
1083
for pat in pats {
1043
- walk_pat ( & * * pat, |p| {
1084
+ ast_util :: walk_pat ( & * * pat, |p| {
1044
1085
if pat_is_binding ( def_map, & * p) {
1045
1086
match p. node {
1046
1087
ast:: PatIdent ( ast:: BindByValue ( _) , _, ref sub) => {
0 commit comments