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

[SR-14381] @objc & @objcMembers attributes break compilation on Windows #56739

Open
swift-ci opened this issue Mar 21, 2021 · 13 comments
Open

[SR-14381] @objc & @objcMembers attributes break compilation on Windows #56739

swift-ci opened this issue Mar 21, 2021 · 13 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself Windows Platform: Windows

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-14381
Radar None
Original Reporter Eugene Gubin (JIRA User)
Type Bug

Attachment: Download

Environment

Windows 10, swift-DEVELOPMENT-SNAPSHOT-2021-03-02-a-windows10

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, Windows
Assignee None
Priority Medium

md5: 3bc38c5bc812b76bec20dd2017e83d57

is blocked by:

  • SR-14575 Frameworks built from Swift packages lack a Headers folder

Issue Description:

Both @objc & @objcMembers attributes break compilation on Windows

Steps to reproduce: download the attachment, unpack and build.

Result:

ObjCAttributeBug.swift:3:2: error: Objective-C interoperability is disabled
@objc @objcMembers class MyClass: NSObject {
~^~~~~
@typesanitizer
Copy link

You can pass the compiler flags -Xfrontend -enable-objc-interop to get this to work. @compnerd points out that using ObjC interop adds some overhead, which is why it is off by default on non-Darwin platforms.

@compnerd
Copy link
Collaborator

This is expected, and dare I say, desired behavior. The default on non-Apple targets is that the ObjC interop is disabled. You would need to provide your own build of an ABI compatible ObjC runtime if you wish to use the ObjC interop. You can enable it with the -enable-objc-interop flag to the frontend. There are runtime overheads for the interop as well, due to the bridging of types. Note that you cannot combine build with different flags, so you would also need to do a custom runtime build as the object layout is impacted.

@swift-ci
Copy link
Collaborator Author

Comment by Eugene Gubin (JIRA)

I was told it's a bug 🙂 Details: https://forums.swift.org/t/objc-attribute-windows/46787

@compnerd
Copy link
Collaborator

I don't consider this a bug, it is intentional. Objective-C interop is non-trivial, and a massive undertaking.

@swift-ci
Copy link
Collaborator Author

swift-ci commented Apr 3, 2021

Comment by Eugene Gubin (JIRA)

@compnerd Sorry, when I said `bug` I mean what `@objc` should be just ignored on Windows since Objective-C runtime is not supported there. One can not use conditional defines to turn these annotations off. It breaks declaration.

```

#if os(Darwin)

@objc

#end

class MyClass: NSObject { }

```

@compnerd
Copy link
Collaborator

compnerd commented Apr 8, 2021

Eugene Gubin (JIRA User) - I think that is the confusion. The runtime is not unsupported, it is unavailable by default. If you have a build of a compatible ObjC runtime, you can enable the ObjC interop via the -enable-objc-interop flag. The original bring up work used a fork of the ObjC runtime that I cannot provide to actually test the ObjC interop 🙂

@swift-ci
Copy link
Collaborator Author

Comment by Eugene Gubin (JIRA)

@compnerd, thanks for clarification! But what to do with these @objc annotations in cross-platform code? As shown in the example above it could force you to repeat an entire declaration. I think it would be good to have a way to ignore these annotations on platforms there ObjC runtime is not available.

@compnerd
Copy link
Collaborator

Changes like that require an evolution proposal, along with an implementation. For @objc sure you could control that via -objc-interop but not all attributes have a corresponding flag. I would suggest that the way to handle this is to extend the support for `#if` to guard the attributes.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@smallscript
Copy link

It is a PITA to when trying to cross check same code on Windows and OSX. :-)

@HeMet
Copy link

HeMet commented Feb 17, 2023

SE-0367 should fix the issue.

@oliviermartin
Copy link

I have the issue I tried:

#if hasAttribute(objc)
@objc
#endif

... but as I would expect, I have still got the same error.

I had to use:

#if canImport(ObjectiveC)
@objc
#endif

which is quite verbose in the code when you go from this easily readable code:

import Foundation

@objc public class Hello: NSObject {
    @objc public func say() {
        print("Hello from Swift!")
    }
}

to this one:

import Foundation

#if canImport(ObjectiveC)
@objc
#endif
public class Hello: NSObject {
    #if canImport(ObjectiveC)
    @objc
    #endif
    public func say() {
        print("Hello from Swift!")
    }
}

An alternative would be to use @objcMembers - but there is a cost to it https://docs.swift.org/swift-book/documentation/the-swift-programming-language/attributes/#objcMembers.
Another alternative would be to be able to define our own custom attribute a bit like Python decorator: https://realpython.com/primer-on-python-decorators/ - but its another topic.

@tbkka
Copy link
Contributor

tbkka commented Apr 18, 2024

I can see where people would want to be able to write Swift frameworks in such a way that on ObjC-supporting platforms, the types would be available from ObjC. And yes, having @objc be ignored on non-ObjC-supporting platforms would make this easier.

As @compnerd pointed out above, however, this would be a change to the existing language behavior. As such, we cannot make such a change without first discussing it on the Swift forums and having a Swift Evolution proposal reviewed by the Swift Language Steering Group. For a change like this, the proposal would not need to be very involved, but we cannot make such a change without going through this process, which allows people who may have other use cases than yours to debate what the full impact would be.

If you wish to pursue doing this, the process is open to anyone who wants to participate. I'd be happy to give you pointers on how to proceed.

@compnerd
Copy link
Collaborator

Just to mention, #if canImport(ObjectiveC) would be incorrect as if the module is available, it will always return true. You should use #if _runtime(_ObjC) instead to ensure that ObjC interop is enabled rather than whether the ObjectiveC module is available.

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. compiler The Swift compiler in itself Windows Platform: Windows
Projects
None yet
Development

No branches or pull requests

7 participants