Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ExtensionMacro extension methods are always (and incorrectly) fileprivate access only #69073

Closed
daniel-hall opened this issue Oct 9, 2023 · 6 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. swift macro Feature → declarations: Swift `macro` declarations

Comments

@daniel-hall
Copy link

Description

When using an attached ExtensionMacro to add an extension method to a protocol, that extension method is only visible in the file where the Macro attribute is applied, even when it should be internally visible by default (or following other explicit access control levels).

If I have all this in the same file it works.

import MacroLibrary

@FooExtension    // <--- apply the macro to generate default `Foo` property and `printFoo()` method
protocol Foo {
  var foo: String { get }
}

extension String: Foo { } 

"Test".printFoo()   // prints "foo"

But if I have the last line in a separate file, the extension method isn't visible even if I generated it specifically with an internal modifier

// Some other file that is different from the above
"Test".printFoo()  // <---- Error: "Value of type ''String" has no member 'printFoo'"

I suspect existing test cases for attached ExtensionMacros may have trouble catching this issue since the extension method is called in the same test file where the macro is applied (therefore never triggering the visibility issue). I'm attached a minimal example package here to demonstrate.

MyMacro.zip

Steps to reproduce

  • Create an attached ExtensionMacro that adds an extension method to the protocol declaration it is attached to
  • Annotate a protocol with the ExtensionMacro in some client code. Note that the extension method can be called in the same file
  • In another file in the client code, try to call the same extension method

Expected behavior

I expect the extension method to be visible, autocomplete-suggested, and called at runtime. However, the compiler says the method doesn't exist.

Screenshot 2023-10-09 at 11 01 56 AM

Environment

  • Swift compiler version info : swift-driver version: 1.87.2 Apple Swift version 5.9 (swiftlang-5.9.2.1.6 clang-1500.1.0.1.1)
  • Xcode version info: Xcode 15.1 Build version 15C5028h
  • Deployment target: iOS 17
@daniel-hall daniel-hall added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels Oct 9, 2023
@ahoppen ahoppen added swift macro Feature → declarations: Swift `macro` declarations and removed triage needed This issue needs more specific labels labels Oct 9, 2023
@Uncommon
Copy link

Uncommon commented Oct 24, 2023

It looks like I'm running into this as well.

My macro takes this:

@ThrowingImplementation(MyError.unimplemented)
protocol SomeAPI {
  func doSomething() throws
}

and expands to this:

protocol ThrowingSomeAPI: SomeAPI {
  // func doSomething() throws
}
extension ThrowingSomeAPI {
  func doSomething() throws { throw MyError.unimplemented }
}

so I should be able to do this, since the macro provides a default implementation for every function:

struct Thing: ThrowingSomeAPI {}

but it only works in the same file. If I put it in a different file, the compiler says it does not conform. Adding the macro's expansion manually eliminates the error.

I tried modifying my macro to explicitly mark the extension or its members as public/internal but it didn't help.

@Uncommon
Copy link

Here is my macro. If you try to build ThrowingImplementationClient, you get an error in other.swift because the extension methods aren't visible.

ThrowingImplementation.zip

@billzhou0223
Copy link

Ran into the exact same issue where the methods added by extension macro cannot be seen from another file.

@hborla
Copy link
Member

hborla commented Feb 23, 2024

I suspect this was fixed by the second commit in #71717, but I haven't tested this theory yet

@xedin
Copy link
Contributor

xedin commented Feb 24, 2024

I tested with main branch compiler and project indeed builds successfully with #71717. Can you use swift main branch snapshot for swift.org once it's older than Feb 20 to verify.

@xedin xedin closed this as completed Feb 24, 2024
@xedin
Copy link
Contributor

xedin commented Feb 24, 2024

ThrowingImplementation build successfully as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. swift macro Feature → declarations: Swift `macro` declarations
Projects
None yet
Development

No branches or pull requests

6 participants