Swift 5.7: Passing `any type` to `some type` argument

I have just watched WWDC22 What's new in Swift and found out it brings so much improvement on generics and protocols.

The video mentions we can pass any type to some type argument and Swift will handle that case for us, like:

extension Mailmap {
    mutating func mergeEntriesfrom other: some Mailmap) { … }
}

func mergeMailmaps(_ a: any Mailmap, _ b: any Mailmap) -> any Mailmap {
    var copy = a
    copy.mergeEntries(from: b) // works fine
    return a
}

That feature could be very useful and I can't wait to use it. I wrote some code to test that feature, turns out the behavior is more complicated than it looks like.

class StarFieldRunner {
    func runSome(_ v: some StarField) {
        
    }
    
    func runAny(_ v: any StarField) {
        // 1. Works fine
        runSome(v)
        
        // 2. Works fine
        let v2 = v
        runSome(v2)
        
        // 3. Compile Error: Type 'any StarField' cannot conform to 'StarField'
        var v3 = v
        runSome(v3)
    }
}
  1. If we pass the parameter of any type into some type directly, everything works fine.
  2. If we pass a constant defined using the any type to some type, it works too.
  3. If we pass a new variable defined from the any type to some type, the old error is raised again.

I have no idea if it's intended behavior or a language bug. Any information will be welcomed.

5 Likes

It turns out using a new method can bridge the call while I have not yet figured out what's going on:

class StarFieldRunner {
    func runSome(_ v: some StarField) {
        
    }
    
    func runAny(_ v: any StarField) {
        // Works fine
        runSome(v)
        
        // Works fine
        let v2 = v
        runSome(v2)
        
        var v3 = v
        runAny2(v3)
    }
    
    func runAny2(_ v: any StarField) {
        runSome(v)
    }
}

Possibly it relates to the mutability of the variable. v3 is a var, so passing it directly produces an error. When you introduced another function call into the mix, the v inside runAny2 is immutable, hence doesn't produce the error. If I mark the function with an inout param, the same error returns.

Update: Turns out the behavior has been fixed in Swift 5.7.2. Now the error is gone.