@@ -8,7 +8,7 @@ use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
8
8
use rustc_hir:: { self as hir, BodyId , Node , HirId } ;
9
9
use rustc_session:: Session ;
10
10
use rustc_session:: config:: CrateType ;
11
- use rustc_middle:: hir:: map as hir_map;
11
+ use rustc_middle:: hir:: { map as hir_map, nested_filter } ;
12
12
use rustc_middle:: ty:: subst:: InternalSubsts ;
13
13
use rustc_middle:: ty:: { FnSig , ParamEnv , PolyFnSig , Ty , TyCtxt , TyKind } ;
14
14
use rustc_errors:: { DiagnosticBuilder , Level } ;
@@ -20,7 +20,7 @@ use rustc_ast::ptr::P;
20
20
use rustc_index:: vec:: IndexVec ;
21
21
use rustc_span:: Span ;
22
22
23
- use crate :: ast_manip:: AstEquiv ;
23
+ use crate :: ast_manip:: { AstEquiv , AstSpanMaps } ;
24
24
use crate :: command:: { GenerationalTyCtxt , TyCtxtGeneration } ;
25
25
use crate :: ast_manip:: util:: { namespace, is_export_attr} ;
26
26
use crate :: { expect, match_or} ;
@@ -55,6 +55,57 @@ impl<'a, 'tcx> RefactorCtxt<'a, 'tcx> {
55
55
}
56
56
}
57
57
58
+ type SpanToHirMap = FxHashMap < Span , HirId > ;
59
+
60
+ struct SpanToHirMapper < ' hir > {
61
+ hir_map : hir_map:: Map < ' hir > ,
62
+ span_to_hir_map : SpanToHirMap ,
63
+ }
64
+
65
+ impl < ' hir > hir:: intravisit:: Visitor < ' hir > for SpanToHirMapper < ' hir > {
66
+ type NestedFilter = nested_filter:: OnlyBodies ;
67
+
68
+ fn nested_visit_map ( & mut self ) -> Self :: Map {
69
+ self . hir_map
70
+ }
71
+
72
+ fn visit_id ( & mut self , id : HirId ) {
73
+ let span = match self . hir_map . find ( id) {
74
+ Some ( Node :: Param ( param) ) => param. span ,
75
+ Some ( Node :: Item ( item) ) => item. span ,
76
+ Some ( Node :: ForeignItem ( foreign_item) ) => foreign_item. span ,
77
+ Some ( Node :: TraitItem ( trait_item) ) => trait_item. span ,
78
+ Some ( Node :: ImplItem ( impl_item) ) => impl_item. span ,
79
+ Some ( Node :: Variant ( variant) ) => variant. span ,
80
+ Some ( Node :: Field ( field) ) => field. span ,
81
+ Some ( Node :: AnonConst ( constant) ) => self . hir_map . body ( constant. body ) . value . span ,
82
+ // TODO: Expr only if not Block
83
+ Some ( Node :: Expr ( expr) ) => expr. span ,
84
+ Some ( Node :: Stmt ( stmt) ) => stmt. span ,
85
+ // Intentionally skip PathSegment to avoid collisions
86
+ // Intentionally skip Ty because we want the actual definitions
87
+ Some ( Node :: TypeBinding ( tb) ) => tb. span ,
88
+ // Intentionally skip TraitRef to avoid collisions
89
+ Some ( Node :: Pat ( pat) ) => pat. span ,
90
+ Some ( Node :: Arm ( arm) ) => arm. span ,
91
+ Some ( Node :: Block ( block) ) => block. span ,
92
+ Some ( Node :: Ctor ( ..) ) => self . hir_map . span_with_body ( self . hir_map . get_parent_node ( id) ) ,
93
+ Some ( Node :: Lifetime ( lifetime) ) => lifetime. span ,
94
+ Some ( Node :: GenericParam ( param) ) => param. span ,
95
+ Some ( Node :: Infer ( i) ) => i. span ,
96
+ Some ( Node :: Local ( local) ) => local. span ,
97
+ Some ( Node :: Crate ( item) ) => item. spans . inner_span ,
98
+ _ => return
99
+ } ;
100
+ if span. is_dummy ( ) {
101
+ return ;
102
+ }
103
+
104
+ let old_id = self . span_to_hir_map . insert ( span, id) ;
105
+ assert ! ( old_id. is_none( ) , "span {span:?} already has id {old_id:?} != {id:?}" ) ;
106
+ }
107
+ }
108
+
58
109
#[ derive( Clone ) ]
59
110
pub struct HirMap < ' hir > {
60
111
map : hir_map:: Map < ' hir > ,
@@ -65,6 +116,9 @@ pub struct HirMap<'hir> {
65
116
66
117
node_id_to_def_id : FxHashMap < NodeId , LocalDefId > ,
67
118
def_id_to_node_id : IndexVec < LocalDefId , NodeId > ,
119
+
120
+ span_to_hir_map : SpanToHirMap ,
121
+ ast_span_maps : AstSpanMaps ,
68
122
}
69
123
70
124
impl < ' hir > HirMap < ' hir > {
@@ -73,8 +127,16 @@ impl<'hir> HirMap<'hir> {
73
127
map : hir_map:: Map < ' hir > ,
74
128
node_id_to_def_id : FxHashMap < NodeId , LocalDefId > ,
75
129
def_id_to_node_id : IndexVec < LocalDefId , NodeId > ,
130
+ ast_span_maps : AstSpanMaps ,
76
131
) -> Self {
77
- Self { map, max_node_id, node_id_to_def_id, def_id_to_node_id }
132
+ let mut mapper = SpanToHirMapper {
133
+ hir_map : map,
134
+ span_to_hir_map : Default :: default ( ) ,
135
+ } ;
136
+ map. visit_all_item_likes_in_crate ( & mut mapper) ;
137
+ let SpanToHirMapper { span_to_hir_map, .. } = mapper;
138
+
139
+ Self { map, max_node_id, node_id_to_def_id, def_id_to_node_id, span_to_hir_map, ast_span_maps }
78
140
}
79
141
}
80
142
@@ -611,9 +673,15 @@ impl<'hir> HirMap<'hir> {
611
673
if id > self . max_node_id {
612
674
None
613
675
} else {
614
- self . node_id_to_def_id . get ( & id) . map ( |ldid| {
615
- self . map . local_def_id_to_hir_id ( * ldid)
616
- } )
676
+ if let Some ( ldid) = self . node_id_to_def_id . get ( & id) {
677
+ return Some ( self . map . local_def_id_to_hir_id ( * ldid) ) ;
678
+ }
679
+
680
+ self
681
+ . ast_span_maps
682
+ . node_id_to_span_map
683
+ . get ( & id)
684
+ . and_then ( |span| self . span_to_hir_map . get ( & span) . copied ( ) )
617
685
}
618
686
}
619
687
@@ -643,6 +711,11 @@ impl<'hir> HirMap<'hir> {
643
711
}
644
712
645
713
pub fn hir_to_node_id ( & self , id : HirId ) -> NodeId {
714
+ let span = self . map . span_with_body ( id) ;
715
+ if let Some ( id) = self . ast_span_maps . span_to_node_id_map . get ( & span) {
716
+ return * id;
717
+ }
718
+
646
719
self
647
720
. map
648
721
. opt_local_def_id ( id)
0 commit comments