[Accepted] SE-0244: Opaque Result Types

SE-0244 has been accepted.

14 Likes

If a function is open or public, I guess it needs the type after the “some“ to be public too. What about the actual return type; since the actual type is hidden only at the user level (and not to the linker), doesn’t the actual type need to be public too?

It's hidden from the linker as well. There's a run-time call to fetch the type.

4 Likes

In spite of that proposal status is Status: Implemented (Swift 5.1),
some codes appeared in proposal document are still can not be compiled.
Is this actually working on implementation against "Status" now?

I found these cases.

[omochi@omochi-iMac-PC43 check]$ cat c1.swift
let strings: some Collection = ["hello", "world"]
[omochi@omochi-iMac-PC43 check]$ swift c1.swift
c1.swift:1:32: error: cannot convert value of type '[String]' to specified type 'some Collection'
let strings: some Collection = ["hello", "world"]
                               ^~~~~~~~~~~~~~~~~~
                                                  as! some Collection
[omochi@omochi-iMac-PC43 check]$ cat c2.swift
public protocol P {
    mutating func flip()
}

private struct Witness: P {
    mutating func flip() { /* ... */ }
}

public var someP: some P = Witness()
[omochi@omochi-iMac-PC43 check]$ swift c2.swift
c2.swift:9:28: error: cannot convert value of type 'Witness' to specified type 'some P'
public var someP: some P = Witness()
                           ^~~~~~~~~
                                     as! some P
[omochi@omochi-iMac-PC43 check]$ cat c3.swift
public protocol P { }
private struct Impl: P { }

public struct Vendor {
    private var storage: [Impl] = [Impl()]
    
    public var count: Int {
        return storage.count
    }
    
    public subscript(index: Int) -> some P {
        get {
            return storage[index]
        }
        set (newValue) {
            storage[index] = newValue
        }
    }
}

var vendor = Vendor()
vendor[0] = vendor[2] // ok: can move elements around
[omochi@omochi-iMac-PC43 check]$ swift c3.swift
c3.swift:16:30: error: cannot assign value of type 'some P' to type 'Impl'
            storage[index] = newValue
                             ^~~~~~~~
                                      as! Impl

I tested with swift-DEVELOPMENT-SNAPSHOT-2019-05-15-a.

Similarly following example from proposal works while it shouldn't (according to the doc):

func foo() -> some BinaryInteger { return 219 }
var x = foo()
x = 912 // error: Int is not known to be the same as the return type as foo()
print(x)

It actually compiles and print 912.

(tested against 5.1-DEVELOPMENT-SNAPSHOT-2019-05-09-a)

BinaryInteger conforms to ExpressibleByIntegerLiteral, so whatever that opaque type is this can still work

I didn't know it. It is interesting.
Literal 912 is implicitly convertible to returnTypeOf(foo) since this type is ExpressibleByIntegerLiteral.

This code can not be compiled correctly.

func foo() -> some BinaryInteger { return 219 }
var x = foo()
x = Int(912) // cannot assign value of type 'Int' to type 'some BinaryInteger'
print(x)

Yeah, this is a bug in the proposal text rather than the implementation.

2 Likes

I opened issue about what I wrote.

https://bugs.swift.org/browse/SR-10723
https://bugs.swift.org/browse/SR-10724

Thanks! Support for settable and stored properties isn't done yet. Get-only computed properties should work at this point.

1 Like