<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>I keep seeing collections brought up whenever this is discussed, so my question is: Have you found a broader use for variance annotations in the Swift you write? Even in Objective-C (perhaps due to their relative obscurity) I don't see (non-Foundation) people make use of the variance annotations for generic classes, so it makes me think we could just implement this as an extension to the collection casting machinery instead of exposing a Scala-esque variance notation. Sort of like how it was done before when subtyping was introduced for function types around 2.x IIRC.</div><div id="AppleMailSignature"><br>~Robert Widmann</div><div><br>2016/12/08 19:45、Braeden Profile via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> のメッセージ:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html charset=utf-8">Has the core team or the community considered the possibility of implementing covariant/contravariant generic types? It would really be appreciated.<div class=""><br class=""></div><div class="">I know with Array, vague-ifying or specific-ifying the type ([Int] to [Any]) has help from the compiler—and we can use `map` if all else fails—but that only lessens the impact of the missing functionality. This is my exact use case here, using SceneKit to identify the first-hit Controller object:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">class</span><span style="font-variant-ligatures: no-common-ligatures" class=""> ControllerNode<Controller: AnyObject>: </span><span style="font-variant-ligatures: no-common-ligatures; color: #aa2eb8" class="">SCNNode</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">{</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> controller: </span><span style="font-variant-ligatures: no-common-ligatures; color: #498672" class="">Controller</span></div></div><div class=""><font face="Menlo" class=""><span style="font-size: 11px;" class="">}</span></font></div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(146, 146, 146);" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">// Ordered front to back, returns the first Controller object.</span></div></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">for</span><span style="font-variant-ligatures: no-common-ligatures" class=""> hit </span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">in</span><span style="font-variant-ligatures: no-common-ligatures" class=""> hitTest</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">{</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(146, 146, 146);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span><span style="font-variant-ligatures: no-common-ligatures" class="">// Determine if this node is part of a controller.</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> ancestrySequence = </span><span style="font-variant-ligatures: no-common-ligatures; color: #3d1d81" class="">sequence</span><span style="font-variant-ligatures: no-common-ligatures" class="">(first: hit.</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">node</span><span style="font-variant-ligatures: no-common-ligatures" class="">, next: { $0.</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">parent</span><span style="font-variant-ligatures: no-common-ligatures" class=""> })</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><b class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> lastControllerNode: </span><span style="font-variant-ligatures: no-common-ligatures; color: #5faeae" class="">ControllerNode</span><span style="font-variant-ligatures: no-common-ligatures" class=""><</span><span style="font-variant-ligatures: no-common-ligatures; color: #aa2eb8" class="">AnyObject</span><span style="font-variant-ligatures: no-common-ligatures" class="">>? = ancestrySequence.</span><span style="font-variant-ligatures: no-common-ligatures; color: #3d1d81" class="">reduce</span><span style="font-variant-ligatures: no-common-ligatures" class="">(</span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">nil</span><span style="font-variant-ligatures: no-common-ligatures" class="">)</span></b></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><b class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>{ ($1 </span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">as</span><span style="font-variant-ligatures: no-common-ligatures" class="">? </span><span style="font-variant-ligatures: no-common-ligatures; color: #5faeae" class="">ControllerNode</span><span style="font-variant-ligatures: no-common-ligatures" class="">) ?? $0 }</span></b></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span class="Apple-tab-span" style="white-space: pre;">        </span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">if</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> cabinet = lastControllerNode?.</span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">controller</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">as</span><span style="font-variant-ligatures: no-common-ligatures" class="">? </span><span style="font-variant-ligatures: no-common-ligatures; color: #5faeae" class="">CabinetController</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>{ </span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> cabinet }</span></div><p style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span><br class="webkit-block-placeholder"></p><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><span class="Apple-tab-span" style="white-space:pre">        </span></span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">if</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> wall = lastControllerNode?.</span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">controller</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">as</span><span style="font-variant-ligatures: no-common-ligatures" class="">? </span><span style="font-variant-ligatures: no-common-ligatures; color: #5faeae" class="">WallController</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><span class="Apple-tab-span" style="white-space:pre">                </span>{ </span><span style="font-variant-ligatures: no-common-ligatures; color: #008f01" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> wall }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">}</span></div></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><div style="font-family: Helvetica; font-size: 12px;" class="">This compiles, but unfortunately, this will never work. The `reduce` algorithm always ends up trying to convert things like `ControllerNode<WallController> as ControllerNode<AnyObject>`, which—unintuitively—always fails. Without compiler help, so would things like `myIntArray as [Any]` or `Optional<Boy>(Boy()) as Optional<Human>`.</div><div style="font-family: Helvetica; font-size: 12px;" class=""><br class=""></div><div style="font-family: Helvetica; font-size: 12px;" class="">If Swift is supposed to welcome generic programming, this would be a great thing to have.</div></span></div></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>