@@ -24,6 +24,7 @@ use hir_expand::{
24
24
builtin:: { BuiltinFnLikeExpander , EagerExpander } ,
25
25
db:: ExpandDatabase ,
26
26
files:: InRealFile ,
27
+ hygiene:: SyntaxContextExt as _,
27
28
inert_attr_macro:: find_builtin_attr_idx,
28
29
name:: AsName ,
29
30
FileRange , InMacroFile , MacroCallId , MacroFileId , MacroFileIdExt ,
@@ -32,7 +33,7 @@ use intern::Symbol;
32
33
use itertools:: Itertools ;
33
34
use rustc_hash:: { FxHashMap , FxHashSet } ;
34
35
use smallvec:: { smallvec, SmallVec } ;
35
- use span:: { EditionedFileId , FileId , HirFileIdRepr } ;
36
+ use span:: { EditionedFileId , FileId , HirFileIdRepr , SyntaxContextId } ;
36
37
use stdx:: TupleExt ;
37
38
use syntax:: {
38
39
algo:: skip_trivia_token,
@@ -608,7 +609,7 @@ impl<'db> SemanticsImpl<'db> {
608
609
let quote = string. open_quote_text_range ( ) ?;
609
610
610
611
let token = self . wrap_token_infile ( string. syntax ( ) . clone ( ) ) . into_real_file ( ) . ok ( ) ?;
611
- self . descend_into_macros_breakable ( token, |token| {
612
+ self . descend_into_macros_breakable ( token, |token, _ | {
612
613
( || {
613
614
let token = token. value ;
614
615
let string = ast:: String :: cast ( token) ?;
@@ -655,7 +656,7 @@ impl<'db> SemanticsImpl<'db> {
655
656
let original_string = ast:: String :: cast ( original_token. clone ( ) ) ?;
656
657
let original_token = self . wrap_token_infile ( original_token) . into_real_file ( ) . ok ( ) ?;
657
658
let quote = original_string. open_quote_text_range ( ) ?;
658
- self . descend_into_macros_breakable ( original_token, |token| {
659
+ self . descend_into_macros_breakable ( original_token, |token, _ | {
659
660
( || {
660
661
let token = token. value ;
661
662
self . resolve_offset_in_format_args (
@@ -718,7 +719,7 @@ impl<'db> SemanticsImpl<'db> {
718
719
// node is just the token, so descend the token
719
720
self . descend_into_macros_impl (
720
721
InRealFile :: new ( file_id, first) ,
721
- & mut |InFile { value, .. } | {
722
+ & mut |InFile { value, .. } , _ctx | {
722
723
if let Some ( node) = value
723
724
. parent_ancestors ( )
724
725
. take_while ( |it| it. text_range ( ) == value. text_range ( ) )
@@ -732,15 +733,15 @@ impl<'db> SemanticsImpl<'db> {
732
733
} else {
733
734
// Descend first and last token, then zip them to look for the node they belong to
734
735
let mut scratch: SmallVec < [ _ ; 1 ] > = smallvec ! [ ] ;
735
- self . descend_into_macros_impl ( InRealFile :: new ( file_id, first) , & mut |token| {
736
+ self . descend_into_macros_impl ( InRealFile :: new ( file_id, first) , & mut |token, _ctx | {
736
737
scratch. push ( token) ;
737
738
CONTINUE_NO_BREAKS
738
739
} ) ;
739
740
740
741
let mut scratch = scratch. into_iter ( ) ;
741
742
self . descend_into_macros_impl (
742
743
InRealFile :: new ( file_id, last) ,
743
- & mut |InFile { value : last, file_id : last_fid } | {
744
+ & mut |InFile { value : last, file_id : last_fid } , _ctx | {
744
745
if let Some ( InFile { value : first, file_id : first_fid } ) = scratch. next ( ) {
745
746
if first_fid == last_fid {
746
747
if let Some ( p) = first. parent ( ) {
@@ -763,7 +764,9 @@ impl<'db> SemanticsImpl<'db> {
763
764
res
764
765
}
765
766
766
- fn is_inside_macro_call ( token : & SyntaxToken ) -> bool {
767
+ // FIXME: This isn't quite right wrt to inner attributes
768
+ /// Does a syntactic traversal to check whether this token might be inside a macro call
769
+ pub fn might_be_inside_macro_call ( & self , token : & SyntaxToken ) -> bool {
767
770
token. parent_ancestors ( ) . any ( |ancestor| {
768
771
if ast:: MacroCall :: can_cast ( ancestor. kind ( ) ) {
769
772
return true ;
@@ -781,25 +784,14 @@ impl<'db> SemanticsImpl<'db> {
781
784
} )
782
785
}
783
786
784
- pub fn descend_into_macros_exact_if_in_macro (
785
- & self ,
786
- token : SyntaxToken ,
787
- ) -> SmallVec < [ SyntaxToken ; 1 ] > {
788
- if Self :: is_inside_macro_call ( & token) {
789
- self . descend_into_macros_exact ( token)
790
- } else {
791
- smallvec ! [ token]
792
- }
793
- }
794
-
795
787
pub fn descend_into_macros_cb (
796
788
& self ,
797
789
token : SyntaxToken ,
798
- mut cb : impl FnMut ( InFile < SyntaxToken > ) ,
790
+ mut cb : impl FnMut ( InFile < SyntaxToken > , SyntaxContextId ) ,
799
791
) {
800
792
if let Ok ( token) = self . wrap_token_infile ( token) . into_real_file ( ) {
801
- self . descend_into_macros_impl ( token, & mut |t| {
802
- cb ( t) ;
793
+ self . descend_into_macros_impl ( token, & mut |t, ctx | {
794
+ cb ( t, ctx ) ;
803
795
CONTINUE_NO_BREAKS
804
796
} ) ;
805
797
}
@@ -808,7 +800,7 @@ impl<'db> SemanticsImpl<'db> {
808
800
pub fn descend_into_macros ( & self , token : SyntaxToken ) -> SmallVec < [ SyntaxToken ; 1 ] > {
809
801
let mut res = smallvec ! [ ] ;
810
802
if let Ok ( token) = self . wrap_token_infile ( token. clone ( ) ) . into_real_file ( ) {
811
- self . descend_into_macros_impl ( token, & mut |t| {
803
+ self . descend_into_macros_impl ( token, & mut |t, _ctx | {
812
804
res. push ( t. value ) ;
813
805
CONTINUE_NO_BREAKS
814
806
} ) ;
@@ -819,10 +811,27 @@ impl<'db> SemanticsImpl<'db> {
819
811
res
820
812
}
821
813
814
+ pub fn descend_into_macros_no_opaque ( & self , token : SyntaxToken ) -> SmallVec < [ SyntaxToken ; 1 ] > {
815
+ let mut res = smallvec ! [ ] ;
816
+ if let Ok ( token) = self . wrap_token_infile ( token. clone ( ) ) . into_real_file ( ) {
817
+ self . descend_into_macros_impl ( token, & mut |t, ctx| {
818
+ if !ctx. is_opaque ( self . db . upcast ( ) ) {
819
+ // Don't descend into opaque contexts
820
+ res. push ( t. value ) ;
821
+ }
822
+ CONTINUE_NO_BREAKS
823
+ } ) ;
824
+ }
825
+ if res. is_empty ( ) {
826
+ res. push ( token) ;
827
+ }
828
+ res
829
+ }
830
+
822
831
pub fn descend_into_macros_breakable < T > (
823
832
& self ,
824
833
token : InRealFile < SyntaxToken > ,
825
- mut cb : impl FnMut ( InFile < SyntaxToken > ) -> ControlFlow < T > ,
834
+ mut cb : impl FnMut ( InFile < SyntaxToken > , SyntaxContextId ) -> ControlFlow < T > ,
826
835
) -> Option < T > {
827
836
self . descend_into_macros_impl ( token. clone ( ) , & mut cb)
828
837
}
@@ -834,10 +843,12 @@ impl<'db> SemanticsImpl<'db> {
834
843
let text = token. text ( ) ;
835
844
let kind = token. kind ( ) ;
836
845
837
- self . descend_into_macros_cb ( token. clone ( ) , |InFile { value, file_id : _ } | {
846
+ self . descend_into_macros_cb ( token. clone ( ) , |InFile { value, file_id : _ } , ctx | {
838
847
let mapped_kind = value. kind ( ) ;
839
848
let any_ident_match = || kind. is_any_identifier ( ) && value. kind ( ) . is_any_identifier ( ) ;
840
- let matches = ( kind == mapped_kind || any_ident_match ( ) ) && text == value. text ( ) ;
849
+ let matches = ( kind == mapped_kind || any_ident_match ( ) )
850
+ && text == value. text ( )
851
+ && !ctx. is_opaque ( self . db . upcast ( ) ) ;
841
852
if matches {
842
853
r. push ( value) ;
843
854
}
@@ -854,17 +865,21 @@ impl<'db> SemanticsImpl<'db> {
854
865
let text = token. text ( ) ;
855
866
let kind = token. kind ( ) ;
856
867
if let Ok ( token) = self . wrap_token_infile ( token. clone ( ) ) . into_real_file ( ) {
857
- self . descend_into_macros_breakable ( token. clone ( ) , |InFile { value, file_id : _ } | {
858
- let mapped_kind = value. kind ( ) ;
859
- let any_ident_match =
860
- || kind. is_any_identifier ( ) && value. kind ( ) . is_any_identifier ( ) ;
861
- let matches = ( kind == mapped_kind || any_ident_match ( ) ) && text == value. text ( ) ;
862
- if matches {
863
- ControlFlow :: Break ( value)
864
- } else {
865
- ControlFlow :: Continue ( ( ) )
866
- }
867
- } )
868
+ self . descend_into_macros_breakable (
869
+ token. clone ( ) ,
870
+ |InFile { value, file_id : _ } , _ctx| {
871
+ let mapped_kind = value. kind ( ) ;
872
+ let any_ident_match =
873
+ || kind. is_any_identifier ( ) && value. kind ( ) . is_any_identifier ( ) ;
874
+ let matches =
875
+ ( kind == mapped_kind || any_ident_match ( ) ) && text == value. text ( ) ;
876
+ if matches {
877
+ ControlFlow :: Break ( value)
878
+ } else {
879
+ ControlFlow :: Continue ( ( ) )
880
+ }
881
+ } ,
882
+ )
868
883
} else {
869
884
None
870
885
}
@@ -874,7 +889,7 @@ impl<'db> SemanticsImpl<'db> {
874
889
fn descend_into_macros_impl < T > (
875
890
& self ,
876
891
InRealFile { value : token, file_id } : InRealFile < SyntaxToken > ,
877
- f : & mut dyn FnMut ( InFile < SyntaxToken > ) -> ControlFlow < T > ,
892
+ f : & mut dyn FnMut ( InFile < SyntaxToken > , SyntaxContextId ) -> ControlFlow < T > ,
878
893
) -> Option < T > {
879
894
let _p = tracing:: info_span!( "descend_into_macros_impl" ) . entered ( ) ;
880
895
let ( sa, span, file_id) = token
@@ -898,7 +913,8 @@ impl<'db> SemanticsImpl<'db> {
898
913
// These are tracked to know which macro calls we still have to look into
899
914
// the tokens themselves aren't that interesting as the span that is being used to map
900
915
// things down never changes.
901
- let mut stack: Vec < ( _ , SmallVec < [ _ ; 2 ] > ) > = vec ! [ ( file_id, smallvec![ token] ) ] ;
916
+ let mut stack: Vec < ( _ , SmallVec < [ _ ; 2 ] > ) > =
917
+ vec ! [ ( file_id, smallvec![ ( token, SyntaxContextId :: ROOT ) ] ) ] ;
902
918
903
919
// Process the expansion of a call, pushing all tokens with our span in the expansion back onto our stack
904
920
let process_expansion_for_token = |stack : & mut Vec < _ > , macro_file| {
@@ -921,11 +937,11 @@ impl<'db> SemanticsImpl<'db> {
921
937
// Filters out all tokens that contain the given range (usually the macro call), any such
922
938
// token is redundant as the corresponding macro call has already been processed
923
939
let filter_duplicates = |tokens : & mut SmallVec < _ > , range : TextRange | {
924
- tokens. retain ( |t : & mut SyntaxToken | !range. contains_range ( t. text_range ( ) ) )
940
+ tokens. retain ( |( t , _ ) : & mut ( SyntaxToken , _ ) | !range. contains_range ( t. text_range ( ) ) )
925
941
} ;
926
942
927
943
while let Some ( ( expansion, ref mut tokens) ) = stack. pop ( ) {
928
- while let Some ( token) = tokens. pop ( ) {
944
+ while let Some ( ( token, ctx ) ) = tokens. pop ( ) {
929
945
let was_not_remapped = ( || {
930
946
// First expand into attribute invocations
931
947
let containing_attribute_macro_call = self . with_ctx ( |ctx| {
@@ -1036,7 +1052,7 @@ impl<'db> SemanticsImpl<'db> {
1036
1052
let text_range = attr. syntax ( ) . text_range ( ) ;
1037
1053
// remove any other token in this macro input, all their mappings are the
1038
1054
// same as this
1039
- tokens. retain ( |t | {
1055
+ tokens. retain ( |( t , _ ) | {
1040
1056
!text_range. contains_range ( t. text_range ( ) )
1041
1057
} ) ;
1042
1058
return process_expansion_for_token (
@@ -1093,7 +1109,7 @@ impl<'db> SemanticsImpl<'db> {
1093
1109
. is_none ( ) ;
1094
1110
1095
1111
if was_not_remapped {
1096
- if let ControlFlow :: Break ( b) = f ( InFile :: new ( expansion, token) ) {
1112
+ if let ControlFlow :: Break ( b) = f ( InFile :: new ( expansion, token) , ctx ) {
1097
1113
return Some ( b) ;
1098
1114
}
1099
1115
}
0 commit comments