5
5
//! - Building the type for an item: This happens through the `type_for_def` query.
6
6
//!
7
7
//! This usually involves resolving names, collecting generic arguments etc.
8
+ use std:: cell:: { Cell , RefCell } ;
8
9
use std:: { iter, sync:: Arc } ;
9
10
10
11
use base_db:: CrateId ;
11
12
use chalk_ir:: { cast:: Cast , fold:: Shift , interner:: HasInterner , Mutability , Safety } ;
12
13
use hir_def:: {
13
14
adt:: StructKind ,
15
+ body:: { Expander , LowerCtx } ,
14
16
builtin_type:: BuiltinType ,
15
17
generics:: { TypeParamProvenance , WherePredicate , WherePredicateTypeTarget } ,
16
18
path:: { GenericArg , Path , PathSegment , PathSegments } ,
17
19
resolver:: { HasResolver , Resolver , TypeNs } ,
18
- type_ref:: { expand_macro_type , TraitRef as HirTraitRef , TypeBound , TypeRef } ,
20
+ type_ref:: { TraitRef as HirTraitRef , TypeBound , TypeRef } ,
19
21
AdtId , AssocContainerId , AssocItemId , ConstId , ConstParamId , EnumId , EnumVariantId , FunctionId ,
20
22
GenericDefId , HasModule , ImplId , LocalFieldId , Lookup , StaticId , StructId , TraitId ,
21
23
TypeAliasId , TypeParamId , UnionId , VariantId ,
22
24
} ;
23
- use hir_expand:: name:: Name ;
25
+ use hir_expand:: { name:: Name , ExpandResult } ;
24
26
use la_arena:: ArenaMap ;
25
27
use smallvec:: SmallVec ;
26
28
use stdx:: impl_from;
29
+ use syntax:: ast;
27
30
28
31
use crate :: {
29
32
db:: HirDatabase ,
@@ -50,7 +53,7 @@ pub struct TyLoweringContext<'a> {
50
53
/// possible currently, so this should be fine for now.
51
54
pub type_param_mode : TypeParamLoweringMode ,
52
55
pub impl_trait_mode : ImplTraitLoweringMode ,
53
- impl_trait_counter : std :: cell :: Cell < u16 > ,
56
+ impl_trait_counter : Cell < u16 > ,
54
57
/// When turning `impl Trait` into opaque types, we have to collect the
55
58
/// bounds at the same time to get the IDs correct (without becoming too
56
59
/// complicated). I don't like using interior mutability (as for the
@@ -59,16 +62,17 @@ pub struct TyLoweringContext<'a> {
59
62
/// we're grouping the mutable data (the counter and this field) together
60
63
/// with the immutable context (the references to the DB and resolver).
61
64
/// Splitting this up would be a possible fix.
62
- opaque_type_data : std:: cell:: RefCell < Vec < ReturnTypeImplTrait > > ,
65
+ opaque_type_data : RefCell < Vec < ReturnTypeImplTrait > > ,
66
+ expander : RefCell < Option < Expander > > ,
63
67
}
64
68
65
69
impl < ' a > TyLoweringContext < ' a > {
66
70
pub fn new ( db : & ' a dyn HirDatabase , resolver : & ' a Resolver ) -> Self {
67
- let impl_trait_counter = std :: cell :: Cell :: new ( 0 ) ;
71
+ let impl_trait_counter = Cell :: new ( 0 ) ;
68
72
let impl_trait_mode = ImplTraitLoweringMode :: Disallowed ;
69
73
let type_param_mode = TypeParamLoweringMode :: Placeholder ;
70
74
let in_binders = DebruijnIndex :: INNERMOST ;
71
- let opaque_type_data = std :: cell :: RefCell :: new ( Vec :: new ( ) ) ;
75
+ let opaque_type_data = RefCell :: new ( Vec :: new ( ) ) ;
72
76
Self {
73
77
db,
74
78
resolver,
@@ -77,6 +81,7 @@ impl<'a> TyLoweringContext<'a> {
77
81
impl_trait_counter,
78
82
type_param_mode,
79
83
opaque_type_data,
84
+ expander : RefCell :: new ( None ) ,
80
85
}
81
86
}
82
87
@@ -86,15 +91,18 @@ impl<'a> TyLoweringContext<'a> {
86
91
f : impl FnOnce ( & TyLoweringContext ) -> T ,
87
92
) -> T {
88
93
let opaque_ty_data_vec = self . opaque_type_data . replace ( Vec :: new ( ) ) ;
94
+ let expander = self . expander . replace ( None ) ;
89
95
let new_ctx = Self {
90
96
in_binders : debruijn,
91
- impl_trait_counter : std:: cell:: Cell :: new ( self . impl_trait_counter . get ( ) ) ,
92
- opaque_type_data : std:: cell:: RefCell :: new ( opaque_ty_data_vec) ,
97
+ impl_trait_counter : Cell :: new ( self . impl_trait_counter . get ( ) ) ,
98
+ opaque_type_data : RefCell :: new ( opaque_ty_data_vec) ,
99
+ expander : RefCell :: new ( expander) ,
93
100
..* self
94
101
} ;
95
102
let result = f ( & new_ctx) ;
96
103
self . impl_trait_counter . set ( new_ctx. impl_trait_counter . get ( ) ) ;
97
104
self . opaque_type_data . replace ( new_ctx. opaque_type_data . into_inner ( ) ) ;
105
+ self . expander . replace ( new_ctx. expander . into_inner ( ) ) ;
98
106
result
99
107
}
100
108
@@ -287,15 +295,50 @@ impl<'a> TyLoweringContext<'a> {
287
295
}
288
296
}
289
297
}
290
- mt @ TypeRef :: Macro ( _) => {
291
- if let Some ( module_id) = self . resolver . module ( ) {
292
- match expand_macro_type ( self . db . upcast ( ) , module_id, mt) {
293
- Some ( type_ref) => self . lower_ty ( & type_ref) ,
294
- None => TyKind :: Error . intern ( & Interner ) ,
298
+ TypeRef :: Macro ( macro_call) => {
299
+ let ( expander, recursion_start) = match self . expander . borrow_mut ( ) {
300
+ expander if expander. is_some ( ) => ( Some ( expander) , false ) ,
301
+ mut expander => {
302
+ if let Some ( module_id) = self . resolver . module ( ) {
303
+ * expander = Some ( Expander :: new (
304
+ self . db . upcast ( ) ,
305
+ macro_call. file_id ,
306
+ module_id,
307
+ ) ) ;
308
+ ( Some ( expander) , true )
309
+ } else {
310
+ ( None , false )
311
+ }
312
+ }
313
+ } ;
314
+ let ty = if let Some ( mut expander) = expander {
315
+ let expander_mut = expander. as_mut ( ) . unwrap ( ) ;
316
+ let macro_call = macro_call. to_node ( self . db . upcast ( ) ) ;
317
+ match expander_mut. enter_expand :: < ast:: Type > ( self . db . upcast ( ) , macro_call) {
318
+ Ok ( ExpandResult { value : Some ( ( mark, expanded) ) , .. } ) => {
319
+ let ctx =
320
+ LowerCtx :: new ( self . db . upcast ( ) , expander_mut. current_file_id ( ) ) ;
321
+ let type_ref = TypeRef :: from_ast ( & ctx, expanded) ;
322
+
323
+ drop ( expander) ;
324
+ let ty = self . lower_ty ( & type_ref) ;
325
+
326
+ self . expander
327
+ . borrow_mut ( )
328
+ . as_mut ( )
329
+ . unwrap ( )
330
+ . exit ( self . db . upcast ( ) , mark) ;
331
+ Some ( ty)
332
+ }
333
+ _ => None ,
295
334
}
296
335
} else {
297
- TyKind :: Error . intern ( & Interner )
336
+ None
337
+ } ;
338
+ if recursion_start {
339
+ * self . expander . borrow_mut ( ) = None ;
298
340
}
341
+ ty. unwrap_or_else ( || TyKind :: Error . intern ( & Interner ) )
299
342
}
300
343
TypeRef :: Error => TyKind :: Error . intern ( & Interner ) ,
301
344
} ;
0 commit comments