1
1
use super :: { AnonymousLifetimeMode , LoweringContext , ParamMode } ;
2
- use super :: { ImplTraitContext , ImplTraitPosition } ;
2
+ use super :: { AstOwner , ImplTraitContext , ImplTraitPosition , ResolverAstLowering } ;
3
3
use crate :: { Arena , FnDeclKind } ;
4
4
5
5
use rustc_ast:: ptr:: P ;
6
- use rustc_ast:: visit:: { self , AssocCtxt , FnCtxt , FnKind , Visitor } ;
6
+ use rustc_ast:: visit:: AssocCtxt ;
7
7
use 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 ;
9
10
use rustc_errors:: struct_span_err;
10
11
use rustc_hir as hir;
11
12
use 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 ;
14
17
use rustc_span:: source_map:: { respan, DesugaringKind } ;
15
18
use rustc_span:: symbol:: { kw, sym, Ident } ;
16
19
use rustc_span:: Span ;
@@ -19,10 +22,14 @@ use smallvec::{smallvec, SmallVec};
19
22
use tracing:: debug;
20
23
21
24
use std:: iter;
22
- use std:: mem;
23
25
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 > > > ,
26
33
}
27
34
28
35
/// 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(
45
52
}
46
53
}
47
54
48
- impl ItemLowerer < ' _ , ' _ , ' _ > {
49
- fn with_trait_impl_ref < T > (
55
+ impl < ' a , ' hir > ItemLowerer < ' a , ' hir > {
56
+ fn with_lctx (
50
57
& 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) ) ;
67
96
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
+ }
83
102
}
84
103
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) ,
92
117
}
93
- _ => visit:: walk_fn ( self , fk, sp) ,
94
118
}
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
- } ) ;
103
119
104
- visit :: walk_assoc_item ( self , item , ctxt ) ;
120
+ self . owners [ def_id ]
105
121
}
106
122
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 ) ;
111
125
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
+ } )
113
131
}
114
- }
115
132
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) ) )
149
135
}
150
136
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 ) ;
158
139
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
+ } ;
163
145
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
+ } ;
165
175
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
+ }
168
182
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) ) )
170
185
}
186
+ }
171
187
188
+ impl < ' hir > LoweringContext < ' _ , ' hir > {
172
189
pub ( super ) fn lower_mod ( & mut self , items : & [ P < Item > ] , inner : Span ) -> hir:: Mod < ' hir > {
173
190
hir:: Mod {
174
191
inner : self . lower_span ( inner) ,
@@ -548,12 +565,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
548
565
let new_id = self . resolver . local_def_id ( new_node_id) ;
549
566
let Some ( res) = resolutions. next ( ) else {
550
567
// 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,
554
570
hir:: MaybeOwner :: NonOwner ( hir:: HirId :: make_owner ( new_id) ) ,
555
571
) ;
556
- debug_assert ! ( matches! ( _old, hir :: MaybeOwner :: Phantom ) ) ;
572
+ debug_assert ! ( _old. is_none ( ) ) ;
557
573
continue ;
558
574
} ;
559
575
let ident = * ident;
0 commit comments