<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 Dec 28, 2015, at 12:04 PM, Developer <<a href="mailto:devteam.codafi@gmail.com" class="">devteam.codafi@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class="">That doesn't look like a variance issue to me, that's about the same "information" invariant I talked about before. The former works because self resolves to an invariant type, the type of the implementing structure, which satisfies the requirement Self introduces. The latter does not because Self indicates a level of specificity C cannot guarantee. Self is magic, but it is also implemented as a generic parameter. So think of it this way:</div><div class=""><br class=""></div><div class="">protocol Q {</div><div class=""> func bar<T>() -> T { return Q() }</div><div class="">}</div><div class=""><br class=""></div><div class="">You wouldn't expect that to compile, would you?</div></div></div></blockquote><div><br class=""></div>It actually does work for structs and for final classes because Self becomes invariant when used in a return type position for them.</div><div><br class=""></div><div>protocol Q {<br class=""> func bar() -> Self<br class="">}</div><div><br class=""></div><div>final class C: Q {<br class=""> func bar() -> C { return C() }<br class="">}</div><div><br class=""></div><div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class=""><br class=""><div class="">~Robert Widmann</div></div><div class=""><br class="">2015/12/28 12:49、Matthew Johnson <<a href="mailto:matthew@anandabits.com" class="">matthew@anandabits.com</a>> のメッセージ:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Dec 28, 2015, at 11:19 AM, Developer <<a href="mailto:devteam.codafi@gmail.com" class="">devteam.codafi@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class=""><span class=""></span></div><div class=""><div class="">My understanding of Self is that it is a special generic parameter resolved by the type system to the type of the implementing structure. That resolution <b class="">must be invariant </b>because the implementing structure (here, non-final classes) can choose to yank the protocol's invariants out from under you when it is subclassed. Sure, retroactively, you can make things conform, but you also can't completely guarantee type safety with any kind of variance in Self in all cases. </div></div></div></div></blockquote><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class=""><div class=""><br class=""></div><div class="">On the other hand, using the protocol itself in either position says that you only wish to restrict yourself to the protocol itself, not some specific implementation. You are necessarily specifying an upper bound (here C) on the amount of "information" you can get out of the type, so it is possible to introduce variance because you will never violate the protocol's invariants by returning a subtype with a legal conformance.</div><div class=""><br class=""></div><div class="">Self doesn't mean two different things, your protocol declarations do!</div></div></div></div></blockquote><div class=""><br class=""></div><div class="">My mind must be a little bit foggy this morning. This works:</div><div class=""><br class=""></div><div class="">extension C: Q {<br class=""> func bar() -> Self { return self }<br class="">}</div><div class=""><br class=""></div><div class="">What doesn’t work, regardless of whether C is final or not, is this:</div><div class=""><br class=""></div><div class="">extension C: Q {</div><div class=""> // Cannot convert return expression of type ‘C’ to return type ‘Self'<br class=""> func bar() -> Self { return C() }<br class="">}</div><div class=""><br class=""></div><div class="">In order for classes to meet a protocol requirement with Self in the return position you must specify Self (rather than the conforming type) as the return type for the method. Self in the return position of a method is treated as covariant.</div><div class=""><br class=""></div><div class="">In order for classes to meet a protocol requirement with Self in parameter position you must specify the type of the conforming class (you cannot specify Self in an argument position). Obviously the type of the conforming class is invariant.</div><div class=""><br class=""></div><div class="">This is the sense in which Self in protocol declarations is inconsistent. The requirements on conforming types are different - invariance for Self parameters and covariance for Self return types.</div><div class=""><br class=""></div><div class="">IMO it would be much more clear if this distinction was explicit rather than implicit based on the location of Self. It would also be extremely useful in some cases to be able to specify an invariant `ConformingSelf` return type.</div><div class=""><br class=""></div><div class=""><br class=""></div><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div class=""><div class=""><br class=""><div class="">~Robert Widmann</div></div><div class=""><br class="">2015/12/28 11:49、Matthew Johnson via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> のメッセージ:<br class=""><br class=""></div><blockquote type="cite" class=""><div class=""><span class="">I have brought up the idea of a non-covarying Self a few times. </span><br class=""><span class=""></span><br class=""><span class="">I was surprised to realize that Self is actually non-covarying when used for parameters in protocol declarations!</span><br class=""><span class=""></span><br class=""><span class="">Here is an example demonstrating this:</span><br class=""><span class=""></span><br class=""><span class="">protocol P {</span><br class=""><span class=""> func foo(s: Self)</span><br class=""><span class="">}</span><br class=""><span class="">protocol Q {</span><br class=""><span class=""> func bar() -> Self</span><br class=""><span class="">}</span><br class=""><span class=""></span><br class=""><span class="">class C: P {</span><br class=""><span class=""> // this works! Self as an argument type in the protocol declaration does not covary</span><br class=""><span class=""> func foo(c: C) {}</span><br class=""><span class="">}</span><br class=""><span class=""></span><br class=""><span class="">class D: C {}</span><br class=""><span class=""></span><br class=""><span class="">extension C: Q {</span><br class=""><span class=""> // method ‘bar()’ in non-final class ‘C’ must return ‘Self’ to conform to protocol ‘Q'</span><br class=""><span class=""> func bar() -> C { return self } </span><br class=""><span class="">}</span><br class=""><span class=""></span><br class=""><span class=""></span><br class=""><span class="">It doesn’t make sense to allow a co-varying Self for parameters so I can understand how the current state might have arisen. At the same time, using Self to mean two different things is inconsistent, confusing and it doesn’t allow us to specify a non-covarying Self as a return type in protocol requirements. </span><br class=""><span class=""></span><br class=""><span class="">As I have pointed out before, the ability to specify a non-covarying Self as a return type would make it possible to design a protocol that can be retroactively conformed to by non-final classes (such as those in Apple’s frameworks).</span><br class=""><span class=""></span><br class=""><span class="">I think it would be a very good idea to introduce a non-covarying Self which would specify the type that adds conformance to the protocol and require this Self to be used in places where covariance is not possible, such as parameter types. It would also be allowed elsewhere, such as return types, making it easier to conform non-final classes when covariance is not required by the protocol.</span><br class=""><span class=""></span><br class=""><span class="">One possible name is `ConformingSelf`. One thing I like about this name is that it makes it very clear that it is the type that introduces protocol conformance.</span><br class=""><span class=""></span><br class=""><span class="">I’m interested in hearing thoughts on this.</span><br class=""><span class=""></span><br class=""><span class="">Matthew</span><br class=""><span class="">_______________________________________________</span><br class=""><span class="">swift-evolution mailing list</span><br class=""><span class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a></span><br class=""><span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br class=""></div></blockquote></div></div></div></blockquote></div><br class=""></div></blockquote></div></div></blockquote></div><br class=""></body></html>