@@ -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 ,
2930FileRange , 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> {
608609let quote = string. open_quote_text_range ( ) ?;
609610
610611let 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( || {
613614let token = token. value ;
614615let string = ast:: String :: cast ( token) ?;
@@ -655,7 +656,7 @@ impl<'db> SemanticsImpl<'db> {
655656let original_string = ast:: String :: cast ( original_token. clone ( ) ) ?;
656657let original_token = self . wrap_token_infile ( original_token) . into_real_file ( ) . ok ( ) ?;
657658let 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( || {
660661let token = token. value ;
661662self . resolve_offset_in_format_args (
@@ -718,7 +719,7 @@ impl<'db> SemanticsImpl<'db> {
718719// node is just the token, so descend the token
719720self . descend_into_macros_impl (
720721InRealFile :: new ( file_id, first) ,
721- & mut |InFile { value, .. } | {
722+ & mut |InFile { value, .. } , _ctx | {
722723if 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
734735let 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) ;
737738CONTINUE_NO_BREAKS
738739} ) ;
739740
740741let mut scratch = scratch. into_iter ( ) ;
741742self . descend_into_macros_impl (
742743InRealFile :: new ( file_id, last) ,
743- & mut |InFile { value : last, file_id : last_fid } | {
744+ & mut |InFile { value : last, file_id : last_fid } , _ctx | {
744745if let Some ( InFile { value : first, file_id : first_fid } ) = scratch. next ( ) {
745746if first_fid == last_fid {
746747if 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| {
768771if ast:: MacroCall :: can_cast ( ancestor. kind ( ) ) {
769772return 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-
795787pub fn descend_into_macros_cb (
796788& self ,
797789token : SyntaxToken ,
798- mut cb : impl FnMut ( InFile < SyntaxToken > ) ,
790+ mut cb : impl FnMut ( InFile < SyntaxToken > , SyntaxContextId ) ,
799791) {
800792if 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 ) ;
803795CONTINUE_NO_BREAKS
804796} ) ;
805797}
@@ -808,7 +800,7 @@ impl<'db> SemanticsImpl<'db> {
808800pub fn descend_into_macros ( & self , token : SyntaxToken ) -> SmallVec < [ SyntaxToken ; 1 ] > {
809801let mut res = smallvec ! [ ] ;
810802if 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 ) ;
813805CONTINUE_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+
822831pub fn descend_into_macros_breakable < T > (
823832& self ,
824833token : InRealFile < SyntaxToken > ,
825- mut cb : impl FnMut ( InFile < SyntaxToken > ) -> ControlFlow < T > ,
834+ mut cb : impl FnMut ( InFile < SyntaxToken > , SyntaxContextId ) -> ControlFlow < T > ,
826835) -> Option < T > {
827836self . descend_into_macros_impl ( token. clone ( ) , & mut cb)
828837}
@@ -834,10 +843,12 @@ impl<'db> SemanticsImpl<'db> {
834843let text = token. text ( ) ;
835844let 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 | {
838847let mapped_kind = value. kind ( ) ;
839848let 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 ( ) ) ;
841852if matches {
842853 r. push ( value) ;
843854}
@@ -854,17 +865,21 @@ impl<'db> SemanticsImpl<'db> {
854865let text = token. text ( ) ;
855866let kind = token. kind ( ) ;
856867if 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 {
869884None
870885}
@@ -874,7 +889,7 @@ impl<'db> SemanticsImpl<'db> {
874889fn descend_into_macros_impl < T > (
875890& self ,
876891InRealFile { 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 > {
879894let _p = tracing:: info_span!( "descend_into_macros_impl" ) . entered ( ) ;
880895let ( 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
904920let 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
923939let 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
927943while let Some ( ( expansion, ref mut tokens) ) = stack. pop ( ) {
928- while let Some ( token) = tokens. pop ( ) {
944+ while let Some ( ( token, ctx ) ) = tokens. pop ( ) {
929945let was_not_remapped = ( || {
930946// First expand into attribute invocations
931947let containing_attribute_macro_call = self . with_ctx ( |ctx| {
@@ -1036,7 +1052,7 @@ impl<'db> SemanticsImpl<'db> {
10361052let 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} ) ;
10421058return process_expansion_for_token (
@@ -1093,7 +1109,7 @@ impl<'db> SemanticsImpl<'db> {
10931109. is_none ( ) ;
10941110
10951111if 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 ) {
10971113return Some ( b) ;
10981114}
10991115}
0 commit comments