@@ -24,7 +24,8 @@ use crate::{
2424 HirFileId , HirFileIdRepr , MacroCallId , MacroCallKind , MacroCallLoc , MacroDefId , MacroDefKind ,
2525 MacroFileId ,
2626} ;
27-
27+ /// This is just to ensure the types of smart_macro_arg and macro_arg are the same
28+ type MacroArgResult = ( Arc < tt:: Subtree > , SyntaxFixupUndoInfo , Span ) ;
2829/// Total limit on the number of tokens produced by any macro invocation.
2930///
3031/// If an invocation produces more tokens than this limit, it will not be stored in the database and
@@ -98,7 +99,13 @@ pub trait ExpandDatabase: SourceDatabase {
9899 /// Lowers syntactic macro call to a token tree representation. That's a firewall
99100 /// query, only typing in the macro call itself changes the returned
100101 /// subtree.
101- fn macro_arg ( & self , id : MacroCallId ) -> ( Arc < tt:: Subtree > , SyntaxFixupUndoInfo , Span ) ;
102+ fn macro_arg ( & self , id : MacroCallId ) -> MacroArgResult ;
103+ #[ salsa:: transparent]
104+ fn macro_arg_considering_derives (
105+ & self ,
106+ id : MacroCallId ,
107+ kind : & MacroCallKind ,
108+ ) -> MacroArgResult ;
102109 /// Fetches the expander for this macro.
103110 #[ salsa:: transparent]
104111 #[ salsa:: invoke( TokenExpander :: macro_expander) ]
@@ -144,7 +151,7 @@ pub fn expand_speculative(
144151 let span_map = RealSpanMap :: absolute ( FileId :: BOGUS ) ;
145152 let span_map = SpanMapRef :: RealSpanMap ( & span_map) ;
146153
147- let ( _, _, span) = db. macro_arg ( actual_macro_call) ;
154+ let ( _, _, span) = db. macro_arg_considering_derives ( actual_macro_call, & loc . kind ) ;
148155
149156 // Build the subtree and token mapping for the speculative args
150157 let ( mut tt, undo_info) = match loc. kind {
@@ -339,12 +346,24 @@ pub(crate) fn parse_with_map(
339346 }
340347}
341348
342- // FIXME: for derive attributes, this will return separate copies of the same structures! Though
343- // they may differ in spans due to differing call sites...
344- fn macro_arg (
349+ /// This resolves the [MacroCallId] to check if it is a derive macro if so get the [macro_arg] for the derive.
350+ /// Other wise return the [macro_arg] for the macro_call_id.
351+ ///
352+ /// This is not connected to the database so it does not cached the result. However, the inner [macro_arg] query is
353+ fn macro_arg_considering_derives (
345354 db : & dyn ExpandDatabase ,
346355 id : MacroCallId ,
347- ) -> ( Arc < tt:: Subtree > , SyntaxFixupUndoInfo , Span ) {
356+ kind : & MacroCallKind ,
357+ ) -> MacroArgResult {
358+ match kind {
359+ // Get the macro arg for the derive macro
360+ MacroCallKind :: Derive { derive_macro_id, .. } => db. macro_arg ( * derive_macro_id) ,
361+ // Normal macro arg
362+ _ => db. macro_arg ( id) ,
363+ }
364+ }
365+
366+ fn macro_arg ( db : & dyn ExpandDatabase , id : MacroCallId ) -> MacroArgResult {
348367 let loc = db. lookup_intern_macro_call ( id) ;
349368
350369 if let MacroCallLoc {
@@ -414,29 +433,30 @@ fn macro_arg(
414433 }
415434 return ( Arc :: new ( tt) , SyntaxFixupUndoInfo :: NONE , span) ;
416435 }
417- MacroCallKind :: Derive { ast_id, derive_attr_index, .. } => {
418- let node = ast_id. to_ptr ( db) . to_node ( & root) ;
419- let censor_derive_input = censor_derive_input ( derive_attr_index, & node) ;
420- let item_node = node. into ( ) ;
421- let attr_source = attr_source ( derive_attr_index, & item_node) ;
422- // FIXME: This is wrong, this should point to the path of the derive attribute`
423- let span =
424- map. span_for_range ( attr_source. as_ref ( ) . and_then ( |it| it. path ( ) ) . map_or_else (
425- || item_node. syntax ( ) . text_range ( ) ,
426- |it| it. syntax ( ) . text_range ( ) ,
427- ) ) ;
428- ( censor_derive_input, item_node, span)
436+ // MacroCallKind::Derive should not be here. As we are getting the argument for the derive macro
437+ MacroCallKind :: Derive { .. } => {
438+ unreachable ! ( "`ExpandDatabase::macro_arg` called with `MacroCallKind::Derive`" )
429439 }
430440 MacroCallKind :: Attr { ast_id, invoc_attr_index, .. } => {
431441 let node = ast_id. to_ptr ( db) . to_node ( & root) ;
432442 let attr_source = attr_source ( invoc_attr_index, & node) ;
443+
433444 let span = map. span_for_range (
434445 attr_source
435446 . as_ref ( )
436447 . and_then ( |it| it. path ( ) )
437448 . map_or_else ( || node. syntax ( ) . text_range ( ) , |it| it. syntax ( ) . text_range ( ) ) ,
438449 ) ;
439- ( attr_source. into_iter ( ) . map ( |it| it. syntax ( ) . clone ( ) . into ( ) ) . collect ( ) , node, span)
450+ // If derive attribute we need to censor the derive input
451+ if matches ! ( loc. def. kind, MacroDefKind :: BuiltInAttr ( expander, ..) if expander. is_derive( ) )
452+ && ast:: Adt :: can_cast ( node. syntax ( ) . kind ( ) )
453+ {
454+ let adt = ast:: Adt :: cast ( node. syntax ( ) . clone ( ) ) . unwrap ( ) ;
455+ let censor_derive_input = censor_derive_input ( invoc_attr_index, & adt) ;
456+ ( censor_derive_input, node, span)
457+ } else {
458+ ( attr_source. into_iter ( ) . map ( |it| it. syntax ( ) . clone ( ) . into ( ) ) . collect ( ) , node, span)
459+ }
440460 }
441461 } ;
442462
@@ -526,7 +546,8 @@ fn macro_expand(
526546 let ( ExpandResult { value : tt, err } , span) = match loc. def . kind {
527547 MacroDefKind :: ProcMacro ( ..) => return db. expand_proc_macro ( macro_call_id) . map ( CowArc :: Arc ) ,
528548 _ => {
529- let ( macro_arg, undo_info, span) = db. macro_arg ( macro_call_id) ;
549+ let ( macro_arg, undo_info, span) =
550+ db. macro_arg_considering_derives ( macro_call_id, & loc. kind ) ;
530551
531552 let arg = & * macro_arg;
532553 let res =
@@ -603,7 +624,7 @@ fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>) -> Span {
603624
604625fn expand_proc_macro ( db : & dyn ExpandDatabase , id : MacroCallId ) -> ExpandResult < Arc < tt:: Subtree > > {
605626 let loc = db. lookup_intern_macro_call ( id) ;
606- let ( macro_arg, undo_info, span) = db. macro_arg ( id) ;
627+ let ( macro_arg, undo_info, span) = db. macro_arg_considering_derives ( id, & loc . kind ) ;
607628
608629 let ( expander, ast) = match loc. def . kind {
609630 MacroDefKind :: ProcMacro ( expander, _, ast) => ( expander, ast) ,
0 commit comments