<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>Recursive protocol constraints is one small-looking feature that could greatly improve the standard library. The generics manifesto describes it this way:</div><div><br></div><div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;"><span style="background-color: rgba(255, 255, 255, 0);">"Currently, an associated type cannot be required to conform to its enclosing protocol (or any protocol that inherits that protocol). For example, in the standard library <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">SubSequence</code> type of a <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">Sequence</code> should itself be a <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">Sequence</code>:</span></p><div class="highlight highlight-source-swift" style="box-sizing: border-box; margin-bottom: 16px;"><pre style="box-sizing: border-box; word-wrap: normal; margin-top: 0px; margin-bottom: 0px; padding: 16px; overflow: auto; line-height: 1.45; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; word-break: normal;"><font face="UICTFontTextStyleBody"><span style="white-space: normal; background-color: rgba(255, 255, 255, 0);"><span class="pl-k" style="box-sizing: border-box;">protocol</span> <span class="pl-en" style="box-sizing: border-box;">Sequence</span> {
<span class="pl-k" style="box-sizing: border-box;">associatedtype</span> <span class="pl-v" style="box-sizing: border-box;">Iterator</span> : <span class="pl-e" style="box-sizing: border-box;"><span class="pl-c1" style="box-sizing: border-box;">IteratorProtocol</span></span>
...
<span class="pl-k" style="box-sizing: border-box;">associatedtype</span> <span class="pl-v" style="box-sizing: border-box;">SubSequence</span> : <span class="pl-e" style="box-sizing: border-box;"><span class="pl-c1" style="box-sizing: border-box;">Sequence</span> <span class="pl-c" style="box-sizing: border-box;">// currently ill-formed, but should be possible</span></span>
<span class="pl-e" style="box-sizing: border-box;"><span class="pl-c" style="box-sizing: border-box;"></span></span>}</span></font></pre></div><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;"><span style="background-color: rgba(255, 255, 255, 0);">The compiler currently rejects this protocol, which is unfortunate: it effectively pushes the <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">SubSequence</code>-must-be-a-<code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">Sequence</code> requirement into every consumer of <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">SubSequence</code>, and does not communicate the intent of this abstraction well."</span></p><h3 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25;"><a id="user-content-nested-generics" class="anchor" href="https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#nested-generics" aria-hidden="true" style="box-sizing: border-box; text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"></svg><font color="#000000" size="3"><span style="background-color: rgba(255, 255, 255, 0);"><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></span></font></a></h3>It's actually slightly worse than the above implies: the standard library has a pile of underscore-prefixed protocols (e.g., _Sequence) specifically to dodge this restriction. They are ugly, and we want them to go away. Many of these places are marked with an ABI FIXME in the standard library sources. </div><div><br></div><div>Would someone like to write up a proposal for this feature? The syntax and basic semantics are pretty direct, but a proposal should also capture the expected effects on the standard library, particularly when combined with where clauses on associated types.</div><div><br></div><div>I also have a nagging feeling that we will need some form of restrictions on this feature for implementation reasons, e.g., because some recursive constraints will form unsolvable systems.</div><div><br></div><div>For reference, we've already been implementing this feature. Some information about the compiler internal issues is captured at:</div><div><br></div><div> <a href="https://gist.github.com/DougGregor/e7c4e7bb4465d6f5fa2b59be72dbdba6">https://gist.github.com/DougGregor/e7c4e7bb4465d6f5fa2b59be72dbdba6</a></div><div><br></div><div> - Doug</div><div><br></div><div><br></div><div><br><div>Sent from my iPhone</div></div></body></html>