@@ -485,10 +485,14 @@ private class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
485485 // Note that 'MacroExpansionExpr'/'MacroExpansionExprDecl' at code item
486486 // position are handled by 'visit(_:CodeBlockItemListSyntax)'.
487487 // Only expression expansions inside other syntax nodes is handled here.
488- if let expanded = expandExpr ( node: node) {
488+ switch expandExpr ( node: node) {
489+ case . success( let expanded) :
489490 return Syntax ( visit ( expanded) )
491+ case . failure:
492+ return Syntax ( node)
493+ case . notAMacro:
494+ break
490495 }
491-
492496 if let declSyntax = node. as ( DeclSyntax . self) ,
493497 let attributedNode = node. asProtocol ( WithAttributesSyntax . self) ,
494498 !attributedNode. attributes. isEmpty
@@ -510,16 +514,21 @@ private class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
510514 var newItems : [ CodeBlockItemSyntax ] = [ ]
511515 func addResult( _ node: CodeBlockItemSyntax ) {
512516 // Expand freestanding macro.
513- if let expanded = expandCodeBlockItem ( node: node) {
517+ switch expandCodeBlockItem ( node: node) {
518+ case . success( let expanded) :
514519 for item in expanded {
515520 addResult ( item)
516521 }
517522 return
523+ case . failure:
524+ // Expanding the macro threw an error. We don't have an expanded source.
525+ // Retain the macro node as-is.
526+ newItems. append ( node)
527+ case . notAMacro:
528+ // Recurse on the child node
529+ newItems. append ( visit ( node) )
518530 }
519531
520- // Recurse on the child node
521- newItems. append ( visit ( node) )
522-
523532 // Expand any peer macro on this item.
524533 if case . decl( let decl) = node. item {
525534 for peer in expandCodeBlockPeers ( of: decl) {
@@ -552,16 +561,19 @@ private class MacroApplication<Context: MacroExpansionContext>: SyntaxRewriter {
552561
553562 func addResult( _ node: MemberBlockItemSyntax ) {
554563 // Expand freestanding macro.
555- if let expanded = expandMemberDecl ( node: node) {
564+ switch expandMemberDecl ( node: node) {
565+ case . success( let expanded) :
556566 for item in expanded {
557567 addResult ( item)
558568 }
559569 return
570+ case . failure:
571+ newItems. append ( node)
572+ case . notAMacro:
573+ // Recurse on the child node.
574+ newItems. append ( visit ( node) )
560575 }
561576
562- // Recurse on the child node.
563- newItems. append ( visit ( node) )
564-
565577 // Expand any peer macro on this member.
566578 for peer in expandMemberDeclPeers ( of: node. decl) {
567579 addResult ( peer)
@@ -842,20 +854,36 @@ extension MacroApplication {
842854// MARK: Freestanding macro expansion
843855
844856extension MacroApplication {
857+ enum MacroExpansionResult < ResultType> {
858+ /// Expansion of the macro succeeded.
859+ case success( ResultType )
860+
861+ /// Macro system found the macro to expand but running the expansion threw
862+ /// an error and thus no expansion result exists.
863+ case failure
864+
865+ /// The node that should be expanded was not a macro known to the macro system.
866+ case notAMacro
867+ }
868+
845869 private func expandFreestandingMacro< ExpandedMacroType: SyntaxProtocol > (
846870 _ node: ( any FreestandingMacroExpansionSyntax ) ? ,
847871 expandMacro: ( _ macro: Macro . Type , _ node: any FreestandingMacroExpansionSyntax ) throws -> ExpandedMacroType ?
848- ) -> ExpandedMacroType ? {
872+ ) -> MacroExpansionResult < ExpandedMacroType > {
849873 guard let node,
850874 let macro = macroSystem. lookup ( node. macro. text)
851875 else {
852- return nil
876+ return . notAMacro
853877 }
854878 do {
855- return try expandMacro ( macro, node)
879+ if let expanded = try expandMacro ( macro, node) {
880+ return . success( expanded)
881+ } else {
882+ return . failure
883+ }
856884 } catch {
857885 context. addDiagnostics ( from: error, node: node)
858- return nil
886+ return . failure
859887 }
860888 }
861889
@@ -867,7 +895,7 @@ extension MacroApplication {
867895 /// #foo
868896 /// }
869897 /// ```
870- func expandCodeBlockItem( node: CodeBlockItemSyntax ) -> CodeBlockItemListSyntax ? {
898+ func expandCodeBlockItem( node: CodeBlockItemSyntax ) -> MacroExpansionResult < CodeBlockItemListSyntax > {
871899 return expandFreestandingMacro ( node. item. asProtocol ( FreestandingMacroExpansionSyntax . self) ) { macro, node in
872900 return try expandFreestandingCodeItemList (
873901 definition: macro,
@@ -886,7 +914,7 @@ extension MacroApplication {
886914 /// #foo
887915 /// }
888916 /// ```
889- func expandMemberDecl( node: MemberBlockItemSyntax ) -> MemberBlockItemListSyntax ? {
917+ func expandMemberDecl( node: MemberBlockItemSyntax ) -> MacroExpansionResult < MemberBlockItemListSyntax > {
890918 return expandFreestandingMacro ( node. decl. as ( MacroExpansionDeclSyntax . self) ) { macro, node in
891919 return try expandFreestandingMemberDeclList (
892920 definition: macro,
@@ -904,7 +932,7 @@ extension MacroApplication {
904932 /// ```swift
905933 /// let a = #foo
906934 /// ```
907- func expandExpr( node: Syntax ) -> ExprSyntax ? {
935+ func expandExpr( node: Syntax ) -> MacroExpansionResult < ExprSyntax > {
908936 return expandFreestandingMacro ( node. as ( MacroExpansionExprSyntax . self) ) { macro, node in
909937 return try expandFreestandingExpr (
910938 definition: macro,
0 commit comments