Unable to extend types generated by macros

I thought that SE-0389 pretty clearly states that macros can introduce symbols which can then be used in other parts of the original source code (subject to certain restrictions). However, I am unable to extend a type that was introduced by a macro:

@Foo
struct Test { }

extension Bar { } // Error: Cannot find type 'Bar' in scope
                  // Error: Circular reference
@attached(peer, names: named(Bar))
public macro Foo () = #externalMacro(module: "TestMacros", type: "FooMacro")
public struct FooMacro: PeerMacro {
    public static func expansion(
        of node: AttributeSyntax,
        providingPeersOf declaration: some DeclSyntaxProtocol,
        in context: some MacroExpansionContext
    ) throws -> [DeclSyntax] {
        [
            """
            struct Bar { }
            """
        ]
    }   
}

Is this a bug? Am I misunderstanding the capabilities as described in this section of the accepted proposal document?

I believe you're seeing this bug:

The only workaround I know of is to move the extension into another file.

It's definitely an easy bug to encounter, and after introducing macros to some packages we distribute, many folks have encountered the issue and reported it to us, so hopefully it will be triaged and fixed in Swift soon.

4 Likes

After introducing macros to a few of our libraries this past week we've already had a dozen reports of this issue. Would be nice to get some eyes on it. We're having to document the Swift bug as a gotcha in all our libraries using macros.

3 Likes

~It seems that this issue has been fixed in Xcode 15.1 Beta 3 .~

I'm so sorry for my misleading.

The issue I had was not related to @Observable, but rather with the custom member macro I created.
The message I encountered was as follows, and it was resolved in Xcode 15.1 Beta 3.

Circular reference expanding member attribute macros on 'Something'

1 Like

We're still regularly getting questions about this when folks adopt the macros we've introduced to our libraries. Any chance we can have a core team member acknowledge the issue, which has been open since the week of WWDC23 and still hasn't been triaged?

1 Like

The folks working on the implementation of macros are aware of and investigating the circularity issues with extensions. There are numerous reports of the issue in addition to the GitHub issue linked upthread. We had fixed some of them in Swift 5.9 (e.g. [Macros] Use source locations to determine whether to suppress macro expansions. by hborla · Pull Request #66532 · apple/swift · GitHub and https://github.com/apple/swift/pull/67642 each fixed slightly different circularity issues that could result in the same error). The circularity errors are manifestations of slightly different circularity issues in the type checker, so the original fixes from 5.9 did not eliminate the error entirely.

EDIT: It's worth noting that [5.9] Eliminate Observable circular reference errors via lazier TypeRefinementContext building by DougGregor · Pull Request #67689 · apple/swift · GitHub was too late for the release/5.9.0 branch, meaning it is not included in Swift 5.9.0 (which is in Xcode 15.0). But as I mentioned above, the various reports are manifestations of slightly different issues, which is why some folks are reporting on the GitHub issue that their specific case is fixed in Xcode 15.1 Beta 3.

6 Likes

Thanks for providing more context and visibility into the scope of the issue!