Tuple subtype problem


(frogcjn) #1

Another problem about sub-typing system in Swift is tuple.

Why tuple does not support sub-typing feature?

for example:

class A{

}

class B:A {

}

let tupleB:(B,B) = (B(),B())
let tupleA:(A,A) = tupleB

This should be allowed in Swift. But a compiler typing-check error.

Thanks!


(Slava Pestov) #2

Hi Cao,

You’re right, this should be fixed some day. The constraint system understands the subtyping relation here. The diagnostic is generated by the rewriting pass, which currently has no way to express tuple conversions in the AST since its slightly tricky.

A tuple conversion needs to be able to wrap each component of a tuple in its own expression, since subtyping conversions can get pretty hairy and involve multiple nested Exprs. Think if a conversion as a lambda form, like \(x,y)->(f(x),g(y)), that we’re applying to some tuple value that results from evaluating some other expression.

The way to do this in the AST is with OpaqueValueExprs, which are already used for opening protocol existentials:

(open_existential_expr
    (opaque_value 1) ;; first sub-expression — establish a binding for the existential payload and type
    (apply_expr … (opaque_value 1)) ;; second sub-expression — do something with the payload — the result of this expression is the result of the whole OpenExistentialExpr
    (load_expr someVar)) ;; third sub-expression — this is something that evaluates to an existential type, and is bound to the opaque value in the first expression

There needs to be a new TupleConversionExpr or similar that also uses OpaqueValueExpr in the same manner, except now we have several opaque values, one for each component of the tuple being destructured:

(tuple_conversion_expr
    (tuple_expr ;; first sub-expression — establish bindings for components of a tuple value — this is sort of like the left hand side of ‘.’ in a lambda expression \(x,y).(f(x),g(y))
        (opaque_value 1)
        (opaque_value 2))
    (tuple_expr ;; second sub-expression — define result of conversion in terms of the bindings
        (upcast_expr (opaque_value 1) A)
        (upcast_expr (opaque_value 2) A))
    (load_expr tupleB)) ;; third sub-expression — input tuple for conversion, must have same number of components as the input pattern

Then SILGen needs to know how to lower these, by evaluating the input expression, loading its components as individual values, binding them to the unique OpaqueValueExprs in the first expression, and finally evaluating the result to yield the ultimate result of the tuple conversion.

It would be great if someone could take a look at this :slight_smile:

Slava

···

On Feb 15, 2016, at 10:47 PM, Cao Jiannan via swift-evolution <swift-evolution@swift.org> wrote:

Another problem about sub-typing system in Swift is tuple.

Why tuple does not support sub-typing feature?

for example:

class A{

}

class B:A {

}

let tupleB:(B,B) = (B(),B())
let tupleA:(A,A) = tupleB

This should be allowed in Swift. But a compiler typing-check error.

Thanks!

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution