Very interesting point, Alexis. So can you reiterate again which of the four options you outlined earlier support this use case? And if there are multiple, which would be the most consistent with the rest of the language?<br><br>And Srdan, could you incorporate that information into your discussion?<br><div class="gmail_quote"><div dir="ltr">On Thu, Jan 26, 2017 at 12:59 Srđan Rašić &lt;<a href="mailto:srdan.rasic@gmail.com">srdan.rasic@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="gmail_msg">That&#39;s a very good point Alexis and makes sense to me. I&#39;ll updated the proposal with that in mind and revise my examples.</div><div class="gmail_extra gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg">On Thu, Jan 26, 2017 at 7:06 PM, Alexis <span dir="ltr" class="gmail_msg">&lt;<a href="mailto:abeingessner@apple.com" class="gmail_msg" target="_blank">abeingessner@apple.com</a>&gt;</span> wrote:<br class="gmail_msg"><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><br class="gmail_msg"><div class="gmail_msg"><span class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg">On Jan 25, 2017, at 8:15 PM, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" class="gmail_msg" target="_blank">xiaodi.wu@gmail.com</a>&gt; wrote:</div><br class="m_2252652473687582788m_3165962419350078136Apple-interchange-newline gmail_msg"><div class="gmail_msg"><div dir="ltr" class="gmail_msg">Srdan, I&#39;m afraid I don&#39;t understand your discussion. Can you simplify it for me by explaining your proposed solution in terms of Alexis&#39;s examples below?<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">```</div><div class="gmail_msg"><div class="gmail_msg">// Example 1: user supplied default is IntegerLiteralConvertible</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">func foo&lt;T=Int64&gt;(t: T) { ... }</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">foo(22)</div><div class="gmail_msg">//  ^</div><div class="gmail_msg">//  |</div><div class="gmail_msg">//  What type gets inferred here?</div><div class="gmail_msg">```</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I believe that it is essential that the answer here be `Int` and not `Int64`.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">My reasoning is: a user&#39;s code *must not* change because a library *adds* a default in a newer version. (As mentioned in several design docs, most recently the new ABI manifesto, defaults in Swift are safe to add without breaking source compatibility.)</div><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></span><div class="gmail_msg">I don’t agree: adding a default to an <b class="gmail_msg">existing</b> type parameter should be a strict source-breaking change (unless the chosen type can avoid all other defaulting rules, see the end of this email).</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Type Parameter Defaults, as I know them, are a tool for avoiding breakage when a <b class="gmail_msg">new</b> type parameter is introduced. That is, they allow you to perform the following transformation safe in the knowledge that it won’t break clients:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">func foo(input: X)</div><div class="gmail_msg">func foo&lt;T=X&gt;(input: T)</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">For this to work, you need to make the &lt;T=X&gt; default have dominance over the other default rules.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Specifically you want this code to keep working identically:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">// before</div><div class="gmail_msg">func foo(input: Int64)</div><div class="gmail_msg">foo(0)  // Int64</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">// after</div><div class="gmail_msg">func foo&lt;T=Int64&gt;(input: T)</div><div class="gmail_msg">foo(0) // Int64</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">This is in direct conflict with making the following keep working identically:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><div class="gmail_msg">// before</div><div class="gmail_msg">func foo&lt;T&gt;(input: T)</div><div class="gmail_msg">foo(0) // Int</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">// after</div><div class="gmail_msg">func foo&lt;T=Int64&gt;(input: T)</div><div class="gmail_msg">foo(0) // Int</div></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">You have to choose which of these API evolution patterns is most important, because you can’t make both work. To me, the first one is obviously the most important, because that’s the whole point of the feature. The reason to do the second one is to try to make a common/correct case more ergonomic and/or the default. But unlike function argument defaults, type parameters can already have inferred values.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Note that source breaking with adding defaults can be avoided as long as long as the chosen default isn’t:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">* XLiteralConvertible (pseudo-exception: if the default is also the XLiteralType it’s fine, but that type is user configurable)</div><div class="gmail_msg">* A supertype of another type (T?, T!, SuperClass, Protocol, (…, someLabel: T, ...), [SuperType], [SuperType1:SuperType2], (SuperType) -&gt; SubType, and probably more in the future)</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Concretely this means it’s fine to retroactively make an existing generic parameter default to MyFinalClass, MyStruct, MyEnum, and collections/functions/unlabeled-tuples thereof. Arguably, Int/String/Bool/Array/etc are fine, but there’s a niche situation where using them can cause user breakage due to changing XLiteralType.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">In practice I expect this will be robust enough to avoid breakage — I expect most defaults will be MyStruct/MyEnum, or an XLiteralType. Even if it’s not, you need to end up in a situation where inference can actually kick in and find an ambiguity *and* where the difference matters. (e.g. SubClass vs SuperClass isn’t a big deal in most cases)</div><div class="gmail_msg"><div class="m_2252652473687582788h5 gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div><br class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><div dir="ltr" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">Here, if version 1 of a library has `func foo&lt;T&gt;(t: T) { ... }`, then `foo(22)` must infer `T` to be `Int`. That&#39;s just the rule in Swift, and it would be severely source-breaking to change that. Therefore, if version 2 of that library has `func foo&lt;T=Int64&gt;(t: T) { ... }`, then `foo(22)` must still infer `T` to be `Int`.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Does your proposed solution have the same effect?</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">```</div><div class="gmail_msg">// Example 2: user supplied default isn&#39;t IntegerLiteralConvertible</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">func bar&lt;T=Character&gt;(t: T) { ... }</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">bar(22)</div><div class="gmail_msg">//  ^</div><div class="gmail_msg">//  |</div><div class="gmail_msg">//  What type gets inferred here?</div></div><div class="gmail_msg">```</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">By the same reasoning as above, this ought to be `Int`. What would the answer be in your proposed solution?</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_extra gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg">On Wed, Jan 25, 2017 at 2:07 PM, Srđan Rašić <span dir="ltr" class="gmail_msg">&lt;<a href="mailto:srdan.rasic@gmail.com" class="gmail_msg" target="_blank">srdan.rasic@gmail.com</a>&gt;</span> wrote:<br class="gmail_msg"><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="gmail_msg">That&#39;s a good example Alexis. I do agree that generic arguments are inferred in a lot of cases, my point was that they should not be inferred in &quot;type declarations&quot;. Not sure what&#39;s the right terminology here, but I mean following places:<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">(I) Variable/Constant declaration</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">  ```</div><div class="gmail_msg">  let x: X</div><div class="gmail_msg">  ```</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">(II) Property declaration</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">  ```</div><div class="gmail_msg">  struct T {</div><div class="gmail_msg">    let x: X</div><div class="gmail_msg">  }</div><div class="gmail_msg">  ```</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">(III) Function declaration</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">  ```</div><div class="gmail_msg">  func a(x: X) -&gt; X</div><div class="gmail_msg">  ```</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><div class="gmail_msg">(IV) Enumeration case declaration</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">  ```</div><div class="gmail_msg">  enum E {</div><div class="gmail_msg">    case x(X)</div><div class="gmail_msg">  }</div><div class="gmail_msg">  ```</div></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><div class="gmail_msg">(V) Where clauses</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">  ```</div><div class="gmail_msg">  extensions E where A == X {}  </div><div class="gmail_msg">  ```</div></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">In those cases `X` should always mean `X&lt;Int&gt;` if it was defined as `struct X&lt;T = Int&gt;`. That&#39;s all my rule says. Sorry for not being clear in the last email :)</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">As for the other cases, mostly those where an instance is created, inference should be applied.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Let&#39;s go through your examples. Given</div><span class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg">struct BigInt: Integer {</span><br style="font-size:12.800000190734863px" class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg">  var storage: Array&lt;Int&gt; = []</span><br style="font-size:12.800000190734863px" class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg">}</span><br class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div></span><span class="gmail_msg"><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg">func process&lt;T: BinaryInteger&gt;(_ input: BigInt&lt;T&gt;) -&gt; BigInt&lt;T&gt; { ... }</span><br style="font-size:12.800000190734863px" class="gmail_msg"></div><div class="gmail_msg"><br class="gmail_msg"></div></span><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg">what happens with `</span><span style="font-size:12.800000190734863px" class="gmail_msg">let val1 = process(BigInt())`? </span><span style="font-size:12.800000190734863px" class="gmail_msg">I think this is actually the same problem as what happens in case of `let x = BigInt()`.</span></div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg">In such case my rule does not apply as we don&#39;t have full type declaration. In </span><span style="font-size:12.800000190734863px" class="gmail_msg">`let x = BigInt()` type is not defined at all, while in `</span><span style="font-size:12.800000190734863px" class="gmail_msg">func process&lt;T: BinaryInteger&gt;(_ input: BigInt&lt;T&gt;) -&gt; BigInt&lt;T&gt; { ... }` </span><span style="font-size:12.800000190734863px" class="gmail_msg">type is explicitly weakened or &quot;undefaulted&quot; if you will. </span></div><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg"><br class="gmail_msg"></span></div><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg">We should introduce new rule for such cases and allowing `Storage=Int` default to participate in such expressions would make sense. As you said, it also solves second example: </span><span style="font-size:12.800000190734863px" class="gmail_msg">let val2 = process(0).</span></div><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg"><br class="gmail_msg"></span></div><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg">I guess this would be the problem we thought we were solving initially and in that case I think the solution should be what Doug suggested: </span><span style="font-size:12.800000190734863px" class="gmail_msg">if you can’t infer a particular type, fill in a default.</span></div><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg"><br class="gmail_msg"></span></div><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg">Of course, if the default conflicts with the generic constraint, it would not be filled in and it would throw an error.</span></div><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg"><br class="gmail_msg"></span></div><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg">For the sake of completeness,</span></div><span class="gmail_msg"><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg"><br class="gmail_msg"></span></div><div class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg">func fastProcess(_ input: BigInt&lt;Int64&gt;) -&gt; BigInt&lt;Int64&gt; { ... }</span><br style="font-size:12.800000190734863px" class="gmail_msg"><span style="font-size:12.800000190734863px" class="gmail_msg">let val3 = fastProcess(BigInt())</span><span style="font-size:12.800000190734863px" class="gmail_msg"><br class="gmail_msg"></span></div><div class="gmail_msg"><br class="gmail_msg"></div></span><div class="gmail_msg">would certainly infer the type from context as my rule does not apply to initializers. It would infer BigInt&lt;Int64&gt;.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">As for your last example, I guess we can&#39;t do anything about that and that&#39;s ok.</div><div class="gmail_msg"><div class="m_2252652473687582788m_3165962419350078136h5 gmail_msg"><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_extra gmail_msg"><br class="gmail_msg"><div class="gmail_quote gmail_msg">On Wed, Jan 25, 2017 at 7:50 PM, Alexis <span dir="ltr" class="gmail_msg">&lt;<a href="mailto:abeingessner@apple.com" class="gmail_msg" target="_blank">abeingessner@apple.com</a>&gt;</span> wrote:<br class="gmail_msg"><blockquote class="gmail_quote gmail_msg" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Yes, I agree with Xiaodi here. I don’t think this particular example is particularly compelling. Especially because it’s not following the full evolution of the APIs and usage, which is critical for understanding how defaults should work.<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
Let&#39;s look at the evolution of an API and its consumers with the example of a BigInt:<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
struct BigInt: Integer {<br class="gmail_msg">
  var storage: Array&lt;Int&gt; = []<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
which a consumer is using like:<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
func process(_ input: BigInt) -&gt; BigInt { ... }<br class="gmail_msg">
let val1 = process(BigInt())<br class="gmail_msg">
let val2 = process(0)<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
Ok that&#39;s all fairly straightforward. Now we decide that BigInt should expose its storage type for power-users:<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
struct BigInt&lt;Storage: BinaryInteger = Int&gt;: Integer {<br class="gmail_msg">
  var storage: Array&lt;Storage&gt; = []<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
Let&#39;s make sure our consumer still works:<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
func process(_ input: BigInt) -&gt; BigInt { ... }<br class="gmail_msg">
let val1 = process(BigInt())<br class="gmail_msg">
let val2 = process(0)<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
Ok BigInt in process’s definition now means BigInt&lt;Int&gt;, so this still all works fine. Perfect!<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
But then the developer of the process function catches wind of this new power user feature, and wants to support it.<br class="gmail_msg">
So they too become generic:<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
func process&lt;T: BinaryInteger&gt;(_ input: BigInt&lt;T&gt;) -&gt; BigInt&lt;T&gt; { ... }<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
The usage sites are now more complicated, and whether they should compile is unclear:<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
let val1 = process(BigInt())<br class="gmail_msg">
let val2 = process(0)<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
For val1 you can take a hard stance with your rule: BigInt() means BigInt&lt;Int&gt;(), and that will work. But for val2 this rule doesn&#39;t work, because no one has written BigInt unqualified. However if you say that the `Storage=Int` default is allowed to participate in this expression, then we can still find the old behaviour by defaulting to it when we discover Storage is ambiguous.<br class="gmail_msg">
<br class="gmail_msg">
We can also consider another power-user function:<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
func fastProcess(_ input: BigInt&lt;Int64&gt;) -&gt; BigInt&lt;Int64&gt; { ... }<br class="gmail_msg">
let val3 = fastProcess(BigInt())<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
Again, we must decide the interpretation of this. If we take the interpretation that BigInt() has an inferred type, then the type checker should discover that BigInt&lt;Int64&gt; is the correct result. If however we take stance that BigInt() means BigInt&lt;Int&gt;(), then we&#39;ll get a type checking error which our users will consider ridiculous: *of course* they wanted a BigInt&lt;Int64&gt; here!<br class="gmail_msg">
<br class="gmail_msg">
We do however have the problem that this won’t work:<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
let temp = BigInt()<br class="gmail_msg">
fastProcess(temp) // ERROR — expected BigInt&lt;Int64&gt;, found BigInt&lt;Int&gt;<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
But that’s just as true for normal ints:<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
let temp = 0<br class="gmail_msg">
takesAnInt64(temp) // ERROR — expected Int64, found Int<br class="gmail_msg">
<br class="gmail_msg">
<br class="gmail_msg">
Such is the limit of Swift’s inference scheme.<br class="gmail_msg">
<br class="gmail_msg">
</blockquote></div><br class="gmail_msg"></div></div></div></div>
</blockquote></div><br class="gmail_msg"></div></div>
</div></blockquote></div></div></div><br class="gmail_msg"></div></blockquote></div><br class="gmail_msg"></div>
</blockquote></div>