<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hi Cao,<div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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)-&gt;(f(x),g(y)), that we’re applying to some tuple value that results from evaluating some other expression.</div><div class=""><br class=""></div><div class="">The way to do this in the AST is with OpaqueValueExprs, which are already used for opening protocol existentials:</div><div class=""><br class=""></div><div class="">(open_existential_expr</div><div class="">&nbsp; &nbsp; (opaque_value 1) &nbsp; &nbsp;;; first sub-expression — establish a binding for the existential payload and type</div><div class="">&nbsp; &nbsp; (apply_expr … (opaque_value 1)) &nbsp; &nbsp;;; second sub-expression — do something with the payload — the result of this expression is the result of the whole OpenExistentialExpr</div><div class="">&nbsp; &nbsp; (load_expr someVar)) &nbsp; &nbsp;;; third sub-expression — this is something that evaluates to an existential type, and is bound to the opaque value in the first expression</div><div class=""><br class=""></div><div class="">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:</div><div class=""><br class=""></div><div class="">(tuple_conversion_expr</div><div class="">&nbsp; &nbsp; (tuple_expr &nbsp; &nbsp; ;; 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))</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; (opaque_value 1)</div>&nbsp; &nbsp; &nbsp; &nbsp; (opaque_value 2))<div class="">&nbsp; &nbsp; (tuple_expr &nbsp; &nbsp;;; second sub-expression — define result of conversion in terms of the bindings</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; (upcast_expr (opaque_value 1) A)</div>&nbsp; &nbsp; &nbsp; &nbsp; (upcast_expr (opaque_value 2) A))<div class="">&nbsp; &nbsp; (load_expr tupleB)) &nbsp; &nbsp;;; third sub-expression — input tuple for conversion, must have same number of components as the input pattern<br class=""><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">It would be great if someone could take a look at this :)</div><div class=""><br class=""></div><div class="">Slava</div><div class=""><br class=""><div class=""><div><blockquote type="cite" class=""><div class="">On Feb 15, 2016, at 10:47 PM, Cao Jiannan via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Another problem about sub-typing system in Swift is tuple.<div class=""><br class=""></div><div class="">Why tuple does not support sub-typing feature?</div><div class=""><br class=""></div><div class="">for example:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: 'Fira Code'; color: rgb(4, 51, 255);" class="">class<span style="font-variant-ligatures: no-common-ligatures;" class=""> A{</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: 'Fira Code'; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: 'Fira Code';" class="">}</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: 'Fira Code'; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: 'Fira Code';" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">class</span> B:<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">A</span> {</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: 'Fira Code'; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: 'Fira Code';" class="">}</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: 'Fira Code'; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: 'Fira Code';" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">let</span> tupleB:(<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">B</span>,<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">B</span>) = (<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">B</span>(),<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">B</span>())</div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: 'Fira Code';" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #0433ff" class="">let</span> tupleA:(<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">A</span>,<span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">A</span>) = <span style="font-variant-ligatures: no-common-ligatures; color: #3495af" class="">tupleB</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: 'Fira Code'; min-height: 13px;" class=""><br class=""></div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: 'Fira Code';" class=""><div style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px;" class="">This should be allowed in Swift. But a compiler typing-check error.</div><div style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px;" class="">Thanks!</div><div style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></div></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></div></div></div></body></html>