@@ -24,6 +24,7 @@ use hir_expand::{
2424 builtin:: { BuiltinFnLikeExpander , EagerExpander } ,
2525 db:: ExpandDatabase ,
2626 files:: InRealFile ,
27+ hygiene:: SyntaxContextExt as _,
2728 inert_attr_macro:: find_builtin_attr_idx,
2829 name:: AsName ,
2930 FileRange , InMacroFile , MacroCallId , MacroFileId , MacroFileIdExt ,
@@ -32,7 +33,7 @@ use intern::Symbol;
3233use itertools:: Itertools ;
3334use rustc_hash:: { FxHashMap , FxHashSet } ;
3435use smallvec:: { smallvec, SmallVec } ;
35- use span:: { EditionedFileId , FileId , HirFileIdRepr } ;
36+ use span:: { EditionedFileId , FileId , HirFileIdRepr , SyntaxContextId } ;
3637use stdx:: TupleExt ;
3738use syntax:: {
3839 algo:: skip_trivia_token,
@@ -608,7 +609,7 @@ impl<'db> SemanticsImpl<'db> {
608609 let quote = string. open_quote_text_range ( ) ?;
609610
610611 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, _ | {
612613 ( || {
613614 let token = token. value ;
614615 let string = ast:: String :: cast ( token) ?;
@@ -655,7 +656,7 @@ impl<'db> SemanticsImpl<'db> {
655656 let original_string = ast:: String :: cast ( original_token. clone ( ) ) ?;
656657 let original_token = self . wrap_token_infile ( original_token) . into_real_file ( ) . ok ( ) ?;
657658 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, _ | {
659660 ( || {
660661 let token = token. value ;
661662 self . resolve_offset_in_format_args (
@@ -718,7 +719,7 @@ impl<'db> SemanticsImpl<'db> {
718719 // node is just the token, so descend the token
719720 self . descend_into_macros_impl (
720721 InRealFile :: new ( file_id, first) ,
721- & mut |InFile { value, .. } | {
722+ & mut |InFile { value, .. } , _ctx | {
722723 if let Some ( node) = value
723724 . parent_ancestors ( )
724725 . take_while ( |it| it. text_range ( ) == value. text_range ( ) )
@@ -732,15 +733,15 @@ impl<'db> SemanticsImpl<'db> {
732733 } else {
733734 // Descend first and last token, then zip them to look for the node they belong to
734735 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 | {
736737 scratch. push ( token) ;
737738 CONTINUE_NO_BREAKS
738739 } ) ;
739740
740741 let mut scratch = scratch. into_iter ( ) ;
741742 self . descend_into_macros_impl (
742743 InRealFile :: new ( file_id, last) ,
743- & mut |InFile { value : last, file_id : last_fid } | {
744+ & mut |InFile { value : last, file_id : last_fid } , _ctx | {
744745 if let Some ( InFile { value : first, file_id : first_fid } ) = scratch. next ( ) {
745746 if first_fid == last_fid {
746747 if let Some ( p) = first. parent ( ) {
@@ -763,7 +764,9 @@ impl<'db> SemanticsImpl<'db> {
763764 res
764765 }
765766
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 {
767770 token. parent_ancestors ( ) . any ( |ancestor| {
768771 if ast:: MacroCall :: can_cast ( ancestor. kind ( ) ) {
769772 return true ;
@@ -781,25 +784,14 @@ impl<'db> SemanticsImpl<'db> {
781784 } )
782785 }
783786
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-
795787 pub fn descend_into_macros_cb (
796788 & self ,
797789 token : SyntaxToken ,
798- mut cb : impl FnMut ( InFile < SyntaxToken > ) ,
790+ mut cb : impl FnMut ( InFile < SyntaxToken > , SyntaxContextId ) ,
799791 ) {
800792 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 ) ;
803795 CONTINUE_NO_BREAKS
804796 } ) ;
805797 }
@@ -808,7 +800,7 @@ impl<'db> SemanticsImpl<'db> {
808800 pub fn descend_into_macros ( & self , token : SyntaxToken ) -> SmallVec < [ SyntaxToken ; 1 ] > {
809801 let mut res = smallvec ! [ ] ;
810802 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 | {
812804 res. push ( t. value ) ;
813805 CONTINUE_NO_BREAKS
814806 } ) ;
@@ -819,10 +811,27 @@ impl<'db> SemanticsImpl<'db> {
819811 res
820812 }
821813
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+
822831 pub fn descend_into_macros_breakable < T > (
823832 & self ,
824833 token : InRealFile < SyntaxToken > ,
825- mut cb : impl FnMut ( InFile < SyntaxToken > ) -> ControlFlow < T > ,
834+ mut cb : impl FnMut ( InFile < SyntaxToken > , SyntaxContextId ) -> ControlFlow < T > ,
826835 ) -> Option < T > {
827836 self . descend_into_macros_impl ( token. clone ( ) , & mut cb)
828837 }
@@ -834,10 +843,12 @@ impl<'db> SemanticsImpl<'db> {
834843 let text = token. text ( ) ;
835844 let kind = token. kind ( ) ;
836845
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 | {
838847 let mapped_kind = value. kind ( ) ;
839848 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 ( ) ) ;
841852 if matches {
842853 r. push ( value) ;
843854 }
@@ -854,17 +865,21 @@ impl<'db> SemanticsImpl<'db> {
854865 let text = token. text ( ) ;
855866 let kind = token. kind ( ) ;
856867 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+ )
868883 } else {
869884 None
870885 }
@@ -874,7 +889,7 @@ impl<'db> SemanticsImpl<'db> {
874889 fn descend_into_macros_impl < T > (
875890 & self ,
876891 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 > ,
878893 ) -> Option < T > {
879894 let _p = tracing:: info_span!( "descend_into_macros_impl" ) . entered ( ) ;
880895 let ( sa, span, file_id) = token
@@ -898,7 +913,8 @@ impl<'db> SemanticsImpl<'db> {
898913 // These are tracked to know which macro calls we still have to look into
899914 // the tokens themselves aren't that interesting as the span that is being used to map
900915 // 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 ) ] ) ] ;
902918
903919 // Process the expansion of a call, pushing all tokens with our span in the expansion back onto our stack
904920 let process_expansion_for_token = |stack : & mut Vec < _ > , macro_file| {
@@ -921,11 +937,11 @@ impl<'db> SemanticsImpl<'db> {
921937 // Filters out all tokens that contain the given range (usually the macro call), any such
922938 // token is redundant as the corresponding macro call has already been processed
923939 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 ( ) ) )
925941 } ;
926942
927943 while let Some ( ( expansion, ref mut tokens) ) = stack. pop ( ) {
928- while let Some ( token) = tokens. pop ( ) {
944+ while let Some ( ( token, ctx ) ) = tokens. pop ( ) {
929945 let was_not_remapped = ( || {
930946 // First expand into attribute invocations
931947 let containing_attribute_macro_call = self . with_ctx ( |ctx| {
@@ -1036,7 +1052,7 @@ impl<'db> SemanticsImpl<'db> {
10361052 let text_range = attr. syntax ( ) . text_range ( ) ;
10371053 // remove any other token in this macro input, all their mappings are the
10381054 // same as this
1039- tokens. retain ( |t | {
1055+ tokens. retain ( |( t , _ ) | {
10401056 !text_range. contains_range ( t. text_range ( ) )
10411057 } ) ;
10421058 return process_expansion_for_token (
@@ -1093,7 +1109,7 @@ impl<'db> SemanticsImpl<'db> {
10931109 . is_none ( ) ;
10941110
10951111 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 ) {
10971113 return Some ( b) ;
10981114 }
10991115 }
0 commit comments