@@ -102,6 +102,7 @@ struct MacroDirective {
102
102
module_id : LocalModuleId ,
103
103
ast_id : AstIdWithPath < ast:: MacroCall > ,
104
104
legacy : Option < MacroCallId > ,
105
+ depth : usize ,
105
106
}
106
107
107
108
#[ derive( Clone , Debug , Eq , PartialEq ) ]
@@ -134,6 +135,7 @@ where
134
135
self . def_map . modules [ module_id] . origin = ModuleOrigin :: CrateRoot { definition : file_id } ;
135
136
ModCollector {
136
137
def_collector : & mut * self ,
138
+ macro_depth : 0 ,
137
139
module_id,
138
140
file_id : file_id. into ( ) ,
139
141
raw_items : & raw_items,
@@ -516,7 +518,7 @@ where
516
518
macros. retain ( |directive| {
517
519
if let Some ( call_id) = directive. legacy {
518
520
res = ReachedFixedPoint :: No ;
519
- resolved. push ( ( directive. module_id , call_id) ) ;
521
+ resolved. push ( ( directive. module_id , call_id, directive . depth ) ) ;
520
522
return false ;
521
523
}
522
524
@@ -530,7 +532,7 @@ where
530
532
) ;
531
533
resolved_res. resolved_def . take_macros ( )
532
534
} ) {
533
- resolved. push ( ( directive. module_id , call_id) ) ;
535
+ resolved. push ( ( directive. module_id , call_id, directive . depth ) ) ;
534
536
res = ReachedFixedPoint :: No ;
535
537
return false ;
536
538
}
@@ -541,7 +543,7 @@ where
541
543
if let Some ( call_id) =
542
544
directive. ast_id . as_call_id ( self . db , |path| self . resolve_attribute_macro ( & path) )
543
545
{
544
- resolved. push ( ( directive. module_id , call_id) ) ;
546
+ resolved. push ( ( directive. module_id , call_id, 0 ) ) ;
545
547
res = ReachedFixedPoint :: No ;
546
548
return false ;
547
549
}
@@ -552,8 +554,12 @@ where
552
554
self . unexpanded_macros = macros;
553
555
self . unexpanded_attribute_macros = attribute_macros;
554
556
555
- for ( module_id, macro_call_id) in resolved {
556
- self . collect_macro_expansion ( module_id, macro_call_id) ;
557
+ for ( module_id, macro_call_id, depth) in resolved {
558
+ if depth > 1024 {
559
+ log:: debug!( "Max macro expansion depth reached" ) ;
560
+ continue ;
561
+ }
562
+ self . collect_macro_expansion ( module_id, macro_call_id, depth) ;
557
563
}
558
564
559
565
res
@@ -573,12 +579,18 @@ where
573
579
None
574
580
}
575
581
576
- fn collect_macro_expansion ( & mut self , module_id : LocalModuleId , macro_call_id : MacroCallId ) {
582
+ fn collect_macro_expansion (
583
+ & mut self ,
584
+ module_id : LocalModuleId ,
585
+ macro_call_id : MacroCallId ,
586
+ depth : usize ,
587
+ ) {
577
588
let file_id: HirFileId = macro_call_id. as_file ( ) ;
578
589
let raw_items = self . db . raw_items ( file_id) ;
579
590
let mod_dir = self . mod_dirs [ & module_id] . clone ( ) ;
580
591
ModCollector {
581
592
def_collector : & mut * self ,
593
+ macro_depth : depth,
582
594
file_id,
583
595
module_id,
584
596
raw_items : & raw_items,
@@ -595,6 +607,7 @@ where
595
607
/// Walks a single module, populating defs, imports and macros
596
608
struct ModCollector < ' a , D > {
597
609
def_collector : D ,
610
+ macro_depth : usize ,
598
611
module_id : LocalModuleId ,
599
612
file_id : HirFileId ,
600
613
raw_items : & ' a raw:: RawItems ,
@@ -684,6 +697,7 @@ where
684
697
685
698
ModCollector {
686
699
def_collector : & mut * self . def_collector ,
700
+ macro_depth : self . macro_depth ,
687
701
module_id,
688
702
file_id : self . file_id ,
689
703
raw_items : self . raw_items ,
@@ -713,6 +727,7 @@ where
713
727
let raw_items = self . def_collector . db . raw_items ( file_id. into ( ) ) ;
714
728
ModCollector {
715
729
def_collector : & mut * self . def_collector ,
730
+ macro_depth : self . macro_depth ,
716
731
module_id,
717
732
file_id : file_id. into ( ) ,
718
733
raw_items : & raw_items,
@@ -887,6 +902,7 @@ where
887
902
module_id : self . module_id ,
888
903
ast_id,
889
904
legacy : Some ( macro_call_id) ,
905
+ depth : self . macro_depth + 1 ,
890
906
} ) ;
891
907
892
908
return ;
@@ -902,6 +918,7 @@ where
902
918
module_id : self . module_id ,
903
919
ast_id,
904
920
legacy : None ,
921
+ depth : self . macro_depth + 1 ,
905
922
} ) ;
906
923
}
907
924
@@ -971,13 +988,26 @@ mod tests {
971
988
}
972
989
973
990
#[ test]
974
- fn test_macro_expand_will_stop ( ) {
991
+ fn test_macro_expand_will_stop_1 ( ) {
992
+ do_resolve (
993
+ r#"
994
+ macro_rules! foo {
995
+ ($($ty:ty)*) => { foo!($($ty)*); }
996
+ }
997
+ foo!(KABOOM);
998
+ "# ,
999
+ ) ;
1000
+ }
1001
+
1002
+ #[ ignore] // this test does succeed, but takes quite a while :/
1003
+ #[ test]
1004
+ fn test_macro_expand_will_stop_2 ( ) {
975
1005
do_resolve (
976
1006
r#"
977
1007
macro_rules! foo {
978
- ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); }
1008
+ ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }
979
1009
}
980
- foo!(KABOOM);
1010
+ foo!(KABOOM);
981
1011
"# ,
982
1012
) ;
983
1013
}
0 commit comments