@@ -57,10 +57,7 @@ impl TokenExpander {
57
57
TokenExpander :: BuiltinAttr ( it) => it. expand ( db, id, tt) ,
58
58
TokenExpander :: BuiltinDerive ( it) => it. expand ( db, id, tt) ,
59
59
TokenExpander :: ProcMacro ( _) => {
60
- // We store the result in salsa db to prevent non-deterministic behavior in
61
- // some proc-macro implementation
62
- // See #4315 for details
63
- db. expand_proc_macro ( id)
60
+ unreachable ! ( "ExpandDatabase::expand_proc_macro should be used for proc macros" )
64
61
}
65
62
}
66
63
}
@@ -141,8 +138,8 @@ pub trait ExpandDatabase: SourceDatabase {
141
138
/// Special case of the previous query for procedural macros. We can't LRU
142
139
/// proc macros, since they are not deterministic in general, and
143
140
/// non-determinism breaks salsa in a very, very, very bad way.
144
- /// @edwin0cheng heroically debugged this once!
145
- fn expand_proc_macro ( & self , call : MacroCallId ) -> ExpandResult < tt:: Subtree > ;
141
+ /// @edwin0cheng heroically debugged this once! See #4315 for details
142
+ fn expand_proc_macro ( & self , call : MacroCallId ) -> ExpandResult < Arc < tt:: Subtree > > ;
146
143
/// Firewall query that returns the errors from the `parse_macro_expansion` query.
147
144
fn parse_macro_expansion_error (
148
145
& self ,
@@ -297,6 +294,14 @@ fn parse_macro_expansion(
297
294
ExpandResult { value : ( parse, Arc :: new ( rev_token_map) ) , err }
298
295
}
299
296
297
+ fn parse_macro_expansion_error (
298
+ db : & dyn ExpandDatabase ,
299
+ macro_call_id : MacroCallId ,
300
+ ) -> ExpandResult < Box < [ SyntaxError ] > > {
301
+ db. parse_macro_expansion ( MacroFile { macro_call_id } )
302
+ . map ( |it| it. 0 . errors ( ) . to_vec ( ) . into_boxed_slice ( ) )
303
+ }
304
+
300
305
fn macro_arg (
301
306
db : & dyn ExpandDatabase ,
302
307
id : MacroCallId ,
@@ -445,6 +450,11 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt
445
450
// This is an input expansion for an eager macro. These are already pre-expanded
446
451
return ExpandResult { value : Arc :: new ( arg. 0 . clone ( ) ) , err : error. clone ( ) } ;
447
452
}
453
+
454
+ if let MacroDefKind :: ProcMacro ( ..) = loc. def . kind {
455
+ return db. expand_proc_macro ( id) ;
456
+ }
457
+
448
458
let expander = match db. macro_def ( loc. def ) {
449
459
Ok ( it) => it,
450
460
// FIXME: We should make sure to enforce a variant that invalid macro
@@ -467,7 +477,7 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt
467
477
token_trees : Vec :: new ( ) ,
468
478
} ,
469
479
) ,
470
- // FIXME: We should make sure to enforce a variant that invalid macro
480
+ // FIXME: We should make sure to enforce an invariant that invalid macro
471
481
// calls do not reach this call path!
472
482
err : Some ( ExpandError :: other (
473
483
"invalid token tree"
@@ -483,47 +493,29 @@ fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt
483
493
}
484
494
485
495
// Set a hard limit for the expanded tt
486
- let count = tt. count ( ) ;
487
- if TOKEN_LIMIT . check ( count) . is_err ( ) {
488
- return ExpandResult {
489
- value : Arc :: new ( tt:: Subtree {
490
- delimiter : tt:: Delimiter :: UNSPECIFIED ,
491
- token_trees : vec ! [ ] ,
492
- } ) ,
493
- err : Some ( ExpandError :: other ( format ! (
494
- "macro invocation exceeds token limit: produced {} tokens, limit is {}" ,
495
- count,
496
- TOKEN_LIMIT . inner( ) ,
497
- ) ) ) ,
498
- } ;
496
+ if let Err ( value) = check_tt_count ( & tt) {
497
+ return value;
499
498
}
500
499
501
500
fixup:: reverse_fixups ( & mut tt, arg_tm, undo_info) ;
502
501
503
502
ExpandResult { value : Arc :: new ( tt) , err }
504
503
}
505
504
506
- fn parse_macro_expansion_error (
507
- db : & dyn ExpandDatabase ,
508
- macro_call_id : MacroCallId ,
509
- ) -> ExpandResult < Box < [ SyntaxError ] > > {
510
- db. parse_macro_expansion ( MacroFile { macro_call_id } )
511
- . map ( |it| it. 0 . errors ( ) . to_vec ( ) . into_boxed_slice ( ) )
512
- }
513
-
514
- fn expand_proc_macro ( db : & dyn ExpandDatabase , id : MacroCallId ) -> ExpandResult < tt:: Subtree > {
505
+ fn expand_proc_macro ( db : & dyn ExpandDatabase , id : MacroCallId ) -> ExpandResult < Arc < tt:: Subtree > > {
515
506
let loc = db. lookup_intern_macro_call ( id) ;
516
507
let Some ( macro_arg) = db. macro_arg ( id) else {
517
508
return ExpandResult {
518
- value : tt:: Subtree {
509
+ value : Arc :: new ( tt:: Subtree {
519
510
delimiter : tt:: Delimiter :: UNSPECIFIED ,
520
511
token_trees : Vec :: new ( ) ,
521
- } ,
512
+ } ) ,
522
513
err : Some ( ExpandError :: other (
523
514
"invalid token tree"
524
515
) ) ,
525
516
} ;
526
517
} ;
518
+ let ( arg_tt, arg_tm, undo_info) = & * macro_arg;
527
519
528
520
let expander = match loc. def . kind {
529
521
MacroDefKind :: ProcMacro ( expander, ..) => expander,
@@ -533,13 +525,23 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<t
533
525
let attr_arg = match & loc. kind {
534
526
MacroCallKind :: Attr { attr_args, .. } => {
535
527
let mut attr_args = attr_args. 0 . clone ( ) ;
536
- mbe:: Shift :: new ( & macro_arg . 0 ) . shift_all ( & mut attr_args) ;
528
+ mbe:: Shift :: new ( arg_tt ) . shift_all ( & mut attr_args) ;
537
529
Some ( attr_args)
538
530
}
539
531
_ => None ,
540
532
} ;
541
533
542
- expander. expand ( db, loc. def . krate , loc. krate , & macro_arg. 0 , attr_arg. as_ref ( ) )
534
+ let ExpandResult { value : mut tt, err } =
535
+ expander. expand ( db, loc. def . krate , loc. krate , arg_tt, attr_arg. as_ref ( ) ) ;
536
+
537
+ // Set a hard limit for the expanded tt
538
+ if let Err ( value) = check_tt_count ( & tt) {
539
+ return value;
540
+ }
541
+
542
+ fixup:: reverse_fixups ( & mut tt, arg_tm, undo_info) ;
543
+
544
+ ExpandResult { value : Arc :: new ( tt) , err }
543
545
}
544
546
545
547
fn hygiene_frame ( db : & dyn ExpandDatabase , file_id : HirFileId ) -> Arc < HygieneFrame > {
@@ -563,3 +565,22 @@ fn token_tree_to_syntax_node(
563
565
} ;
564
566
mbe:: token_tree_to_syntax_node ( tt, entry_point)
565
567
}
568
+
569
+ fn check_tt_count ( tt : & tt:: Subtree ) -> Result < ( ) , ExpandResult < Arc < tt:: Subtree > > > {
570
+ let count = tt. count ( ) ;
571
+ if TOKEN_LIMIT . check ( count) . is_err ( ) {
572
+ Err ( ExpandResult {
573
+ value : Arc :: new ( tt:: Subtree {
574
+ delimiter : tt:: Delimiter :: UNSPECIFIED ,
575
+ token_trees : vec ! [ ] ,
576
+ } ) ,
577
+ err : Some ( ExpandError :: other ( format ! (
578
+ "macro invocation exceeds token limit: produced {} tokens, limit is {}" ,
579
+ count,
580
+ TOKEN_LIMIT . inner( ) ,
581
+ ) ) ) ,
582
+ } )
583
+ } else {
584
+ Ok ( ( ) )
585
+ }
586
+ }
0 commit comments