11use super :: { AnonymousLifetimeMode , LoweringContext , ParamMode } ;
2- use super :: { ImplTraitContext , ImplTraitPosition } ;
2+ use super :: { AstOwner , ImplTraitContext , ImplTraitPosition , ResolverAstLowering } ;
33use crate :: { Arena , FnDeclKind } ;
44
55use rustc_ast:: ptr:: P ;
6- use rustc_ast:: visit:: { self , AssocCtxt , FnCtxt , FnKind , Visitor } ;
6+ use rustc_ast:: visit:: AssocCtxt ;
77use rustc_ast:: * ;
8- use rustc_data_structures:: fx:: FxHashSet ;
8+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
9+ use rustc_data_structures:: sorted_map:: SortedMap ;
910use rustc_errors:: struct_span_err;
1011use rustc_hir as hir;
1112use rustc_hir:: def:: { DefKind , Res } ;
12- use rustc_hir:: def_id:: LocalDefId ;
13- use rustc_index:: vec:: Idx ;
13+ use rustc_hir:: def_id:: { LocalDefId , CRATE_DEF_ID } ;
14+ use rustc_index:: vec:: { Idx , IndexVec } ;
15+ use rustc_session:: utils:: NtToTokenstream ;
16+ use rustc_session:: Session ;
1417use rustc_span:: source_map:: { respan, DesugaringKind } ;
1518use rustc_span:: symbol:: { kw, sym, Ident } ;
1619use rustc_span:: Span ;
@@ -19,10 +22,14 @@ use smallvec::{smallvec, SmallVec};
1922use tracing:: debug;
2023
2124use std:: iter;
22- use std:: mem;
2325
24- pub ( super ) struct ItemLowerer < ' a , ' lowering , ' hir > {
25- pub ( super ) lctx : & ' a mut LoweringContext < ' lowering , ' hir > ,
26+ pub ( super ) struct ItemLowerer < ' a , ' hir > {
27+ pub ( super ) sess : & ' a Session ,
28+ pub ( super ) resolver : & ' a mut dyn ResolverAstLowering ,
29+ pub ( super ) nt_to_tokenstream : NtToTokenstream ,
30+ pub ( super ) arena : & ' hir Arena < ' hir > ,
31+ pub ( super ) ast_index : & ' a IndexVec < LocalDefId , AstOwner < ' a > > ,
32+ pub ( super ) owners : & ' a mut IndexVec < LocalDefId , hir:: MaybeOwner < & ' hir hir:: OwnerInfo < ' hir > > > ,
2633}
2734
2835/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span
@@ -45,130 +52,140 @@ fn add_ty_alias_where_clause(
4552 }
4653}
4754
48- impl ItemLowerer < ' _ , ' _ , ' _ > {
49- fn with_trait_impl_ref < T > (
55+ impl < ' a , ' hir > ItemLowerer < ' a , ' hir > {
56+ fn with_lctx (
5057 & mut self ,
51- impl_ref : & Option < TraitRef > ,
52- f : impl FnOnce ( & mut Self ) -> T ,
53- ) -> T {
54- let old = self . lctx . is_in_trait_impl ;
55- self . lctx . is_in_trait_impl = impl_ref. is_some ( ) ;
56- let ret = f ( self ) ;
57- self . lctx . is_in_trait_impl = old;
58- ret
59- }
60- }
61-
62- impl < ' a > Visitor < ' a > for ItemLowerer < ' a , ' _ , ' _ > {
63- fn visit_attribute ( & mut self , _: & ' a Attribute ) {
64- // We do not want to lower expressions that appear in attributes,
65- // as they are not accessible to the rest of the HIR.
66- }
58+ owner : NodeId ,
59+ f : impl FnOnce ( & mut LoweringContext < ' _ , ' hir > ) -> hir:: OwnerNode < ' hir > ,
60+ ) {
61+ let mut lctx = LoweringContext {
62+ // Pseudo-globals.
63+ sess : & self . sess ,
64+ resolver : self . resolver ,
65+ nt_to_tokenstream : self . nt_to_tokenstream ,
66+ arena : self . arena ,
67+
68+ // HirId handling.
69+ bodies : Vec :: new ( ) ,
70+ attrs : SortedMap :: default ( ) ,
71+ children : FxHashMap :: default ( ) ,
72+ current_hir_id_owner : CRATE_DEF_ID ,
73+ item_local_id_counter : hir:: ItemLocalId :: new ( 0 ) ,
74+ node_id_to_local_id : Default :: default ( ) ,
75+ local_id_to_def_id : SortedMap :: new ( ) ,
76+ trait_map : Default :: default ( ) ,
77+
78+ // Lowering state.
79+ catch_scope : None ,
80+ loop_scope : None ,
81+ is_in_loop_condition : false ,
82+ is_in_trait_impl : false ,
83+ is_in_dyn_type : false ,
84+ anonymous_lifetime_mode : AnonymousLifetimeMode :: PassThrough ,
85+ generator_kind : None ,
86+ task_context : None ,
87+ current_item : None ,
88+ lifetimes_to_define : Vec :: new ( ) ,
89+ is_collecting_anonymous_lifetimes : None ,
90+ in_scope_lifetimes : Vec :: new ( ) ,
91+ allow_try_trait : Some ( [ sym:: try_trait_v2] [ ..] . into ( ) ) ,
92+ allow_gen_future : Some ( [ sym:: gen_future] [ ..] . into ( ) ) ,
93+ allow_into_future : Some ( [ sym:: into_future] [ ..] . into ( ) ) ,
94+ } ;
95+ lctx. with_hir_id_owner ( owner, |lctx| f ( lctx) ) ;
6796
68- fn visit_item ( & mut self , item : & ' a Item ) {
69- let hir_id = self . lctx . with_hir_id_owner ( item. id , |lctx| {
70- let node = lctx. without_in_scope_lifetime_defs ( |lctx| lctx. lower_item ( item) ) ;
71- hir:: OwnerNode :: Item ( node)
72- } ) ;
73-
74- self . lctx . with_parent_item_lifetime_defs ( hir_id, |this| {
75- let this = & mut ItemLowerer { lctx : this } ;
76- match item. kind {
77- ItemKind :: Impl ( box Impl { ref of_trait, .. } ) => {
78- this. with_trait_impl_ref ( of_trait, |this| visit:: walk_item ( this, item) ) ;
79- }
80- _ => visit:: walk_item ( this, item) ,
81- }
82- } ) ;
97+ for ( def_id, info) in lctx. children {
98+ self . owners . ensure_contains_elem ( def_id, || hir:: MaybeOwner :: Phantom ) ;
99+ debug_assert ! ( matches!( self . owners[ def_id] , hir:: MaybeOwner :: Phantom ) ) ;
100+ self . owners [ def_id] = info;
101+ }
83102 }
84103
85- fn visit_fn ( & mut self , fk : FnKind < ' a > , sp : Span , _: NodeId ) {
86- match fk {
87- FnKind :: Fn ( FnCtxt :: Foreign , _, sig, _, _) => {
88- self . visit_fn_header ( & sig. header ) ;
89- visit:: walk_fn_decl ( self , & sig. decl ) ;
90- // Don't visit the foreign function body even if it has one, since lowering the
91- // body would have no meaning and will have already been caught as a parse error.
104+ pub ( super ) fn lower_node (
105+ & mut self ,
106+ def_id : LocalDefId ,
107+ ) -> hir:: MaybeOwner < & ' hir hir:: OwnerInfo < ' hir > > {
108+ self . owners . ensure_contains_elem ( def_id, || hir:: MaybeOwner :: Phantom ) ;
109+ if let hir:: MaybeOwner :: Phantom = self . owners [ def_id] {
110+ let node = self . ast_index [ def_id] ;
111+ match node {
112+ AstOwner :: NonOwner => { }
113+ AstOwner :: Crate ( c) => self . lower_crate ( c) ,
114+ AstOwner :: Item ( item) => self . lower_item ( item) ,
115+ AstOwner :: AssocItem ( item, ctxt) => self . lower_assoc_item ( item, ctxt) ,
116+ AstOwner :: ForeignItem ( item) => self . lower_foreign_item ( item) ,
92117 }
93- _ => visit:: walk_fn ( self , fk, sp) ,
94118 }
95- }
96-
97- fn visit_assoc_item ( & mut self , item : & ' a AssocItem , ctxt : AssocCtxt ) {
98- debug ! ( in_scope_lifetimes = ?self . lctx. in_scope_lifetimes) ;
99- self . lctx . with_hir_id_owner ( item. id , |lctx| match ctxt {
100- AssocCtxt :: Trait => hir:: OwnerNode :: TraitItem ( lctx. lower_trait_item ( item) ) ,
101- AssocCtxt :: Impl => hir:: OwnerNode :: ImplItem ( lctx. lower_impl_item ( item) ) ,
102- } ) ;
103119
104- visit :: walk_assoc_item ( self , item , ctxt ) ;
120+ self . owners [ def_id ]
105121 }
106122
107- fn visit_foreign_item ( & mut self , item : & ' a ForeignItem ) {
108- self . lctx . with_hir_id_owner ( item. id , |lctx| {
109- hir:: OwnerNode :: ForeignItem ( lctx. lower_foreign_item ( item) )
110- } ) ;
123+ fn lower_crate ( & mut self , c : & Crate ) {
124+ debug_assert_eq ! ( self . resolver. local_def_id( CRATE_NODE_ID ) , CRATE_DEF_ID ) ;
111125
112- visit:: walk_foreign_item ( self , item) ;
126+ self . with_lctx ( CRATE_NODE_ID , |lctx| {
127+ let module = lctx. lower_mod ( & c. items , c. spans . inner_span ) ;
128+ lctx. lower_attrs ( hir:: CRATE_HIR_ID , & c. attrs ) ;
129+ hir:: OwnerNode :: Crate ( lctx. arena . alloc ( module) )
130+ } )
113131 }
114- }
115132
116- impl < ' hir > LoweringContext < ' _ , ' hir > {
117- // Same as the method above, but accepts `hir::GenericParam`s
118- // instead of `ast::GenericParam`s.
119- // This should only be used with generics that have already had their
120- // in-band lifetimes added. In practice, this means that this function is
121- // only used when lowering a child item of a trait or impl.
122- #[ tracing:: instrument( level = "debug" , skip( self , f) ) ]
123- fn with_parent_item_lifetime_defs < T > (
124- & mut self ,
125- parent_hir_id : LocalDefId ,
126- f : impl FnOnce ( & mut Self ) -> T ,
127- ) -> T {
128- let parent_generics = match self . owners [ parent_hir_id] . unwrap ( ) . node ( ) . expect_item ( ) . kind {
129- hir:: ItemKind :: Impl ( hir:: Impl { ref generics, .. } )
130- | hir:: ItemKind :: Trait ( _, _, ref generics, ..) => generics. params ,
131- _ => & [ ] ,
132- } ;
133- let lt_def_names = parent_generics
134- . iter ( )
135- . filter_map ( |param| match param. kind {
136- hir:: GenericParamKind :: Lifetime { .. } => {
137- Some ( param. name . normalize_to_macros_2_0 ( ) )
138- }
139- _ => None ,
140- } )
141- . collect ( ) ;
142- let old_in_scope_lifetimes = mem:: replace ( & mut self . in_scope_lifetimes , lt_def_names) ;
143- debug ! ( in_scope_lifetimes = ?self . in_scope_lifetimes) ;
144-
145- let res = f ( self ) ;
146-
147- self . in_scope_lifetimes = old_in_scope_lifetimes;
148- res
133+ fn lower_item ( & mut self , item : & Item ) {
134+ self . with_lctx ( item. id , |lctx| hir:: OwnerNode :: Item ( lctx. lower_item ( item) ) )
149135 }
150136
151- // Clears (and restores) the `in_scope_lifetimes` field. Used when
152- // visiting nested items, which never inherit in-scope lifetimes
153- // from their surrounding environment.
154- #[ tracing:: instrument( level = "debug" , skip( self , f) ) ]
155- fn without_in_scope_lifetime_defs < T > ( & mut self , f : impl FnOnce ( & mut Self ) -> T ) -> T {
156- let old_in_scope_lifetimes = mem:: replace ( & mut self . in_scope_lifetimes , vec ! [ ] ) ;
157- debug ! ( ?old_in_scope_lifetimes) ;
137+ fn lower_assoc_item ( & mut self , item : & AssocItem , ctxt : AssocCtxt ) {
138+ let def_id = self . resolver . local_def_id ( item. id ) ;
158139
159- // this vector is only used when walking over impl headers,
160- // input types, and the like, and should not be non-empty in
161- // between items
162- assert ! ( self . lifetimes_to_define. is_empty( ) ) ;
140+ let parent_id = {
141+ let parent = self . resolver . definitions ( ) . def_key ( def_id) . parent ;
142+ let local_def_index = parent. unwrap ( ) ;
143+ LocalDefId { local_def_index }
144+ } ;
163145
164- let res = f ( self ) ;
146+ let parent_hir = self . lower_node ( parent_id) . unwrap ( ) . node ( ) . expect_item ( ) ;
147+ self . with_lctx ( item. id , |lctx| {
148+ // Evaluate with the lifetimes in `params` in-scope.
149+ // This is used to track which lifetimes have already been defined,
150+ // and which need to be replicated when lowering an async fn.
151+ match parent_hir. kind {
152+ hir:: ItemKind :: Impl ( hir:: Impl { ref of_trait, ref generics, .. } ) => {
153+ lctx. is_in_trait_impl = of_trait. is_some ( ) ;
154+ lctx. in_scope_lifetimes = generics
155+ . params
156+ . iter ( )
157+ . filter ( |param| {
158+ matches ! ( param. kind, hir:: GenericParamKind :: Lifetime { .. } )
159+ } )
160+ . map ( |param| param. name )
161+ . collect ( ) ;
162+ }
163+ hir:: ItemKind :: Trait ( _, _, ref generics, ..) => {
164+ lctx. in_scope_lifetimes = generics
165+ . params
166+ . iter ( )
167+ . filter ( |param| {
168+ matches ! ( param. kind, hir:: GenericParamKind :: Lifetime { .. } )
169+ } )
170+ . map ( |param| param. name )
171+ . collect ( ) ;
172+ }
173+ _ => { }
174+ } ;
165175
166- assert ! ( self . in_scope_lifetimes. is_empty( ) ) ;
167- self . in_scope_lifetimes = old_in_scope_lifetimes;
176+ match ctxt {
177+ AssocCtxt :: Trait => hir:: OwnerNode :: TraitItem ( lctx. lower_trait_item ( item) ) ,
178+ AssocCtxt :: Impl => hir:: OwnerNode :: ImplItem ( lctx. lower_impl_item ( item) ) ,
179+ }
180+ } )
181+ }
168182
169- res
183+ fn lower_foreign_item ( & mut self , item : & ForeignItem ) {
184+ self . with_lctx ( item. id , |lctx| hir:: OwnerNode :: ForeignItem ( lctx. lower_foreign_item ( item) ) )
170185 }
186+ }
171187
188+ impl < ' hir > LoweringContext < ' _ , ' hir > {
172189 pub ( super ) fn lower_mod ( & mut self , items : & [ P < Item > ] , inner : Span ) -> hir:: Mod < ' hir > {
173190 hir:: Mod {
174191 inner : self . lower_span ( inner) ,
@@ -548,12 +565,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
548565 let new_id = self . resolver . local_def_id ( new_node_id) ;
549566 let Some ( res) = resolutions. next ( ) else {
550567 // Associate an HirId to both ids even if there is no resolution.
551- self . owners . ensure_contains_elem ( new_id, || hir:: MaybeOwner :: Phantom ) ;
552- let _old = std:: mem:: replace (
553- & mut self . owners [ new_id] ,
568+ let _old = self . children . insert (
569+ new_id,
554570 hir:: MaybeOwner :: NonOwner ( hir:: HirId :: make_owner ( new_id) ) ,
555571 ) ;
556- debug_assert ! ( matches! ( _old, hir :: MaybeOwner :: Phantom ) ) ;
572+ debug_assert ! ( _old. is_none ( ) ) ;
557573 continue ;
558574 } ;
559575 let ident = * ident;
0 commit comments