swiftlang / swift

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

[cxx-interop, maccatalyst] CxxOptional does not work on Catalyst as it does on iOS, macOS and Linux #76999

Open wmanth opened 4 days ago

wmanth commented 4 days ago

Description

Working on a Swift package using C++ interoperability I am facing an issue handling optional values when compiling it with Mac Catalyst as target.

While principally it should be possible to use Swift Optionals in C++, the documentation also states regarding Mixing Swift and C++ Using Swift Package Manager:

Swift Package Manager does not yet provide support for using Swift APIs in C++.

Hence, I use a C++ proxy class that works around this limitation by returning a std::optional from C++ to Swift instead:

public:
    std::optional<DateTime> getDateTimeOriginal() const;

Accordingly, a Swift wrapper offers a computed getter with Optional return value:

    public var dateTimeOriginal: DateTime? {
        get { imageProxy.getDateTimeOriginal().value }

While targeting iOS, macOS and Linux this code compiles and runs without any issues, on MacCatalyst the compiler reports:

error: value of type 'std.__1.optional<DateTime>' has no member 'value'
        get { imageProxy.getDateTimeOriginal().value }
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^~~~~

Reproduction

Use above code to reproduce in a sample project.

Alternatively use my original SwiftExiv2 package to compile in Xcode with Mac Catalyst as target.

Expected behavior

Mac Catalyst should compile above code the same way successfully as it does with iOS, macOS and Linux as target.

Environment

Additional information

The getter value together with hasValue are exposed by the Cxx module most likely by calling their C++ stdlib std::optional pendants has_value() and value():

extension CxxOptional {

    /// Creates an instance initialized with `nil`.
    public init(nilLiteral: ())

    @inlinable public var hasValue: Bool { get }

    @inlinable public var value: Self.Wrapped? { get }
}

In fact, above Swift getter could also be written as:

        get {
            let dateTime = imageProxy.getDateTimeOriginal()
            return dateTime.hasValue ? dateTime.value : nil
        }

This works for iOS, macOS and Linux as well.

Considering #73409 has been closed I would assume the CxxOptional extension works for Mac Catalyst as well.

Trying to not use the extension, I was able to silence the compiler using:

        get {
            let dateTime = imageProxy.getDateTimeOriginal()
            return dateTime.has_value() ? dateTime.pointee : nil
        }

Though this code compiles for Mac Catalyst without issues, I was not able to test whether it runs due to another issue with Mac Catalyst C++ interoperability #77000 .

egorzhdan commented 2 days ago

Thanks for reporting this @wmanth!

This should be fixed by https://github.com/swiftlang/swift/pull/74994, however, the fix hasn't yet shipped in any released Swift compiler version.