Macro unable to add Codable conformance if type has only private init (though the expanded code compiles)

I have an extension macro which adds Codable conformance (and other protocols, though they don't matter). The macro expands the code:

@Foo
public struct Name {
    private var value: String
}

to:

public struct Name {
    private var value: String
}

extension Name: Codable {
}

The expanded code compiles, but the original code doesn't. The error:

'_value' is inaccessible due to 'private' protection level

If I add an internal (or pubic) init(), the error is gone. I wonder if anyone observed the issue? Is it a bug?

I ran into the issue in my app code where I use Foo macro, MemberInit macro, and property wrapper together, like the following:

@Foo
@MemberInit
public struct Name {
    @SomePW var value: String
}

From what I read, during macro expansion Foo can't see the public init() generated by MemberInit. I suspect that somehow caused the issue, though I don't understand why, because from my understanding Codable doesn't depends on init() provided by other code. The fact that transformed code compiles also proves it.

Foo macro code (simplified version):
public enum FooMacro: ExtensionMacro {
    public static func expansion(
        of node: AttributeSyntax,
        attachedTo declaration: some DeclGroupSyntax,
        providingExtensionsOf type: some TypeSyntaxProtocol,
        conformingTo protocols: [TypeSyntax],
        in context: some MacroExpansionContext
    ) throws -> [ExtensionDeclSyntax] {
        let extensionDecl = try ExtensionDeclSyntax(
            """
            extension \(type.trimmed): Codables {
            }
            """
        )

        return [extensionDecl]
    }
}

(BTW, I’m not sure if it’s just me, but this is not the first time I run into weird issues like this - expanded code compiles but original code doesn’t. Fortunately this time I am able to narrow it down).

UPDATE: I submitted bug #70086

1 Like

I find it disconcerting that it's even possible for macro-expanded code to behave differently from having the exact same code in the source file.