<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 Jacob<div class=""><br class=""></div><div class="">Apologies for the delay in answering…</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 9, 2015, at 2:00 AM, Jacob Bandes-Storch via swift-dev &lt;<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="">I'm looking into allowing extensions like "extension Array where Element == Int" — relaxing the restriction that prevents generic function/type definitions from having concrete types specified. (Slava mentioned that this is a favorable language change without need for the evolution process:&nbsp;<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/000865.html" target="_blank" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/000865.html</a>)</div><div class=""><br class=""></div><div class="">I'd like to run my thoughts by some people who know what they're talking about, before diving in too far :-)</div><div class=""><br class=""></div><div class="">The diagnostic in question is</div><div class="">&nbsp; &nbsp; diag::requires_generic_param_made_equal_to_concrete</div><div class="">&nbsp; &nbsp; "same-type requirement makes generic parameter %0 non-generic"</div><div class="">which is emitted from ArchetypeBuilder::addSameTypeRequirementToConcrete().</div><div class=""><br class=""></div><div class="">Multiple code paths reach&nbsp;checkGenericParamList() which adds the requirements:</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; - DeclChecker::visitClassDecl</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;-&gt; TC::validateDecl case for struct/class/enum</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;-&gt; TC::validateGenericTypeSignature</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;-&gt; TC::validateGenericSignature</div>







<div class="">&nbsp; &nbsp; &nbsp; &nbsp;-&gt; TC::checkGenericParamList</div><div class=""><br class=""></div>







<div class="">&nbsp; &nbsp; - DeclChecker::visitFuncDecl</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;-&gt; TC::<span class="">validateGenericFuncSignature</span></div><div class=""><span class="">&nbsp; &nbsp; &nbsp; &nbsp;-&gt; TC::</span>checkGenericFuncSignature</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;-&gt; TC::checkGenericParamList</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp; - DeclChecker::visitExtensionDecl</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;-&gt; TC::validateExtension</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;-&gt; TC::checkExtensionGenericParams</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;-&gt; TC::validateGenericSignature</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;-&gt; TC::checkGenericParamList</div></div></div></blockquote><div><br class=""></div><div>There’s a path through&nbsp;TypeChecker::handleSILGenericParams() that you need to consider, which is triggered when parsing SIL. It’s an odd case because you get all of the generic parameter lists up front. I suspect you would just always allow type parameters to be equated with concrete types from here.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="">(Mildly confusing to have both "validate" and "check" variants, but only in some of the cases…?)</div></div></div></blockquote><div><br class=""></div><div>Having the “check” in the middle/bottom is the exceptional part here. The rough intent at one point was that “validate” was basic validation of a declaration so that it could be useful from elsewhere, while “check” checks all of the semantic constraints to see if the declaration was well-formed. But, it wasn’t followed that carefully, and this turns out to be a not-terribly-useful distinction. Rather, we should be handling more fine-grained type checking requests iteratively, per</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span><a href="https://github.com/apple/swift/blob/master/docs/proposals/DeclarationTypeChecker.rst" class="">https://github.com/apple/swift/blob/master/docs/proposals/DeclarationTypeChecker.rst</a></div><div><br class=""></div>But that’s off on the horizon. Back to your actual question…</div><div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class="">























































































<div class=""><br class=""></div><div class="">It's only in the 3rd case (extensions) that we want to allow the requirements to make the types fully bound/concrete. </div></div></div></blockquote><div><br class=""></div><div>Okay, so this means that your example would be accepted, but something like:</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>class X&lt;T where T == Int&gt; {</div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div><br class=""></div><div>would remain ill-formed, as would</div><div><br class=""></div><div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>class X&lt;T&gt; {</div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>&nbsp; func f&lt;U where T == Int&gt;() { … }</div><div><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class=""><br class=""></div></div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="">So here's what I propose doing:</div><div class=""><br class=""></div><div class="">&nbsp; 1. The ArchetypeBuilder needs to know whether this is allowed. So add a boolean field, called e.g. AllowConcreteRequirements.</div><div class=""><br class=""></div><div class="">&nbsp; 2a. Pass false to the ArchetypeBuilder created in validateGenericFuncSignature.</div><div class="">&nbsp; 2b. Pass the boolean through as a param to validateGenericSignature, where the ArchetypeBuilder is created. (validateGenericSignature&nbsp;is used in both class &amp; extension cases). In particular, pass true from checkExtensionGenericParams and false from validateGenericTypeSignature.</div><div class=""><br class=""></div><div class="">&nbsp; 3. Skip the error if AllowConcreteRequirements was true. Instead allow the requirement to be added (and fix any fallout issues from this change, add tests, yadda yadda).</div><div class=""><br class=""></div><div class="">How does that sound?</div></div></div></blockquote><div><br class=""></div><div>You may need to make the AllowConcreteRequirements flag indicate the depth at which generic parameters are allowed to be made equivalent to concrete types. Consider, for example:</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>class X&lt;T&gt; { }</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>extension X&lt;T&gt; {</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&nbsp; func f&lt;U where T == Int&gt;() { }</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div>Presumably that should be ill-formed still, and that one would properly have to write</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>extension X where T == Int {</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>&nbsp; func f() { }</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div>(which is much clearer anyway, of course!).</div><div><br class=""></div><div>And although it’s broken today for other reasons, the depth of the generic parameters that are allowed to be made equivalent to concrete types could be &gt; 0 if you had a generic type nested within a generic type, e.g.,</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>class X&lt;T&gt; {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>class Y&lt;U&gt; {</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>extension X.Y where T == Int, U == String { … } // okay; both depths 0 and 1 are okay to bind to concrete types</div><div><br class=""></div><div><br class=""></div></div><div><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="">Also, is there any desire to remove this restriction?</div><div class=""><span class="">&nbsp; &nbsp; diag</span><span class="">::</span><span class="">extension_specialization</span></div><div class="">&nbsp; &nbsp; "constrained extension must be declared on the unspecialized generic type %0 with constraints specified by a 'where' clause"</div><div class="">It seems natural to want to allow "extension Array&lt;Int&gt;", but I'm afraid it may complicate things significantly, especially if we only wanted to allow this syntax in the case of .</div></div></div></blockquote></div><br class=""></div><div class="">I’d want this bit of syntax to go through swift-evolution, even though I suspect it would be very well-received. There’s a syntactic symmetry question it invokes, because</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>struct X&lt;T&gt; { … }</div><div class=""><br class=""></div><div class="">introduces T as a type parameter while</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>extension X&lt;T&gt; { … }</div><div class=""><br class=""></div><div class="">looks up T in the enclosing scope. That potentially becomes somewhat ambiguous if we want to be able to introduce new type parameters in a specific extension, which comes up if we implement something akin to C++’s partial specialization. For example, extending an array of optional values:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>extension X&lt;T?&gt; { } // no, looks up T in the enclosing scope</div><div class=""><br class=""></div><div class="">There are syntactic ways around this. For example, putting the type parameters after “extension”:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>extension&lt;T&gt; Array&lt;T?&gt; { }</div><div class=""><br class=""></div><div class="">or even spell it with the syntactic sugar:</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>extension&lt;T&gt; [T?] {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>func nonnilValues() -&gt; [T] {</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">                </span>}</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div></div><div class=""><br class=""></div><div class="">to open the flood gates yet further.</div><div class=""><br class=""></div><div class="">I don’t see any rush to push the syntax through swift-evolution: you can work on the implementation using the “Element == Int” syntax (which should work regardless of whether there’s a more concise way to spell the same intent) and discuss/add the syntactic sugar later.</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>