1
1
//! Defines database & queries for macro expansion.
2
2
3
- use base_db:: { salsa, Edition , SourceDatabase } ;
3
+ use base_db:: { salsa, CrateId , Edition , SourceDatabase } ;
4
4
use either:: Either ;
5
5
use limit:: Limit ;
6
6
use mbe:: syntax_node_to_token_tree;
@@ -13,7 +13,7 @@ use triomphe::Arc;
13
13
14
14
use crate :: {
15
15
ast_id_map:: AstIdMap , builtin_attr_macro:: pseudo_derive_attr_expansion,
16
- builtin_fn_macro:: EagerExpander , fixup, hygiene:: HygieneFrame , tt, BuiltinAttrExpander ,
16
+ builtin_fn_macro:: EagerExpander , fixup, hygiene:: HygieneFrame , tt, AstId , BuiltinAttrExpander ,
17
17
BuiltinDeriveExpander , BuiltinFnLikeExpander , EagerCallInfo , ExpandError , ExpandResult ,
18
18
ExpandTo , HirFileId , HirFileIdRepr , MacroCallId , MacroCallKind , MacroCallLoc , MacroDefId ,
19
19
MacroDefKind , MacroFile , ProcMacroExpander ,
@@ -27,61 +27,59 @@ use crate::{
27
27
/// Actual max for `analysis-stats .` at some point: 30672.
28
28
static TOKEN_LIMIT : Limit = Limit :: new ( 1_048_576 ) ;
29
29
30
+ #[ derive( Debug , Clone , Eq , PartialEq ) ]
31
+ /// Old-style `macro_rules` or the new macros 2.0
32
+ pub struct DeclarativeMacroExpander {
33
+ pub mac : mbe:: DeclarativeMacro ,
34
+ pub def_site_token_map : mbe:: TokenMap ,
35
+ }
36
+
37
+ impl DeclarativeMacroExpander {
38
+ pub fn expand ( & self , tt : & tt:: Subtree ) -> ExpandResult < tt:: Subtree > {
39
+ match self . mac . err ( ) {
40
+ Some ( e) => ExpandResult :: new (
41
+ tt:: Subtree :: empty ( ) ,
42
+ ExpandError :: other ( format ! ( "invalid macro definition: {e}" ) ) ,
43
+ ) ,
44
+ None => self . mac . expand ( tt) . map_err ( Into :: into) ,
45
+ }
46
+ }
47
+ }
48
+
30
49
#[ derive( Debug , Clone , Eq , PartialEq ) ]
31
50
pub enum TokenExpander {
32
- /// Old-style `macro_rules` or the new macros 2.0
33
- DeclarativeMacro { mac : mbe:: DeclarativeMacro , def_site_token_map : mbe:: TokenMap } ,
51
+ DeclarativeMacro ( Arc < DeclarativeMacroExpander > ) ,
34
52
/// Stuff like `line!` and `file!`.
35
- Builtin ( BuiltinFnLikeExpander ) ,
53
+ BuiltIn ( BuiltinFnLikeExpander ) ,
36
54
/// Built-in eagerly expanded fn-like macros (`include!`, `concat!`, etc.)
37
- BuiltinEager ( EagerExpander ) ,
55
+ BuiltInEager ( EagerExpander ) ,
38
56
/// `global_allocator` and such.
39
- BuiltinAttr ( BuiltinAttrExpander ) ,
57
+ BuiltInAttr ( BuiltinAttrExpander ) ,
40
58
/// `derive(Copy)` and such.
41
- BuiltinDerive ( BuiltinDeriveExpander ) ,
59
+ BuiltInDerive ( BuiltinDeriveExpander ) ,
42
60
/// The thing we love the most here in rust-analyzer -- procedural macros.
43
61
ProcMacro ( ProcMacroExpander ) ,
44
62
}
45
63
46
64
impl TokenExpander {
47
- fn expand (
48
- & self ,
49
- db : & dyn ExpandDatabase ,
50
- id : MacroCallId ,
51
- tt : & tt:: Subtree ,
52
- ) -> ExpandResult < tt:: Subtree > {
53
- match self {
54
- TokenExpander :: DeclarativeMacro { mac, .. } => mac. expand ( tt) . map_err ( Into :: into) ,
55
- TokenExpander :: Builtin ( it) => it. expand ( db, id, tt) . map_err ( Into :: into) ,
56
- TokenExpander :: BuiltinEager ( it) => it. expand ( db, id, tt) . map_err ( Into :: into) ,
57
- TokenExpander :: BuiltinAttr ( it) => it. expand ( db, id, tt) ,
58
- TokenExpander :: BuiltinDerive ( _) => {
59
- unreachable ! ( "builtin derives should be expanded manually" )
60
- }
61
- TokenExpander :: ProcMacro ( _) => {
62
- unreachable ! ( "ExpandDatabase::expand_proc_macro should be used for proc macros" )
63
- }
64
- }
65
- }
66
-
67
65
pub ( crate ) fn map_id_down ( & self , id : tt:: TokenId ) -> tt:: TokenId {
68
66
match self {
69
- TokenExpander :: DeclarativeMacro { mac , .. } => mac. map_id_down ( id) ,
70
- TokenExpander :: Builtin ( ..)
71
- | TokenExpander :: BuiltinEager ( ..)
72
- | TokenExpander :: BuiltinAttr ( ..)
73
- | TokenExpander :: BuiltinDerive ( ..)
67
+ TokenExpander :: DeclarativeMacro ( expander ) => expander . mac . map_id_down ( id) ,
68
+ TokenExpander :: BuiltIn ( ..)
69
+ | TokenExpander :: BuiltInEager ( ..)
70
+ | TokenExpander :: BuiltInAttr ( ..)
71
+ | TokenExpander :: BuiltInDerive ( ..)
74
72
| TokenExpander :: ProcMacro ( ..) => id,
75
73
}
76
74
}
77
75
78
76
pub ( crate ) fn map_id_up ( & self , id : tt:: TokenId ) -> ( tt:: TokenId , mbe:: Origin ) {
79
77
match self {
80
- TokenExpander :: DeclarativeMacro { mac , .. } => mac. map_id_up ( id) ,
81
- TokenExpander :: Builtin ( ..)
82
- | TokenExpander :: BuiltinEager ( ..)
83
- | TokenExpander :: BuiltinAttr ( ..)
84
- | TokenExpander :: BuiltinDerive ( ..)
78
+ TokenExpander :: DeclarativeMacro ( expander ) => expander . mac . map_id_up ( id) ,
79
+ TokenExpander :: BuiltIn ( ..)
80
+ | TokenExpander :: BuiltInEager ( ..)
81
+ | TokenExpander :: BuiltInAttr ( ..)
82
+ | TokenExpander :: BuiltInDerive ( ..)
85
83
| TokenExpander :: ProcMacro ( ..) => ( id, mbe:: Origin :: Call ) ,
86
84
}
87
85
}
@@ -124,7 +122,14 @@ pub trait ExpandDatabase: SourceDatabase {
124
122
fn macro_arg_text ( & self , id : MacroCallId ) -> Option < GreenNode > ;
125
123
/// Gets the expander for this macro. This compiles declarative macros, and
126
124
/// just fetches procedural ones.
127
- fn macro_def ( & self , id : MacroDefId ) -> Result < Arc < TokenExpander > , mbe:: ParseError > ;
125
+ // FIXME: Rename this
126
+ #[ salsa:: transparent]
127
+ fn macro_def ( & self , id : MacroDefId ) -> TokenExpander ;
128
+ fn decl_macro_expander (
129
+ & self ,
130
+ def_crate : CrateId ,
131
+ id : AstId < ast:: Macro > ,
132
+ ) -> Arc < DeclarativeMacroExpander > ;
128
133
129
134
/// Expand macro call to a token tree.
130
135
// This query is LRU cached
@@ -162,7 +167,7 @@ pub fn expand_speculative(
162
167
token_to_map : SyntaxToken ,
163
168
) -> Option < ( SyntaxNode , SyntaxToken ) > {
164
169
let loc = db. lookup_intern_macro_call ( actual_macro_call) ;
165
- let macro_def = db. macro_def ( loc. def ) . ok ( ) ? ;
170
+ let macro_def = db. macro_def ( loc. def ) ;
166
171
let token_range = token_to_map. text_range ( ) ;
167
172
168
173
// Build the subtree and token mapping for the speculative args
@@ -239,7 +244,12 @@ pub fn expand_speculative(
239
244
let adt = ast:: Adt :: cast ( speculative_args. clone ( ) ) . unwrap ( ) ;
240
245
expander. expand ( db, actual_macro_call, & adt, & spec_args_tmap)
241
246
}
242
- _ => macro_def. expand ( db, actual_macro_call, & tt) ,
247
+ MacroDefKind :: Declarative ( it) => db. decl_macro_expander ( loc. krate , it) . expand ( & tt) ,
248
+ MacroDefKind :: BuiltIn ( it, _) => it. expand ( db, actual_macro_call, & tt) . map_err ( Into :: into) ,
249
+ MacroDefKind :: BuiltInEager ( it, _) => {
250
+ it. expand ( db, actual_macro_call, & tt) . map_err ( Into :: into)
251
+ }
252
+ MacroDefKind :: BuiltInAttr ( it, _) => it. expand ( db, actual_macro_call, & tt) ,
243
253
} ;
244
254
245
255
let expand_to = macro_expand_to ( db, actual_macro_call) ;
@@ -412,44 +422,55 @@ fn macro_arg_text(db: &dyn ExpandDatabase, id: MacroCallId) -> Option<GreenNode>
412
422
}
413
423
}
414
424
415
- fn macro_def (
425
+ fn decl_macro_expander (
416
426
db : & dyn ExpandDatabase ,
417
- id : MacroDefId ,
418
- ) -> Result < Arc < TokenExpander > , mbe:: ParseError > {
427
+ def_crate : CrateId ,
428
+ id : AstId < ast:: Macro > ,
429
+ ) -> Arc < DeclarativeMacroExpander > {
430
+ let is_2021 = db. crate_graph ( ) [ def_crate] . edition >= Edition :: Edition2021 ;
431
+ let ( mac, def_site_token_map) = match id. to_node ( db) {
432
+ ast:: Macro :: MacroRules ( macro_rules) => match macro_rules. token_tree ( ) {
433
+ Some ( arg) => {
434
+ let ( tt, def_site_token_map) = mbe:: syntax_node_to_token_tree ( arg. syntax ( ) ) ;
435
+ let mac = mbe:: DeclarativeMacro :: parse_macro_rules ( & tt, is_2021) ;
436
+ ( mac, def_site_token_map)
437
+ }
438
+ None => (
439
+ mbe:: DeclarativeMacro :: from_err (
440
+ mbe:: ParseError :: Expected ( "expected a token tree" . into ( ) ) ,
441
+ is_2021,
442
+ ) ,
443
+ Default :: default ( ) ,
444
+ ) ,
445
+ } ,
446
+ ast:: Macro :: MacroDef ( macro_def) => match macro_def. body ( ) {
447
+ Some ( arg) => {
448
+ let ( tt, def_site_token_map) = mbe:: syntax_node_to_token_tree ( arg. syntax ( ) ) ;
449
+ let mac = mbe:: DeclarativeMacro :: parse_macro2 ( & tt, is_2021) ;
450
+ ( mac, def_site_token_map)
451
+ }
452
+ None => (
453
+ mbe:: DeclarativeMacro :: from_err (
454
+ mbe:: ParseError :: Expected ( "expected a token tree" . into ( ) ) ,
455
+ is_2021,
456
+ ) ,
457
+ Default :: default ( ) ,
458
+ ) ,
459
+ } ,
460
+ } ;
461
+ Arc :: new ( DeclarativeMacroExpander { mac, def_site_token_map } )
462
+ }
463
+
464
+ fn macro_def ( db : & dyn ExpandDatabase , id : MacroDefId ) -> TokenExpander {
419
465
match id. kind {
420
466
MacroDefKind :: Declarative ( ast_id) => {
421
- let is_2021 = db. crate_graph ( ) [ id. krate ] . edition >= Edition :: Edition2021 ;
422
- let ( mac, def_site_token_map) = match ast_id. to_node ( db) {
423
- ast:: Macro :: MacroRules ( macro_rules) => {
424
- let arg = macro_rules
425
- . token_tree ( )
426
- . ok_or_else ( || mbe:: ParseError :: Expected ( "expected a token tree" . into ( ) ) ) ?;
427
- let ( tt, def_site_token_map) = mbe:: syntax_node_to_token_tree ( arg. syntax ( ) ) ;
428
- let mac = mbe:: DeclarativeMacro :: parse_macro_rules ( & tt, is_2021) ?;
429
- ( mac, def_site_token_map)
430
- }
431
- ast:: Macro :: MacroDef ( macro_def) => {
432
- let arg = macro_def
433
- . body ( )
434
- . ok_or_else ( || mbe:: ParseError :: Expected ( "expected a token tree" . into ( ) ) ) ?;
435
- let ( tt, def_site_token_map) = mbe:: syntax_node_to_token_tree ( arg. syntax ( ) ) ;
436
- let mac = mbe:: DeclarativeMacro :: parse_macro2 ( & tt, is_2021) ?;
437
- ( mac, def_site_token_map)
438
- }
439
- } ;
440
- Ok ( Arc :: new ( TokenExpander :: DeclarativeMacro { mac, def_site_token_map } ) )
441
- }
442
- MacroDefKind :: BuiltIn ( expander, _) => Ok ( Arc :: new ( TokenExpander :: Builtin ( expander) ) ) ,
443
- MacroDefKind :: BuiltInAttr ( expander, _) => {
444
- Ok ( Arc :: new ( TokenExpander :: BuiltinAttr ( expander) ) )
445
- }
446
- MacroDefKind :: BuiltInDerive ( expander, _) => {
447
- Ok ( Arc :: new ( TokenExpander :: BuiltinDerive ( expander) ) )
448
- }
449
- MacroDefKind :: BuiltInEager ( expander, ..) => {
450
- Ok ( Arc :: new ( TokenExpander :: BuiltinEager ( expander) ) )
467
+ TokenExpander :: DeclarativeMacro ( db. decl_macro_expander ( id. krate , ast_id) )
451
468
}
452
- MacroDefKind :: ProcMacro ( expander, ..) => Ok ( Arc :: new ( TokenExpander :: ProcMacro ( expander) ) ) ,
469
+ MacroDefKind :: BuiltIn ( expander, _) => TokenExpander :: BuiltIn ( expander) ,
470
+ MacroDefKind :: BuiltInAttr ( expander, _) => TokenExpander :: BuiltInAttr ( expander) ,
471
+ MacroDefKind :: BuiltInDerive ( expander, _) => TokenExpander :: BuiltInDerive ( expander) ,
472
+ MacroDefKind :: BuiltInEager ( expander, ..) => TokenExpander :: BuiltInEager ( expander) ,
473
+ MacroDefKind :: ProcMacro ( expander, ..) => TokenExpander :: ProcMacro ( expander) ,
453
474
}
454
475
}
455
476
@@ -483,20 +504,6 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt
483
504
( expander. expand ( db, id, & adt, & tmap) , Some ( ( tmap, fixups. undo_info ) ) )
484
505
}
485
506
_ => {
486
- let expander = match db. macro_def ( loc. def ) {
487
- Ok ( it) => it,
488
- // FIXME: We should make sure to enforce a variant that invalid macro
489
- // definitions do not get expanders that could reach this call path!
490
- Err ( err) => {
491
- return ExpandResult {
492
- value : Arc :: new ( tt:: Subtree {
493
- delimiter : tt:: Delimiter :: UNSPECIFIED ,
494
- token_trees : vec ! [ ] ,
495
- } ) ,
496
- err : Some ( ExpandError :: other ( format ! ( "invalid macro definition: {err}" ) ) ) ,
497
- }
498
- }
499
- } ;
500
507
let Some ( macro_arg) = db. macro_arg ( id) else {
501
508
return ExpandResult {
502
509
value : Arc :: new ( tt:: Subtree {
@@ -509,7 +516,15 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt
509
516
} ;
510
517
} ;
511
518
let ( arg, arg_tm, undo_info) = & * macro_arg;
512
- let mut res = expander. expand ( db, id, arg) ;
519
+ let mut res = match loc. def . kind {
520
+ MacroDefKind :: Declarative ( id) => {
521
+ db. decl_macro_expander ( loc. def . krate , id) . expand ( & arg)
522
+ }
523
+ MacroDefKind :: BuiltIn ( it, _) => it. expand ( db, id, & arg) . map_err ( Into :: into) ,
524
+ MacroDefKind :: BuiltInEager ( it, _) => it. expand ( db, id, & arg) . map_err ( Into :: into) ,
525
+ MacroDefKind :: BuiltInAttr ( it, _) => it. expand ( db, id, & arg) ,
526
+ _ => unreachable ! ( ) ,
527
+ } ;
513
528
fixup:: reverse_fixups ( & mut res. value , arg_tm, undo_info) ;
514
529
( res, None )
515
530
}
0 commit comments