Assignment of tuples of related types, why is it allowed only through explicit assignment of a member? (Error: Cannot express tuple conversion)

When assigning a tuple, say, of Intmembers, to a tuple of a (heterogeneous) type of protocol, which corresponds Int, apparently, it is allowed to perform this assignment only through an explicit member after the assignment element.

protocol MyType {}
extension Int: MyType {}

let intPair = (1, 2)
var myTypePair : (MyType, MyType)

// OK
myTypePair = (intPair.0, intPair.1)

// OK
let intPairToMyTypePair : ((Int, Int)) -> (MyType, MyType) = { ($0.0, $0.1) }
myTypePair = intPairToMyTypePair(intPair)

// For all below: 
// "Error: cannot express tuple conversion '(Int, Int)' to '(MyType, MyType)'"
myTypePair = intPair
myTypePair = (intPair as! (MyType, MyType))
    /* warning: forced cast from '(Int, Int)' to '(MyType, MyType)' 
                always succeeds <-- well, not really */

if let _ = intPair as? (MyType, MyType) { }
    /* warning: conditional cast from '(Int, Int)' to '(MyType, MyType)' 
                always succeeds */

The peculiarity is that for cases of casting above, the Swift compiler warns that

warning: forced / conditional drop from '(Int, Int)'to '(MyType, MyType)' always performed

This clearly does not mean:

error: unable to express tuple conversion '(Int, Int)'before'(MyType, MyType)'

: , , ? , , ?

( )

, : , "bar", , 'is' case is always true:

let intPair = (1, 2)

switch intPair {
case is (MyType, MyType): print("foo") /* warning: 'is' test is always true */
case _ : print("bar")
}
    // "bar"

, , , , Array.

let intArr = [Int](1...5)
var myTypeArr : [MyType]

myTypeArr = intArr
    /* error: cannot assign value of type '[Int]' to type '[MyType]' */

if let _ = intArr as? [MyType] { }
    /* error: 'MyType' is not a subtype of 'Int' */
+4
2

, intPair - (Int, Int), (MyType, MyType). . - , .

myTypePair = intPair - , myTypePair , intPair, . , , , .

0

Swift . , . - , .

, , - Swift, Objective-C. Swift Java. Java :

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<B> b = new ArrayList<B>();
        ArrayList<A> a = b; // compile error: incompatible types: java.util.ArrayList<B> cannot be converted to java.util.ArrayList<A>
    }
}
class A {
}
class B extends A {
}

answer . , Swift Value Type.

, Value Type. Class Type . :

class A {}
let a = [A()]
let o: [AnyObject] = a // there is no problem for this!

, , AnyObject @objc, NSArray. swift document.

, , - , , !

0

Source: https://habr.com/ru/post/1627041/


All Articles