@@ -117,6 +117,7 @@ use std::io::prelude::*;
117117use std:: io;
118118use std:: rc:: Rc ;
119119use syntax:: ast:: { self , NodeId } ;
120+ use syntax:: ptr:: P ;
120121use syntax:: symbol:: keywords;
121122use syntax_pos:: Span ;
122123
@@ -398,72 +399,65 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
398399 lsets. warn_about_unused_args ( body, entry_ln) ;
399400}
400401
401- fn visit_local < ' a , ' tcx > ( ir : & mut IrMaps < ' a , ' tcx > , local : & ' tcx hir:: Local ) {
402- local. pat . each_binding ( |_, p_id, sp, path1| {
403- debug ! ( "adding local variable {}" , p_id) ;
402+ fn add_from_pat < ' a , ' tcx > ( ir : & mut IrMaps < ' a , ' tcx > , pat : & P < hir:: Pat > ) {
403+ // For struct patterns, take note of which fields used shorthand
404+ // (`x` rather than `x: x`).
405+ //
406+ // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be
407+ // phased out in favor of `HirId`s; however, we need to match the signature of
408+ // `each_binding`, which uses `NodeIds`.
409+ let mut shorthand_field_ids = NodeSet ( ) ;
410+ let mut pats = VecDeque :: new ( ) ;
411+ pats. push_back ( pat) ;
412+ while let Some ( pat) = pats. pop_front ( ) {
413+ use hir:: PatKind :: * ;
414+ match pat. node {
415+ Binding ( _, _, _, ref inner_pat) => {
416+ pats. extend ( inner_pat. iter ( ) ) ;
417+ }
418+ Struct ( _, ref fields, _) => {
419+ for field in fields {
420+ if field. node . is_shorthand {
421+ shorthand_field_ids. insert ( field. node . pat . id ) ;
422+ }
423+ }
424+ }
425+ Ref ( ref inner_pat, _) |
426+ Box ( ref inner_pat) => {
427+ pats. push_back ( inner_pat) ;
428+ }
429+ TupleStruct ( _, ref inner_pats, _) |
430+ Tuple ( ref inner_pats, _) => {
431+ pats. extend ( inner_pats. iter ( ) ) ;
432+ }
433+ Slice ( ref pre_pats, ref inner_pat, ref post_pats) => {
434+ pats. extend ( pre_pats. iter ( ) ) ;
435+ pats. extend ( inner_pat. iter ( ) ) ;
436+ pats. extend ( post_pats. iter ( ) ) ;
437+ }
438+ _ => { }
439+ }
440+ }
441+
442+ pat. each_binding ( |_bm, p_id, _sp, path1| {
404443 let name = path1. node ;
405- ir. add_live_node_for_node ( p_id, VarDefNode ( sp ) ) ;
444+ ir. add_live_node_for_node ( p_id, VarDefNode ( path1 . span ) ) ;
406445 ir. add_variable ( Local ( LocalInfo {
407446 id : p_id,
408447 name,
409- is_shorthand : false ,
448+ is_shorthand : shorthand_field_ids . contains ( & p_id )
410449 } ) ) ;
411450 } ) ;
451+ }
452+
453+ fn visit_local < ' a , ' tcx > ( ir : & mut IrMaps < ' a , ' tcx > , local : & ' tcx hir:: Local ) {
454+ add_from_pat ( ir, & local. pat ) ;
412455 intravisit:: walk_local ( ir, local) ;
413456}
414457
415458fn visit_arm < ' a , ' tcx > ( ir : & mut IrMaps < ' a , ' tcx > , arm : & ' tcx hir:: Arm ) {
416- for mut pat in & arm. pats {
417- // For struct patterns, take note of which fields used shorthand
418- // (`x` rather than `x: x`).
419- //
420- // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be
421- // phased out in favor of `HirId`s; however, we need to match the signature of
422- // `each_binding`, which uses `NodeIds`.
423- let mut shorthand_field_ids = NodeSet ( ) ;
424- let mut pats = VecDeque :: new ( ) ;
425- pats. push_back ( pat) ;
426- while let Some ( pat) = pats. pop_front ( ) {
427- use hir:: PatKind :: * ;
428- match pat. node {
429- Binding ( _, _, _, ref inner_pat) => {
430- pats. extend ( inner_pat. iter ( ) ) ;
431- }
432- Struct ( _, ref fields, _) => {
433- for field in fields {
434- if field. node . is_shorthand {
435- shorthand_field_ids. insert ( field. node . pat . id ) ;
436- }
437- }
438- }
439- Ref ( ref inner_pat, _) |
440- Box ( ref inner_pat) => {
441- pats. push_back ( inner_pat) ;
442- }
443- TupleStruct ( _, ref inner_pats, _) |
444- Tuple ( ref inner_pats, _) => {
445- pats. extend ( inner_pats. iter ( ) ) ;
446- }
447- Slice ( ref pre_pats, ref inner_pat, ref post_pats) => {
448- pats. extend ( pre_pats. iter ( ) ) ;
449- pats. extend ( inner_pat. iter ( ) ) ;
450- pats. extend ( post_pats. iter ( ) ) ;
451- }
452- _ => { }
453- }
454- }
455-
456- pat. each_binding ( |bm, p_id, _sp, path1| {
457- debug ! ( "adding local variable {} from match with bm {:?}" ,
458- p_id, bm) ;
459- let name = path1. node ;
460- ir. add_live_node_for_node ( p_id, VarDefNode ( path1. span ) ) ;
461- ir. add_variable ( Local ( LocalInfo {
462- id : p_id,
463- name : name,
464- is_shorthand : shorthand_field_ids. contains ( & p_id)
465- } ) ) ;
466- } )
459+ for pat in & arm. pats {
460+ add_from_pat ( ir, pat) ;
467461 }
468462 intravisit:: walk_arm ( ir, arm) ;
469463}
0 commit comments