6262// in the HIR, especially for multiple identifiers.
6363
6464use hir;
65+ use hir:: map:: Definitions ;
66+ use hir:: map:: definitions:: DefPathData ;
67+ use hir:: def_id:: DefIndex ;
6568
6669use std:: collections:: BTreeMap ;
6770use std:: collections:: HashMap ;
@@ -92,10 +95,20 @@ pub struct LoweringContext<'a> {
9295 // A copy of cached_id, but is also set to an id while a node is lowered for
9396 // the first time.
9497 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 > > ,
95105}
96106
97107impl < ' 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 > {
99112 let crate_root = c. and_then ( |c| {
100113 if std_inject:: no_core ( c) {
101114 None
@@ -113,6 +126,23 @@ impl<'a, 'hir> LoweringContext<'a> {
113126 cached_id : Cell :: new ( 0 ) ,
114127 gensym_cache : RefCell :: new ( HashMap :: new ( ) ) ,
115128 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 ) ,
116146 }
117147 }
118148
@@ -146,6 +176,25 @@ impl<'a, 'hir> LoweringContext<'a> {
146176 fn diagnostic ( & self ) -> & Handler {
147177 self . id_assigner . diagnostic ( )
148178 }
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+ }
149198}
150199
151200// Utility fn for setting and unsetting the cached id.
@@ -733,47 +782,51 @@ pub fn lower_item_kind(lctx: &LoweringContext, i: &ItemKind) -> hir::Item_ {
733782}
734783
735784pub 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+ } )
756807}
757808
758809pub 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+ } )
777830}
778831
779832pub fn lower_mod ( lctx : & LoweringContext , m : & Mod ) -> hir:: Mod {
@@ -831,7 +884,9 @@ pub fn lower_item_id(_lctx: &LoweringContext, i: &Item) -> hir::ItemId {
831884}
832885
833886pub 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+ } ) ;
835890
836891 hir:: Item {
837892 id : i. id ,
@@ -844,21 +899,23 @@ pub fn lower_item(lctx: &LoweringContext, i: &Item) -> hir::Item {
844899}
845900
846901pub 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+ } )
862919}
863920
864921pub 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> {
926983 node : match p. node {
927984 PatKind :: Wild => hir:: PatKind :: Wild ,
928985 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+ } )
932991 }
933992 PatKind :: Lit ( ref e) => hir:: PatKind :: Lit ( lower_expr ( lctx, e) ) ,
934993 PatKind :: TupleStruct ( ref pth, ref pats) => {
@@ -1202,9 +1261,11 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
12021261 hir:: MatchSource :: Normal )
12031262 }
12041263 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+ } )
12081269 }
12091270 ExprKind :: Block ( ref blk) => hir:: ExprBlock ( lower_block ( lctx, blk) ) ,
12101271 ExprKind :: Assign ( ref el, ref er) => {
@@ -1602,7 +1663,12 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
16021663 // `{ let _result = ...; _result }`
16031664 // underscore prevents an unused_variables lint if the head diverges
16041665 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 ) ;
16061672 let result = expr_ident ( lctx, e. span , result_ident, None ) ;
16071673 let block = block_all ( lctx, e. span , hir_vec ! [ let_stmt] , Some ( result) ) ;
16081674 // add the attributes to the outer returned expr node
@@ -1655,7 +1721,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
16551721 let err_ctor = expr_path ( lctx, path, None ) ;
16561722 expr_call ( lctx, e. span , err_ctor, hir_vec ! [ from_expr] , None )
16571723 } ;
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) ) ;
16591726 let ret_expr = expr ( lctx, e. span ,
16601727 hir:: Expr_ :: ExprRet ( Some ( err_expr) ) , None ) ;
16611728
@@ -1938,12 +2005,22 @@ fn pat_ident_binding_mode(lctx: &LoweringContext,
19382005 bm : hir:: BindingMode )
19392006 -> P < hir:: Pat > {
19402007 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
19472024}
19482025
19492026fn pat_wild ( lctx : & LoweringContext , span : Span ) -> P < hir:: Pat > {
@@ -2130,7 +2207,8 @@ mod test {
21302207 let ast_in = quote_expr ! ( & cx, in HEAP { foo( ) } ) ;
21312208 let ast_in = assigner. fold_expr ( ast_in) ;
21322209
2133- let lctx = LoweringContext :: new ( & assigner, None ) ;
2210+ let lctx = LoweringContext :: testing_context ( & assigner) ;
2211+
21342212 let hir1 = lower_expr ( & lctx, & ast_if_let) ;
21352213 let hir2 = lower_expr ( & lctx, & ast_if_let) ;
21362214 assert ! ( hir1 == hir2) ;
0 commit comments