<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 <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> 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 <</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="">> 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><<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> 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<T>(_ t: T) {<br class=""><br class=""> //..<br class="">}<br class=""><br class="">f(5) // T inferred to be Int<br class="">f("xzcvzxcvx") // T inferred to be string<span class="Apple-converted-space"> </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<T>(_ x: Int) -> [T] {<br class=""><br class=""> var result: [T] = []<br class=""><br class=""> //..<br class=""><br class=""> 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) // Error: T cannot be inferred<br class="">let array = g(7) // Error: T cannot be inferred<br class="">let array: [String] = g(7) // Ok: T inferred to be String<br class="">let array = g<String>(7) // 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<String>(7) // 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=""> var currentSpeed = 0<br class=""> //..<br class="">}<br class=""><br class="">class Bicycle: Vehicle {<br class=""> //..<br class="">}<br class=""><br class="">class Car: Vehicle {<br class=""> //..<br class="">}<br class=""><br class="">@discardableResult<br class="">func processAll<T: Vehicle>(in vehicles: [Vehicle], condition: (Vehicle) -> Bool) -> [T] {<br class=""><br class=""> var processed: [T] = []<br class=""><br class=""> for vehicle in vehicles {<br class=""> guard let t = vehicle as? T, condition(vehicle) else { continue }<br class=""> //..<br class=""> processed.append(t)<br class=""> }<br class=""><br class=""> return processed<br class="">}<br class=""><br class="">func aboveSpeedLimit(vehicle: Vehicle) -> Bool {<br class=""> return vehicle.currentSpeed >= 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<Bicycle>(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<T, U>(_ x: T, to: U.Type) -> 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<U, T>(_ x: T) -> U // 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<Int>(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=""> 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>