+1. This should be fixed.
On 23.06.2016 22:53, Slava Pestov via swift-evolution wrote:
Consistent formal type for 'self' in class methods
* Proposal: SE-9999
<https://github.com/slavapestov/swift-evolution/blob/self-formal-type-in-class/proposals/9999-self-formal-type-in-class.md>
* Author: Slava Pestov <https://github.com/slavapestov>
* Status: Awaiting review
* Review manager: TBD
<https://github.com/slavapestov/swift-evolution/tree/self-formal-type-in-class#introduction>Introduction
This proposal makes the |self| value behave consistently whether or not
it is used from a method with a |Self| return type.
Swift-evolution thread: Discussion thread topic for that proposal
<http://news.gmane.org/gmane.comp.lang.swift.evolution>
<https://github.com/slavapestov/swift-evolution/tree/self-formal-type-in-class#motivation>Motivation
Right now, we exhibit inconsistent behavior when |self| is used as an
argument to a generic function, violating the principle of least surprise.
Consider the following code:
class Base {
@discardableResult
func methodWithDynamicSelf() -> Self {
doSomething(self)
return self
}
func methodWithoutDynamicSelf() {
doSomething(self)
}
}
class Derived : Base {}
func doSomething<T>(_ t: T) {
print(T.self)
}
Base().methodWithDynamicSelf()
Base().methodWithoutDynamicSelf()
Derived().methodWithDynamicSelf()
Derived().methodWithoutDynamicSelf()
Currently, it prints the following output:
Base
Base
Derived
Base
Note that there's no inconsistency when the method is called on the base
class. When called on the derived class however, we see that in a method
with a dynamic |Self| return type, the type of |self| is |Derived|,
whereas in a method with any other return type, the type of |self| is |Base|.
<https://github.com/slavapestov/swift-evolution/tree/self-formal-type-in-class#proposed-solution>Proposed
solution
The proposal is to change the type of |self| to always be |Self|, which
can be thought of as a special generic type parameter bound to the
dynamic type of the instance.
With this proposal, the above code will instead produce the following:
Base
Base
Derived
Derived
Here, the type of |self| would always be |Derived| when called on an
instance of the derived class.
Of course a more useful program could instead do something with the type
parameter |T|, such as constraining it to a protocol or a class with a
required initializer, and then using the type to construct a new instance
of the class.
This also dovetails nicely with SE-0068
<https://github.com/slavapestov/swift-evolution/blob/self-formal-type-in-class/proposals/0068-universal-self.md>.
Finally, it opens the door to generalizing dynamic |Self|, allowing it to
appear in covariant position within parameter types:
class ArtClass {
func paint(withBrush: (Self) -> ()) { ... }
}
This would allow a class to conform to a protocol with a requirement
written like the following, something that is currently not possible at all:
protocol OddProtocol {
func weaken<X, Y>((Self) -> (X) -> Y) -> (X) -> Y
}
<https://github.com/slavapestov/swift-evolution/tree/self-formal-type-in-class#detailed-design>Detailed
design
There's really not much more to say here. The code for typing |self| with
a dynamic |Self| is in place already, however enabling this change might
expose some new bugs we have not yet encountered, because currently,
methods with dynamic |Self| return type are relatively rare.
<https://github.com/slavapestov/swift-evolution/tree/self-formal-type-in-class#impact-on-existing-code>Impact
on existing code
This will have a small impact on existing code that uses a pattern
similar to the above.
<https://github.com/slavapestov/swift-evolution/tree/self-formal-type-in-class#alternatives-considered>Alternatives
considered
One alternative is to simply do nothing, but this makes the language less
consistent than it could be.
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution