62
62
// in the HIR, especially for multiple identifiers.
63
63
64
64
use hir;
65
+ use hir:: map:: Definitions ;
66
+ use hir:: map:: definitions:: DefPathData ;
67
+ use hir:: def_id:: DefIndex ;
65
68
66
69
use std:: collections:: BTreeMap ;
67
70
use std:: collections:: HashMap ;
@@ -92,10 +95,20 @@ pub struct LoweringContext<'a> {
92
95
// A copy of cached_id, but is also set to an id while a node is lowered for
93
96
// the first time.
94
97
gensym_key : Cell < u32 > ,
98
+ // We must keep the set of definitions up to date as we add nodes that
99
+ // weren't in the AST.
100
+ definitions : Option < & ' a RefCell < Definitions > > ,
101
+ // As we walk the AST we must keep track of the current 'parent' def id (in
102
+ // the form of a DefIndex) so that if we create a new node which introduces
103
+ // a definition, then we can properly create the def id.
104
+ parent_def : Cell < Option < DefIndex > > ,
95
105
}
96
106
97
107
impl < ' a , ' hir > LoweringContext < ' a > {
98
- pub fn new ( id_assigner : & ' a NodeIdAssigner , c : Option < & Crate > ) -> LoweringContext < ' a > {
108
+ pub fn new ( id_assigner : & ' a NodeIdAssigner ,
109
+ c : Option < & Crate > ,
110
+ defs : & ' a RefCell < Definitions > )
111
+ -> LoweringContext < ' a > {
99
112
let crate_root = c. and_then ( |c| {
100
113
if std_inject:: no_core ( c) {
101
114
None
@@ -113,6 +126,23 @@ impl<'a, 'hir> LoweringContext<'a> {
113
126
cached_id : Cell :: new ( 0 ) ,
114
127
gensym_cache : RefCell :: new ( HashMap :: new ( ) ) ,
115
128
gensym_key : Cell :: new ( 0 ) ,
129
+ definitions : Some ( defs) ,
130
+ parent_def : Cell :: new ( None ) ,
131
+ }
132
+ }
133
+
134
+ // Only use this when you want a LoweringContext for testing and won't look
135
+ // up def ids for anything created during lowering.
136
+ pub fn testing_context ( id_assigner : & ' a NodeIdAssigner ) -> LoweringContext < ' a > {
137
+ LoweringContext {
138
+ crate_root : None ,
139
+ id_cache : RefCell :: new ( HashMap :: new ( ) ) ,
140
+ id_assigner : id_assigner,
141
+ cached_id : Cell :: new ( 0 ) ,
142
+ gensym_cache : RefCell :: new ( HashMap :: new ( ) ) ,
143
+ gensym_key : Cell :: new ( 0 ) ,
144
+ definitions : None ,
145
+ parent_def : Cell :: new ( None ) ,
116
146
}
117
147
}
118
148
@@ -146,6 +176,25 @@ impl<'a, 'hir> LoweringContext<'a> {
146
176
fn diagnostic ( & self ) -> & Handler {
147
177
self . id_assigner . diagnostic ( )
148
178
}
179
+
180
+ fn with_parent_def < T , F : FnOnce ( ) -> T > ( & self , parent_id : NodeId , f : F ) -> T {
181
+ if self . definitions . is_none ( ) {
182
+ // This should only be used for testing.
183
+ return f ( ) ;
184
+ }
185
+
186
+ let old_def = self . parent_def . get ( ) ;
187
+ self . parent_def . set ( Some ( self . get_def ( parent_id) ) ) ;
188
+ let result = f ( ) ;
189
+ self . parent_def . set ( old_def) ;
190
+
191
+ result
192
+ }
193
+
194
+ fn get_def ( & self , id : NodeId ) -> DefIndex {
195
+ let defs = self . definitions . unwrap ( ) . borrow ( ) ;
196
+ defs. opt_def_index ( id) . unwrap ( )
197
+ }
149
198
}
150
199
151
200
// Utility fn for setting and unsetting the cached id.
@@ -733,47 +782,51 @@ pub fn lower_item_kind(lctx: &LoweringContext, i: &ItemKind) -> hir::Item_ {
733
782
}
734
783
735
784
pub fn lower_trait_item ( lctx : & LoweringContext , i : & TraitItem ) -> hir:: TraitItem {
736
- hir:: TraitItem {
737
- id : i. id ,
738
- name : i. ident . name ,
739
- attrs : lower_attrs ( lctx, & i. attrs ) ,
740
- node : match i. node {
741
- TraitItemKind :: Const ( ref ty, ref default) => {
742
- hir:: ConstTraitItem ( lower_ty ( lctx, ty) ,
743
- default. as_ref ( ) . map ( |x| lower_expr ( lctx, x) ) )
744
- }
745
- TraitItemKind :: Method ( ref sig, ref body) => {
746
- hir:: MethodTraitItem ( lower_method_sig ( lctx, sig) ,
747
- body. as_ref ( ) . map ( |x| lower_block ( lctx, x) ) )
748
- }
749
- TraitItemKind :: Type ( ref bounds, ref default) => {
750
- hir:: TypeTraitItem ( lower_bounds ( lctx, bounds) ,
751
- default. as_ref ( ) . map ( |x| lower_ty ( lctx, x) ) )
752
- }
753
- } ,
754
- span : i. span ,
755
- }
785
+ lctx. with_parent_def ( i. id , || {
786
+ hir:: TraitItem {
787
+ id : i. id ,
788
+ name : i. ident . name ,
789
+ attrs : lower_attrs ( lctx, & i. attrs ) ,
790
+ node : match i. node {
791
+ TraitItemKind :: Const ( ref ty, ref default) => {
792
+ hir:: ConstTraitItem ( lower_ty ( lctx, ty) ,
793
+ default. as_ref ( ) . map ( |x| lower_expr ( lctx, x) ) )
794
+ }
795
+ TraitItemKind :: Method ( ref sig, ref body) => {
796
+ hir:: MethodTraitItem ( lower_method_sig ( lctx, sig) ,
797
+ body. as_ref ( ) . map ( |x| lower_block ( lctx, x) ) )
798
+ }
799
+ TraitItemKind :: Type ( ref bounds, ref default) => {
800
+ hir:: TypeTraitItem ( lower_bounds ( lctx, bounds) ,
801
+ default. as_ref ( ) . map ( |x| lower_ty ( lctx, x) ) )
802
+ }
803
+ } ,
804
+ span : i. span ,
805
+ }
806
+ } )
756
807
}
757
808
758
809
pub fn lower_impl_item ( lctx : & LoweringContext , i : & ImplItem ) -> hir:: ImplItem {
759
- hir:: ImplItem {
760
- id : i. id ,
761
- name : i. ident . name ,
762
- attrs : lower_attrs ( lctx, & i. attrs ) ,
763
- vis : lower_visibility ( lctx, & i. vis ) ,
764
- defaultness : lower_defaultness ( lctx, i. defaultness ) ,
765
- node : match i. node {
766
- ImplItemKind :: Const ( ref ty, ref expr) => {
767
- hir:: ImplItemKind :: Const ( lower_ty ( lctx, ty) , lower_expr ( lctx, expr) )
768
- }
769
- ImplItemKind :: Method ( ref sig, ref body) => {
770
- hir:: ImplItemKind :: Method ( lower_method_sig ( lctx, sig) , lower_block ( lctx, body) )
771
- }
772
- ImplItemKind :: Type ( ref ty) => hir:: ImplItemKind :: Type ( lower_ty ( lctx, ty) ) ,
773
- ImplItemKind :: Macro ( ..) => panic ! ( "Shouldn't exist any more" ) ,
774
- } ,
775
- span : i. span ,
776
- }
810
+ lctx. with_parent_def ( i. id , || {
811
+ hir:: ImplItem {
812
+ id : i. id ,
813
+ name : i. ident . name ,
814
+ attrs : lower_attrs ( lctx, & i. attrs ) ,
815
+ vis : lower_visibility ( lctx, & i. vis ) ,
816
+ defaultness : lower_defaultness ( lctx, i. defaultness ) ,
817
+ node : match i. node {
818
+ ImplItemKind :: Const ( ref ty, ref expr) => {
819
+ hir:: ImplItemKind :: Const ( lower_ty ( lctx, ty) , lower_expr ( lctx, expr) )
820
+ }
821
+ ImplItemKind :: Method ( ref sig, ref body) => {
822
+ hir:: ImplItemKind :: Method ( lower_method_sig ( lctx, sig) , lower_block ( lctx, body) )
823
+ }
824
+ ImplItemKind :: Type ( ref ty) => hir:: ImplItemKind :: Type ( lower_ty ( lctx, ty) ) ,
825
+ ImplItemKind :: Macro ( ..) => panic ! ( "Shouldn't exist any more" ) ,
826
+ } ,
827
+ span : i. span ,
828
+ }
829
+ } )
777
830
}
778
831
779
832
pub fn lower_mod ( lctx : & LoweringContext , m : & Mod ) -> hir:: Mod {
@@ -831,7 +884,9 @@ pub fn lower_item_id(_lctx: &LoweringContext, i: &Item) -> hir::ItemId {
831
884
}
832
885
833
886
pub fn lower_item ( lctx : & LoweringContext , i : & Item ) -> hir:: Item {
834
- let node = lower_item_kind ( lctx, & i. node ) ;
887
+ let node = lctx. with_parent_def ( i. id , || {
888
+ lower_item_kind ( lctx, & i. node )
889
+ } ) ;
835
890
836
891
hir:: Item {
837
892
id : i. id ,
@@ -844,21 +899,23 @@ pub fn lower_item(lctx: &LoweringContext, i: &Item) -> hir::Item {
844
899
}
845
900
846
901
pub fn lower_foreign_item ( lctx : & LoweringContext , i : & ForeignItem ) -> hir:: ForeignItem {
847
- hir:: ForeignItem {
848
- id : i. id ,
849
- name : i. ident . name ,
850
- attrs : lower_attrs ( lctx, & i. attrs ) ,
851
- node : match i. node {
852
- ForeignItemKind :: Fn ( ref fdec, ref generics) => {
853
- hir:: ForeignItemFn ( lower_fn_decl ( lctx, fdec) , lower_generics ( lctx, generics) )
854
- }
855
- ForeignItemKind :: Static ( ref t, m) => {
856
- hir:: ForeignItemStatic ( lower_ty ( lctx, t) , m)
857
- }
858
- } ,
859
- vis : lower_visibility ( lctx, & i. vis ) ,
860
- span : i. span ,
861
- }
902
+ lctx. with_parent_def ( i. id , || {
903
+ hir:: ForeignItem {
904
+ id : i. id ,
905
+ name : i. ident . name ,
906
+ attrs : lower_attrs ( lctx, & i. attrs ) ,
907
+ node : match i. node {
908
+ ForeignItemKind :: Fn ( ref fdec, ref generics) => {
909
+ hir:: ForeignItemFn ( lower_fn_decl ( lctx, fdec) , lower_generics ( lctx, generics) )
910
+ }
911
+ ForeignItemKind :: Static ( ref t, m) => {
912
+ hir:: ForeignItemStatic ( lower_ty ( lctx, t) , m)
913
+ }
914
+ } ,
915
+ vis : lower_visibility ( lctx, & i. vis ) ,
916
+ span : i. span ,
917
+ }
918
+ } )
862
919
}
863
920
864
921
pub fn lower_method_sig ( lctx : & LoweringContext , sig : & MethodSig ) -> hir:: MethodSig {
@@ -926,9 +983,11 @@ pub fn lower_pat(lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
926
983
node : match p. node {
927
984
PatKind :: Wild => hir:: PatKind :: Wild ,
928
985
PatKind :: Ident ( ref binding_mode, pth1, ref sub) => {
929
- hir:: PatKind :: Ident ( lower_binding_mode ( lctx, binding_mode) ,
930
- respan ( pth1. span , lower_ident ( lctx, pth1. node ) ) ,
931
- sub. as_ref ( ) . map ( |x| lower_pat ( lctx, x) ) )
986
+ lctx. with_parent_def ( p. id , || {
987
+ hir:: PatKind :: Ident ( lower_binding_mode ( lctx, binding_mode) ,
988
+ respan ( pth1. span , lower_ident ( lctx, pth1. node ) ) ,
989
+ sub. as_ref ( ) . map ( |x| lower_pat ( lctx, x) ) )
990
+ } )
932
991
}
933
992
PatKind :: Lit ( ref e) => hir:: PatKind :: Lit ( lower_expr ( lctx, e) ) ,
934
993
PatKind :: TupleStruct ( ref pth, ref pats) => {
@@ -1202,9 +1261,11 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
1202
1261
hir:: MatchSource :: Normal )
1203
1262
}
1204
1263
ExprKind :: Closure ( capture_clause, ref decl, ref body) => {
1205
- hir:: ExprClosure ( lower_capture_clause ( lctx, capture_clause) ,
1206
- lower_fn_decl ( lctx, decl) ,
1207
- lower_block ( lctx, body) )
1264
+ lctx. with_parent_def ( e. id , || {
1265
+ hir:: ExprClosure ( lower_capture_clause ( lctx, capture_clause) ,
1266
+ lower_fn_decl ( lctx, decl) ,
1267
+ lower_block ( lctx, body) )
1268
+ } )
1208
1269
}
1209
1270
ExprKind :: Block ( ref blk) => hir:: ExprBlock ( lower_block ( lctx, blk) ) ,
1210
1271
ExprKind :: Assign ( ref el, ref er) => {
@@ -1602,7 +1663,12 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
1602
1663
// `{ let _result = ...; _result }`
1603
1664
// underscore prevents an unused_variables lint if the head diverges
1604
1665
let result_ident = lctx. str_to_ident ( "_result" ) ;
1605
- let let_stmt = stmt_let ( lctx, e. span , false , result_ident, match_expr, None ) ;
1666
+ let let_stmt = stmt_let ( lctx,
1667
+ e. span ,
1668
+ false ,
1669
+ result_ident,
1670
+ match_expr,
1671
+ None ) ;
1606
1672
let result = expr_ident ( lctx, e. span , result_ident, None ) ;
1607
1673
let block = block_all ( lctx, e. span , hir_vec ! [ let_stmt] , Some ( result) ) ;
1608
1674
// add the attributes to the outer returned expr node
@@ -1655,7 +1721,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
1655
1721
let err_ctor = expr_path ( lctx, path, None ) ;
1656
1722
expr_call ( lctx, e. span , err_ctor, hir_vec ! [ from_expr] , None )
1657
1723
} ;
1658
- let err_pat = pat_err ( lctx, e. span , pat_ident ( lctx, e. span , err_ident) ) ;
1724
+ let err_pat = pat_err ( lctx, e. span ,
1725
+ pat_ident ( lctx, e. span , err_ident) ) ;
1659
1726
let ret_expr = expr ( lctx, e. span ,
1660
1727
hir:: Expr_ :: ExprRet ( Some ( err_expr) ) , None ) ;
1661
1728
@@ -1938,12 +2005,22 @@ fn pat_ident_binding_mode(lctx: &LoweringContext,
1938
2005
bm : hir:: BindingMode )
1939
2006
-> P < hir:: Pat > {
1940
2007
let pat_ident = hir:: PatKind :: Ident ( bm,
1941
- Spanned {
1942
- span : span,
1943
- node : ident,
1944
- } ,
1945
- None ) ;
1946
- pat ( lctx, span, pat_ident)
2008
+ Spanned {
2009
+ span : span,
2010
+ node : ident,
2011
+ } ,
2012
+ None ) ;
2013
+
2014
+ let pat = pat ( lctx, span, pat_ident) ;
2015
+
2016
+ if let Some ( defs) = lctx. definitions {
2017
+ let mut defs = defs. borrow_mut ( ) ;
2018
+ defs. create_def_with_parent ( lctx. parent_def . get ( ) ,
2019
+ pat. id ,
2020
+ DefPathData :: Binding ( ident. name ) ) ;
2021
+ }
2022
+
2023
+ pat
1947
2024
}
1948
2025
1949
2026
fn pat_wild ( lctx : & LoweringContext , span : Span ) -> P < hir:: Pat > {
@@ -2130,7 +2207,8 @@ mod test {
2130
2207
let ast_in = quote_expr ! ( & cx, in HEAP { foo( ) } ) ;
2131
2208
let ast_in = assigner. fold_expr ( ast_in) ;
2132
2209
2133
- let lctx = LoweringContext :: new ( & assigner, None ) ;
2210
+ let lctx = LoweringContext :: testing_context ( & assigner) ;
2211
+
2134
2212
let hir1 = lower_expr ( & lctx, & ast_if_let) ;
2135
2213
let hir2 = lower_expr ( & lctx, & ast_if_let) ;
2136
2214
assert ! ( hir1 == hir2) ;
0 commit comments