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-14548] 5.4 Linux Toolchain no longer ignores @objc #56900

Closed
swift-ci opened this issue Apr 29, 2021 · 26 comments
Closed

[SR-14548] 5.4 Linux Toolchain no longer ignores @objc #56900

swift-ci opened this issue Apr 29, 2021 · 26 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-14548
Radar rdar://problem/77325078
Original Reporter kencarroll (JIRA User)
Type Bug
Status Closed
Resolution Done
Environment

Toolchain Ubuntu-18.04.

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug
Assignee kencarroll (JIRA)
Priority Medium

md5: 30e0bafaa0fe2efb3b254fa1b8f290b8

relates to:

  • SR-13713 SIL verification failed: result of witness_method must have correct representation for protocol

Issue Description:

The following code fails to compile with 5.4 on Linux. It compiled with 5.3.3.

      • BEGIN Code ----

import Foundation

@objc enum XY: Int

{

case x = 1

case y = 0

}

@objc class XY
{
var text = "Hello World"
}

      • END Code ------
@typesanitizer
Copy link

@swift-ci create

@swift-ci
Copy link
Collaborator Author

swift-ci commented May 3, 2021

Comment by Ken Carroll (JIRA)

I don't see the relevance of the link.

@xymus
Copy link
Contributor

xymus commented May 3, 2021

Varun created a Radar link for internal tracking.

kencarroll (JIRA User) can you tell us more about the error that you're seeing with this code? If you can attach the full compiler output it would help us to start investigating.

@swift-ci
Copy link
Collaborator Author

swift-ci commented May 4, 2021

Comment by Ken Carroll (JIRA)

@xymus Build output:

----- BEGIN swift build -v

lsb_release -r
/home/ken/swift-5.4-RELEASE-ubuntu18.04/usr/bin/swiftc -print-target-info
/home/ken/swift-5.4-RELEASE-ubuntu18.04/usr/bin/swiftc -print-target-info
/home/ken/swift-5.4-RELEASE-ubuntu18.04/usr/bin/swiftc -module-name objctest -incremental -emit-dependencies -emit-module -emit-module-path /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug/objctest.swiftmodule -output-file-map /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug/objctest.build/output-file-map.json -parse-as-library -c /home/ken/tmp/objctest/Sources/objctest/objctest.swift -I /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug -target x86_64-unknown-linux-gnu -swift-version 5 -enable-batch-mode -index-store-path /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug/index/store -Onone -enable-testing -g -j4 -DSWIFT_PACKAGE -DDEBUG -module-cache-path /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug/ModuleCache -parseable-output -color-diagnostics
/home/ken/swift-5.4-RELEASE-ubuntu18.04/usr/bin/swift-frontend -frontend -c -primary-file /home/ken/tmp/objctest/Sources/objctest/objctest.swift -emit-module-path /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug/objctest.build/objctestpartial.swiftmodule -emit-module-doc-path /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug/objctest.build/objctestpartial.swiftdoc -emit-module-source-info-path /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug/objctest.build/objctestpartial.swiftsourceinfo -emit-dependencies-path /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug/objctest.build/objctest.d -emit-reference-dependencies-path /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug/objctest.build/objctest.swiftdeps -target x86_64-unknown-linux-gnu -disable-objc-interop -I /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug -color-diagnostics -enable-testing -g -module-cache-path /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug/ModuleCache -swift-version 5 -Onone -D SWIFT_PACKAGE -D DEBUG -enable-anonymous-context-mangled-names -parse-as-library -module-name objctest -o /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug/objctest.build/objctest.swift.o -index-store-path /home/ken/tmp/objctest/.build/x86_64-unknown-linux-gnu/debug/index/store -index-system-modules
�[1m/home/ken/tmp/objctest/Sources/objctest/objctest.swift:3:2: �[0m�[0;1;31merror: �[0m�[1mObjective-C interoperability is disabled
�[0m@objc
�[0;1;32m
^~~~
�[0m�[1m/home/ken/tmp/objctest/Sources/objctest/objctest.swift:10:2: �[0m�[0;1;31merror: �[0m�[1mObjective-C interoperability is disabled
�[0m@objc
�[0;1;32m~^~~~
�[0m

----- END swift build -v

@swift-ci
Copy link
Collaborator Author

swift-ci commented May 5, 2021

Comment by Ken Carroll (JIRA)

Up to 5.4 @objc was ignored in Linux on enums and classes. A protocol had to be defined like this:

#if os(Linux)

public protocol P

{ func Q() }

#else

@objc

public protocol P
{ func Q() }

#endif

This requires duplication of the protocol. Painful, but with enums and classes it will become unbearable.

I can have this:

func R()
{ #if os(Linux) let x = 1; #endif }

But not this:

#if !os(Linux)

@objc

#endif

public protocol P
{ func Q() }

I can understand there is probably a good reason. And yet, preprocessor-like processing of the '#if', as in the given illegal example, would solve the problem I am facing (maintaining two copies of enums, classes and protocols).

@swift-ci
Copy link
Collaborator Author

swift-ci commented May 7, 2021

Comment by Ken Carroll (JIRA)

Any update on this?

@beccadax
Copy link
Contributor

Rejecting @objc on Linux is the intended behavior. The fact that it was previously allowed when you imported Foundation was a bug, and that bug caused crashes like SR-13713. @objc validation on Linux was tightened to prevent these crashes.

(@slavapestov, just in case I'm wrong that this behavior change was intentional.)

Since we want the compiler to reject this code, I think we should close this bug report.

@swift-ci
Copy link
Collaborator Author

Comment by Ken Carroll (JIRA)

How can you have Swift code that works on MacOS and Linux then?

The suggestion in your comments is that Swift code cannot target both Linux and mixed MacOS Swift/Objective-C projects.

The idea of keeping a completely separate code base of the same identical code for different target platforms goes against all coding philosophies of the last 40 years.

Is this progress?

And ... the Swift project supports doing this for what, 8 years, before removing it?

Am I the only one caught out by this?

@swift-ci
Copy link
Collaborator Author

Comment by Ken Carroll (JIRA)

Please advise on best method for maintaining cross-platform code. Thanks.

Forget it. Just re-close the bug.

I'll just work around it. Find another language probably.

@swift-ci
Copy link
Collaborator Author

Comment by Ken Carroll (JIRA)

Pointless pursuing this.

@typesanitizer
Copy link

Hi kencarroll (JIRA User), could you try using the -enable-objc-interop compiler flag on Linux?

@swift-ci
Copy link
Collaborator Author

Comment by Ken Carroll (JIRA)

This was the first thing I tried. It appears that this is an 'unknown option' on Linux.

@jckarter
Copy link
Member

Although in general, we do not support ObjC interop on Linux, for enums, there's no reason we should need to require ObjC interop support to support @objc enum. On enums, that really makes the enum plain C compatible, and doesn't need any ObjC-specific runtime support.

@swift-ci
Copy link
Collaborator Author

Comment by Ken Carroll (JIRA)

For the record, I am not requesting Objc interoperability on Linux, I am just asking for the parser to continue to ignore @objc. Treat it as nul token.

@slavapestov
Copy link
Member

This PR formalizes the old behavior – using an @objc enum no longer requires Objective-C interop, or an import of Foundation: #37661

@slavapestov
Copy link
Member

kencarroll (JIRA User) with my change @objc enums will work on Linux again. This is allowed because as Joe said they don't rely on bridging or the Objective-C runtime.

However to the best of my knowledge, @objc protocols never worked on Linux and it was a mistake to allow them after importing corelibs-foundation. Method calls on @objc protocols always compiled down to objc_msgSend().

@swift-ci
Copy link
Collaborator Author

Comment by Ken Carroll (JIRA)

@slavapestov This is correct. For protocols I have had to maintain separate Linux and MacOS definitions. For classes and enums, the @objc annotation would just be ignored on Linux.

@swift-ci
Copy link
Collaborator Author

Comment by Ken Carroll (JIRA)

Will this be fixed? Currently the only way I can move to Swift 4 is to write a pre-processor. I would really prefer not to have to do this.

@typesanitizer
Copy link

This should be fixed in Swift 5.5 (#37664 please verify with a Swift 5.5 Development snapshot from swift.org.

@swift-ci
Copy link
Collaborator Author

Comment by Ken Carroll (JIRA)

theindigamer (JIRA User) I have tested this with the snapshot build and it only addresses enums. Classes and protocols still fail. The link to the issue you sent is only concerned with enums.

@slavapestov
Copy link
Member

"@objc" protocols never worked on Linux and would crash at compile time when you called a method. "@objc" classes worked on accident but this was not intended behavior. The only case we can reasonably support is "@objc" enums, because they don't rely on the Objective-C runtime.

@swift-ci
Copy link
Collaborator Author

Comment by Ken Carroll (JIRA)

@slavapestov What is the recommended way of supporting code that is intended to run on Linux and macOS (and be callable from Objective C but only on macOS)? Is there a reason that @objc cannot just be ignored on Linux? It could for example be discarded in the lexical phase as a null token.

@swift-ci
Copy link
Collaborator Author

Comment by Ken Carroll (JIRA)

Re-opening this bug because it only addresses enums. Please read the text of comments. Enums was just a part of the issue. It was only used for illustrative purposes. But classes are similarly affected. The code example has been expanded to demonstrate this.

If the Linux swift compiler is to stay as is, what are the cross-platform support mechanisms for a 'code base'? Completely separate code repositories for Linux/macOS means that this is not a cross-platform language as advertised.

Quite simply: If you have a class that is exported to Objective C on macOS, it cannot compile for Linux.

@swift-ci
Copy link
Collaborator Author

Comment by Ken Carroll (JIRA)

Any movement on this? Do I have to write a pre-processor?

@swift-ci
Copy link
Collaborator Author

Comment by Ken Carroll (JIRA)

Will fix with build process.

@typesanitizer
Copy link

The preprocessor idea is one option.

Having the attribute be ignored on Linux for classes and protocols would require a Swift evolution proposal [earlier, they were ignored due to a bug, not intentionally]. You could submit a small evolution pitch for that. If that gets some momentum, you could submit a proposal with an implementation.

Another option is a Swift evolution pitch for more flexible usage around attributes. In https://forums.swift.org/t/accepted-se-0308-postfix-if-config-expressions/47780, it says

The core team believes that additional refinement of conditional compilation is something that the language would benefit from. As such, proposals extending support towards conditional compilation of repeated lexical constructs, e.g. elements within an array literal, would be welcome.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
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
Projects
None yet
Development

No branches or pull requests

6 participants