@@ -28,14 +28,15 @@ use std::iter::{range_inclusive, AdditiveIterator, FromIterator, repeat};
2828use std:: num:: Float ;
2929use std:: slice;
3030use syntax:: ast:: { self , DUMMY_NODE_ID , NodeId , Pat } ;
31- use syntax:: ast_util:: walk_pat ;
31+ use syntax:: ast_util;
3232use syntax:: codemap:: { Span , Spanned , DUMMY_SP } ;
3333use syntax:: fold:: { Folder , noop_fold_pat} ;
3434use syntax:: print:: pprust:: pat_to_string;
3535use syntax:: parse:: token;
3636use syntax:: ptr:: P ;
3737use syntax:: visit:: { self , Visitor , FnKind } ;
3838use util:: ppaux:: ty_to_string;
39+ use util:: nodemap:: FnvHashMap ;
3940
4041pub const DUMMY_WILD_PAT : & ' static Pat = & Pat {
4142 id : DUMMY_NODE_ID ,
@@ -171,7 +172,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
171172 }
172173 }
173174
174- let mut static_inliner = StaticInliner :: new ( cx. tcx ) ;
175+ let mut static_inliner = StaticInliner :: new ( cx. tcx , None ) ;
175176 let inlined_arms = arms. iter ( ) . map ( |arm| {
176177 ( arm. pats . iter ( ) . map ( |pat| {
177178 static_inliner. fold_pat ( ( * pat) . clone ( ) )
@@ -235,7 +236,7 @@ fn is_expr_const_nan(tcx: &ty::ctxt, expr: &ast::Expr) -> bool {
235236}
236237
237238fn check_for_bindings_named_the_same_as_variants ( cx : & MatchCheckCtxt , pat : & Pat ) {
238- walk_pat ( pat, |p| {
239+ ast_util :: walk_pat ( pat, |p| {
239240 match p. node {
240241 ast:: PatIdent ( ast:: BindByValue ( ast:: MutImmutable ) , ident, None ) => {
241242 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)
266267
267268// Check that we do not match against a static NaN (#6804)
268269fn check_for_static_nan ( cx : & MatchCheckCtxt , pat : & Pat ) {
269- walk_pat ( pat, |p| {
270+ ast_util :: walk_pat ( pat, |p| {
270271 match p. node {
271272 ast:: PatLit ( ref expr) if is_expr_const_nan ( cx. tcx , & * * expr) => {
272273 span_warn ! ( cx. tcx. sess, p. span, E0003 ,
@@ -399,28 +400,50 @@ fn const_val_to_expr(value: &const_val) -> P<ast::Expr> {
399400
400401pub struct StaticInliner < ' a , ' tcx : ' a > {
401402 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 > > ,
403405}
404406
405407impl < ' 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 > {
407411 StaticInliner {
408412 tcx : tcx,
409- failed : false
413+ failed : false ,
414+ renaming_map : renaming_map
410415 }
411416 }
412417}
413418
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+
414432impl < ' a , ' tcx > Folder for StaticInliner < ' a , ' tcx > {
415433 fn fold_pat ( & mut self , pat : P < Pat > ) -> P < Pat > {
416- match pat. node {
434+ return match pat. node {
417435 ast:: PatIdent ( ..) | ast:: PatEnum ( ..) => {
418436 let def = self . tcx . def_map . borrow ( ) . get ( & pat. id ) . cloned ( ) ;
419437 match def {
420438 Some ( DefConst ( did) ) => match lookup_const_by_id ( self . tcx , did) {
421439 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+
424447 new_pat
425448 } )
426449 }
@@ -435,6 +458,24 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
435458 }
436459 }
437460 _ => 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) ;
438479 }
439480 }
440481}
@@ -953,7 +994,7 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &ast::Local) {
953994 ast:: LocalFor => "`for` loop"
954995 } ;
955996
956- let mut static_inliner = StaticInliner :: new ( cx. tcx ) ;
997+ let mut static_inliner = StaticInliner :: new ( cx. tcx , None ) ;
957998 is_refutable ( cx, & * static_inliner. fold_pat ( loc. pat . clone ( ) ) , |pat| {
958999 span_err ! ( cx. tcx. sess, loc. pat. span, E0005 ,
9591000 "refutable pattern in {} binding: `{}` not covered" ,
@@ -1040,7 +1081,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
10401081 } ;
10411082
10421083 for pat in pats {
1043- walk_pat ( & * * pat, |p| {
1084+ ast_util :: walk_pat ( & * * pat, |p| {
10441085 if pat_is_binding ( def_map, & * p) {
10451086 match p. node {
10461087 ast:: PatIdent ( ast:: BindByValue ( _) , _, ref sub) => {
0 commit comments