<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"><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=""><div class="">(This is my first time on swift-evolution / Mailman, I apologize for any formatting errors)</div><div class=""><br class=""></div><div class="">As we know, the following fails:</div><div class="">​</div><div class="">protocol _Protocol</div><div class="">{</div><div class="">&nbsp; &nbsp; static var _Parameter: Any.Type { get }</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; var nonGenericVariable: Int { get }</div><div class="">&nbsp; &nbsp; var _parameter: Any { get set }</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; func _inputParameter(_: Any) -&gt; Any?</div><div class="">}</div><div class="">​</div><div class="">Protocol.self</div><div class="">​</div><div class="">with the error:</div><div class="">​</div><div class="">protocol 'Protocol' can only be used as a generic constraint because it has Self or associated type requirements</div><div class="">​</div><div class="">For quite some time, I have been using a particular workaround for this:</div><div class="">​</div><div class="">protocol _Protocol</div><div class="">{</div><div class="">&nbsp; &nbsp; static var _Parameter: Any.Type { get }</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; var nonGenericVariable: Int { get }</div><div class="">&nbsp; &nbsp; var _parameter: Any { get set }</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; func _inputParameter(_: Any) -&gt; Any?</div><div class="">}</div><div class="">​</div><div class="">extension _Protocol where Self: Protocol</div><div class="">{</div><div class="">&nbsp; &nbsp; static var _Parameter: Any.Type</div><div class="">&nbsp; &nbsp; {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; return Parameter.self</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; var _parameter: Any</div><div class="">&nbsp; &nbsp; {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; get</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return parameter</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; set</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parameter = newValue as! Parameter</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; func _inputParameter(parameter: Any) -&gt; Any?</div><div class="">&nbsp; &nbsp; {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; return (parameter as? Parameter).map(inputParameter)</div><div class="">&nbsp; &nbsp; }</div><div class="">}</div><div class="">​</div><div class="">protocol Protocol: _Protocol</div><div class="">{</div><div class="">&nbsp; &nbsp; typealias Parameter</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; var nonGenericVariable: Int { get }</div><div class="">&nbsp; &nbsp; var parameter: Parameter { get set }</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; func inputParameter(_: Parameter) -&gt; Parameter</div><div class="">}</div><div class="">​</div><div class="">And it has worked well so far.&nbsp;</div><div class="">​</div><div class="">The idea is to let the compiler generate these type-erased ‘versions’ on demand, using syntax like:</div><div class=""><br class=""></div><div class="">Protocol.Opaque&nbsp;</div><div class="">​</div><div class="">The rough procedure of creating a type-erased version for a given protocol is as follows:</div><div class=""><br class=""></div><div class="">- Create a protocol with an underscore prefixed to the name of the target protocol.</div><div class=""><br class=""></div><div class="">- Expose all the non-ATD (self or associated type dependent) constructs as requirements (essentially just copying the declarations)&nbsp;</div><div class=""><br class=""></div><div class="">- Expose all the ATD constructs as requirements with associated types replaced with “Any”, with an underscore prefixed to their name changing the return value of functions accepting ATD inputs to an optional version of the same type. &nbsp;</div><div class=""><br class=""></div><div class="">- Extend the target protocol with implementations of these type-erased ‘versions’ of ATD constructs. For variables, a computed property is provided which returns the target variable, and force casts newValue in the setter (if any) to the required ATD type. For functions, the parameters undergo an attempted cast to the required ATD types, and are then mapped over the original implementation. Functions without ATD parameters can return just Any, because there is no casting involved.&nbsp;</div><div class=""><br class=""></div><div class="">- Initializers become static functions with prefixed underscores, returning an Optional&lt;Protocol.Opaque&gt;</div><div class=""><br class=""></div><div class="">I admit that I don’t have a plan on how this should be implemented. My fear is that it require tremendous amounts of metadata, bloating the binary size, and so I have submitted this as an idea and not a proposal.</div><div class=""><br class=""></div><div class="">I have created a gist (<a href="https://gist.github.com/vmanot/888afc3f26caf142cd21" class="">https://gist.github.com/vmanot/888afc3f26caf142cd21</a>) as a demonstration.&nbsp;</div><div class=""><br class=""></div><div class="">This pattern has helped on innumerable occasions, and is used in my projects to allow some runtime tricks. It also helps me forward implementations in a way similar (behavior-wise) to “AnyGenerator”&nbsp;</div><div class=""><br class=""></div><div class=""><div class="">import Swift</div><div class=""><br class=""></div><div class="">struct AnyGenerator&lt;Element&gt;</div><div class="">{</div><div class="">&nbsp; &nbsp; var base: _GeneratorType</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; init&lt;G: protocol&lt;_GeneratorType, GeneratorType&gt; where G.Element == Element&gt;(base: G)</div><div class="">&nbsp; &nbsp; {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; self.base = base</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; mutating func next() -&gt; Element?</div><div class="">&nbsp; &nbsp; {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; return (base._next() as! Optional&lt;Element&gt;)</div><div class="">&nbsp; &nbsp; }</div><div class="">}</div><div class=""><br class=""></div><div class="">AnyGenerator(base: [1, 2, 3].generate())</div></div><div class=""><br class=""></div><div class="">(I have tested this with an actual_GeneratorType implementation, and it works)</div><div class=""><br class=""></div><div class="">Please let me know what you think of this idea, and whether it is viable or not.</div><div class=""><br class=""></div></body></html>