<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=""><br class=""><div><blockquote type="cite" class=""><div class="">On Nov 30, 2016, at 4:09 PM, Dave Abrahams 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=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">on Mon Nov 28 2016, Douglas Gregor &lt;</span><a href="mailto:swift-evolution@swift.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">&gt; wrote:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" class="">On Nov 21, 2016, at 3:05 PM, Ramiro Feria Purón via swift-evolution<br class=""></blockquote>&lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><blockquote type="cite" class=""><br class="">Problem:<br class=""><br class="">Currently, it is not possible to be explicit about the generic parameters (type parameters) in a<br class=""></blockquote>generic function call. Type parameters are inferred from actual parameters:<br class=""><br class=""><blockquote type="cite" class=""><br class="">func f&lt;T&gt;(_ t: T) {<br class=""><br class="">&nbsp;&nbsp;&nbsp;//..<br class="">}<br class=""><br class="">f(5) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// T inferred to be Int<br class="">f("xzcvzxcvx") &nbsp;// T inferred to be string<span class="Apple-converted-space">&nbsp;</span><br class=""><br class="">If no type parameter is involved in the formal parameters, the type parameter needs to be used somehow as part of the return type. For example:<br class=""><br class="">func g&lt;T&gt;(_ x: Int) -&gt; [T] {<br class=""><br class="">&nbsp;&nbsp;&nbsp;var result: [T] = []<br class=""><br class="">&nbsp;&nbsp;&nbsp;//..<br class=""><br class="">&nbsp;&nbsp;&nbsp;return result<br class="">}<br class=""><br class="">In such cases, the type parameters must be inferrable from the context:<br class=""><br class="">g(7) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Error: T cannot be inferred<br class="">let array = g(7) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Error: T cannot be inferred<br class="">let array: [String] = g(7) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Ok: T inferred to be String<br class="">let array = g&lt;String&gt;(7) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Error: Cannot explicitly specialise generic function<br class=""><br class=""><br class=""><br class="">Proposed Solution:<br class=""><br class="">Allow explicit type parameters in generic function call:<br class=""><br class="">let _ = g&lt;String&gt;(7) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Ok<br class=""><br class=""><br class=""><br class="">Motivation:<br class=""><br class="">Consider the following contrived example:<br class=""><br class="">class Vehicle {<br class="">&nbsp;&nbsp;&nbsp;var currentSpeed = 0<br class="">&nbsp;&nbsp;&nbsp;//..<br class="">}<br class=""><br class="">class Bicycle: Vehicle {<br class="">&nbsp;&nbsp;&nbsp;//..<br class="">}<br class=""><br class="">class Car: Vehicle {<br class="">&nbsp;&nbsp;&nbsp;//..<br class="">}<br class=""><br class="">@discardableResult<br class="">func processAll&lt;T: Vehicle&gt;(in vehicles: [Vehicle], condition: (Vehicle) -&gt; Bool) -&gt; [T] {<br class=""><br class="">&nbsp;&nbsp;&nbsp;var processed: [T] = []<br class=""><br class="">&nbsp;&nbsp;&nbsp;for vehicle in vehicles {<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;guard let t = vehicle as? T, condition(vehicle) else { continue }<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//..<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;processed.append(t)<br class="">&nbsp;&nbsp;&nbsp;}<br class=""><br class="">&nbsp;&nbsp;&nbsp;return processed<br class="">}<br class=""><br class="">func aboveSpeedLimit(vehicle: Vehicle) -&gt; Bool {<br class="">&nbsp;&nbsp;&nbsp;return vehicle.currentSpeed &gt;= 100<br class="">}<br class=""><br class=""><br class="">let processedVehicles = processAll(in: vehicles, condition: aboveSpeedLimit) // Uh, T inferred to<br class=""></blockquote>be Vehicle!<br class=""><blockquote type="cite" class="">let processedCars: [Car] = processAll(in: vehicles, condition: aboveSpeedLimit) // T inferred to<br class=""></blockquote>be Car<br class=""><blockquote type="cite" class="">processAll&lt;Bicycle&gt;(in: vehicles, condition: aboveSpeedLimit) // This should be allowed under this<br class=""></blockquote>proposal<br class=""><blockquote type="cite" class=""><br class=""><br class="">Notes:<br class=""><br class="">If necessary, the (real life) Swift code that lead to the proposal could be shared.<br class=""></blockquote><br class="">This seems completely reasonable to me. I had always expected us to<br class="">implement this feature, but we never got around to it, and it wasn’t a<br class="">high priority because one can always use type inference. Additionally,<br class="">there were a few places where we originally thought we wanted this<br class="">feature, but prefer the more-explicit form where the user is required<br class="">to explicitly pass along a metatype. unsafeBitCast is one such case:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func unsafeBitCast&lt;T, U&gt;(_ x: T, to: U.Type) -&gt; U<br class=""><br class="">Even if we had the ability to provide explicit type arguments, we<br class="">would *not* want to change this signature to<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>func unsafeBitCast&lt;U, T&gt;(_ x: T) -&gt; U &nbsp;&nbsp;&nbsp;&nbsp;// bad idea<br class=""><br class="">because while it makes the correct usage slightly cleaner:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>unsafeBitCast&lt;Int&gt;(something)<span class="Apple-tab-span" style="white-space: pre;">        </span>// slightly prettier, but...<br class=""><br class="">it would enable type inference to go wild with unsafe casts:<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>foo(unsafeBitCast(something))<span class="Apple-tab-span" style="white-space: pre;">        </span>// just cast it to.. whatever<span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><br class="">which is… not great.<br class=""></blockquote><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Yeah, but IMO ideally we'd have a way to inhibit deduction of some</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">generic type parameters. </span></div></blockquote><div><br class=""></div><div>Well, I’d say we already have it: it’s the pass-a-metatype approach already used by unsafeBitCast, and I think usages of that API read really, really well as it is.</div><br class=""><blockquote type="cite" class=""><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">&nbsp;I might even be willing to inhibit deduction,</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">by default, of all generic function type parameters that don't appear in</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">the parameter list.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></blockquote></div><div class=""><br class=""></div><div class="">I’m not a fan of this for the reasons I and Ramiro outlined.</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>- Doug</div><div class=""><br class=""></div></body></html>