swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.04k stars 10.32k forks source link

Specific macro that works on macOS is not working with latest Linux snapshot #68345

Open MahdiBM opened 10 months ago

MahdiBM commented 10 months ago

Edit: More specific info is available in comments down below: https://github.com/apple/swift/issues/68345#issuecomment-1712458495

Description Latest Linux snapshot is supposed to have linux support, but build of DiscordBM macros PR fails in latest linux snapshot (see the logs below) The same PR works as expected in Xcode 15 beta 8.

The logs: macro-linux-failure.txt

Steps to reproduce Use what is used in the attached CI (here).

Expected behavior To work fine like on Xcode.

Environment

MahdiBM commented 10 months ago

Update: Added the logs

MaxDesiatov commented 10 months ago

IMO the issue title here is misleading, I don't see any failures related to macros per se in the build log. The build errors mention Codable synthesis, but no specific macros. If macros are involved, they might be expanding to code that's invalid on Linux, but that should be filed as an issue against packages that provide those macros, not on the Swift repository itself.

MahdiBM commented 10 months ago

So first thing to just repeat is that these all work on macOS unlike on Linux. I do believe this is a macros on Linux problem as the UnstableEnum macro does have some stuff to do with Codable. I also do think the errors might be quite misleading, but i still believe they must be something related to the macro on Linux.

MahdiBM commented 10 months ago

The macro comes with some documentation: https://github.com/DiscordBM/DiscordBM/blob/31a17d916b22d5efddd0f383d9c617b348883f36/Macros/UnstableEnumMacro/Macro.swift#L29

MaxDesiatov commented 10 months ago

So first thing to just repeat is that these all work on macOS unlike on Linux.

The fact that some code works on macOS is by no means a guarantee that it will work or even build on Linux. Each platform may need some adjustments to make arbitrary code build and run correctly. The issue should be filed against the package that implements UnstableEnum macro to add Linux support, unless you're able to show that a specific underlying macro infrastructure as specified in Swift Evolution macro proposals does not work on Linux.

MahdiBM commented 10 months ago

I understand that not every macOS thing will work on Linux. I believe the problem comes from the macro implementation on Linux and I don't think anything in the proposal notes that Linux and macOS macros will not have feature parity.

The implementation of the macro-related stuff do not use anything special that works on Linux but not macOS as far as i can tell. UnstableEnum is an internal macro of DiscordBM. I wrote the macro and i believed it's a problem in the code, i would have just fixed my code 😅

MaxDesiatov commented 10 months ago

Would you be able to attach a self-contained reproducible sample code that's smaller than the whole DiscordBM package? It should only include a specific macro that you can show builds correctly on macOS, but not on Linux. That would make diagnosing this much easier than reviewing a build log of a relatively big package that has multiple dependencies.

MahdiBM commented 10 months ago

Unfortunately I'm in a place with pretty bad internet connection. I've already disconnected 5+ times trying to file this issue in the hopes that in incomplete macros implementation doesn't reach the 5.9 release. I understand I should provide a minimal reproducible sample code and that's what i always try to do, but i don't think i'll be able to provide that this time, unfortunately. I understand if it's too much to ask to investigate this issue until i provide the sample code, although i hope otherwise as it might already be too late by the time i'm able to provide that (in 48+ hours?).

MahdiBM commented 10 months ago

Here is a repo to reproduce the inconsistency between macOS and Linux behavior: https://github.com/MahdiBM/linux-macro-issue

Try to build on macOS and Linux and you'll notice the inconsistency. It appears something is wrong in conformance-synthesizations in macros on Linux. In this case, it's an Equatable conformance.

On linux you'll see the following error using swift-5.9-nightly (swift-5.9-DEVELOPMENT-SNAPSHOT-2023-09-05-a) :

/workspaces/linux-macro-issue/Sources/Macro/Kind.swift:17:27: error: value of optional type 'Kind?' must be unwrapped to a value of type 'Kind'
        if Optional<Self>.some(.announcementThread) == .announcementThread {
                          ^
/workspaces/linux-macro-issue/Sources/Macro/Kind.swift:17:27: note: coalesce using '??' to provide a default when the optional value contains 'nil'
        if Optional<Self>.some(.announcementThread) == .announcementThread {
                          ^
                                                    ?? <#default value#>
/workspaces/linux-macro-issue/Sources/Macro/Kind.swift:17:27: note: force-unwrap using '!' to abort execution if the optional value contains 'nil'
        if Optional<Self>.some(.announcementThread) == .announcementThread {
                          ^
                                                   !
error: fatalError
MahdiBM commented 10 months ago

More news. I simplified the whole macro in the repro repo, and found out what triggers the bug. In the non-working code, i declare the macro as:

@attached(
    extension,
    conformances: RawRepresentable, Equatable, Hashable
)
macro UnstableEnum() = #externalMacro(module: "UnstableEnumMacro", type: "UnstableEnum")

This makes it not work on Linux, but work on macOS. If I change the macro declaration to this, the macro will work on both platforms:

@attached(
    extension,
    conformances: RawRepresentable
)
macro UnstableEnum() = #externalMacro(module: "UnstableEnumMacro", type: "UnstableEnum")

Basically removing Equatable and Hashable from the conformances list.

On linux it apparently doesn't synthesize a conformance if the macro claims to provide it? But on macOS it'll synthesize the conformance as if it's some normal code when an explicit conformance is not provided.

MahdiBM commented 10 months ago

Generally it seems like macros on macOS provides synthesized conformance even when the conformance is explicitly claimed by macro. Linux is probably having the correct-er behavior? If yes, I would expect some macro errors when a macro claims a protocol conformance but doesn't provide it. Though these errors might already be too late to happen on Swift 5 since 5.9 will be released soon?

MaxDesiatov commented 10 months ago

cc @DougGregor @hborla

MahdiBM commented 8 months ago

I added some comments in this issue that were supposed to be in another issue. I've removed them now to prevent confusion considering they weren't too-related to this issue.