> On Jan 7, 2017, at 10:02 AM, Adrian Zubarev via swift-evolution 
> <[email protected]> wrote:
> 
> True, but there are a few edge cases where Self simply does not work. 
> 
> On classes the return type has the contract to return self.
> Even if we get SE–0068, will Self work in generic context like showed in OP 
> with Current?
> #1 Using value semantics on classes means that the returned instance is a new 
> instance different from self.
> 
> Assume this small protocol:
> 
> // Follow value semantics == immutability
> protocol Cloned : class {
>       func cloned() -> Self
> }
> 
> class A : Cloned {
>      func cloned() -> Self {
>            return /* copy of self */ <— ERROR
>      }
> }
> One could workaround the problem and use final, but what if the class meant 
> to be subtypeable? Self simply does not work in this scenario. The only 
> workaround here would be associatedtype T as the return type instead of Self, 
> but is this really what we wanted to describe in our protocol. T could be 
> anything else and we cannot constrain it like: associatedtype T : Self.
> 
> Either a static Self is needed or we need to remove the restriction that on 
> the conforming non-final class we cannot overrider Self with the TypeName, 
> like on any of it’s subtype.
> 
> 

Actually it is possible to construct values of type “Self” inside a class that 
are not “self”. type(of: self) returns a metatype of type Self.Type, which you 
can then invoke required initializers on to get a new instance of type ‘Self’.

> \2# On non-final classes from the generic context something like this 
> following snippet seems to be odd if Self is dynamic.
> 
> // What is the constraint here? `Self` is dynamic.  
> // I might want to cast to `A` where `Self` in this case would be 
> e.g.`NSObject`
> // but the dynamic type of the current instance is `B`.
> // The relationship might look like this: B : A : NSObject
> // `Self` would refer to `B`, but `A` is not a subclass of `B`.
> extension AReallyLongNonFinalClassName {
>     func casted<T : Self>() -> T { ... }
> }
> 
> // In contrast the proposed static `Self` as `Current`
> extension AReallyLongNonFinalClassName {
>     func casted<T : Current>() -> T { ... }
> }
> 

Using the dynamic “Self” like that would not be allowed even with SE-0068, 
because of implementation constraints — only a static class name can appear in 
a superclass constraint like that, not a type parameter.

Slava

> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 7. Januar 2017 um 18:34:38, Xiaodi Wu ([email protected] 
> <mailto:[email protected]>) schrieb:
> 
>> `Self` _always_ refers to the dynamic type of `self`. It just happens to be 
>> that in the case of structs the dynamic type is the same as the static type. 
>> The idea of having a shorthand for the containing type (spelled #Self or 
>> StaticSelf) was discussed during consideration of SE-0068. The accepted 
>> version of the proposal rejects that idea, having adopted the position that 
>> "You will continue to specify full type names for any other use. Joe Groff 
>> writes, 'I don't think it's all that onerous to have to write ClassName.foo 
>> if that's really what you specifically mean.'"
>> 
>> 
>> On Sat, Jan 7, 2017 at 11:14 AM, thislooksfun via swift-evolution 
>> <[email protected] <mailto:[email protected]>> wrote:
>> I like this idea, however, if I understand the proposal correctly, I think 
>> that the naming would make more sense the other way around. `Self` is, at 
>> least in my head, tied directly and statically to the enclosing type, where 
>> as `Current` sounds more dynamic, and could change from place-to-place.
>> 
>> -thislooksfun (tlf)
>> 
>>> On Jan 7, 2017, at 4:38 AM, Adrian Zubarev via swift-evolution 
>>> <[email protected] <mailto:[email protected]>> wrote:
>>> 
>>> Hi Swift community,
>>> 
>>> I’d like to talk to about current Self keyword. If I’m not totally mistaken 
>>> then the current Self has a few meanings:
>>> 
>>> Refer to the current type, or refer to the dynamic type for non-final 
>>> classes inside containing type (SE–0068 - not yet implemented).
>>> For non-final class types use Self as return type on the conforming super 
>>> type (or return an instance of receiver Self).
>>> Let me visualize the behaviors quickly in some short code snippet:
>>> 
>>> protocol Foo {
>>>     func foo(_ f: Self) -> Self
>>> }
>>> 
>>> class A : Foo {
>>>     // forced to use `A` as parameter type and `Self` as return type
>>>     func foo(_ f: A) -> Self { return self }
>>>     // Returning `A()` would cause an error: Cannot convert return 
>>> expression of type 'A' to return type 'Self'
>>>     func bar() -> A { return A() /* or self */ }
>>>     func zoo() -> Self { return /* only */ self }
>>> }
>>> 
>>> class B : A {
>>>     // Both is fine `B` or `Self` as the return type
>>>     // If `B` is used you can return a different instance like `B()`
>>>     // `Self` does only allow `self` to be used here
>>>     override func foo(_ f: A) -> B { return self }
>>> }
>>> 
>>> struct D : Foo {
>>>     // No `Self` allowed here at all
>>>     func foo(_ f: D) -> D { return self /* or D() */ }
>>> }
>>> The behavior of Self is a little magical, because it sometimes refers to 
>>> the current type it is used in, or it has a contract of using self.
>>> 
>>> I propose of introducing a new keyword called Current to solve a few 
>>> problems here.
>>> 
>>> Self on parameter types would be disallowed for protocol members, because 
>>> conformances to that protocol already disallow that (see A above). Instead 
>>> one would use Current and get the correct meaning.
>>> 
>>> protocol Boo {
>>>     func boo(_ b: Current) -> Self
>>> }
>>>       
>>> procotol Loo {
>>>     func loo() -> Current
>>> }
>>>       
>>> class X : Boo, Loo {
>>>     func boo(_ b: X) -> Self { return self }
>>>     func loo() -> X { return self /* or X() */ }
>>> }
>>>       
>>> final class Y : Boo {
>>>     func boo(_ b: X) -> Y { return self /* or Y */ }
>>> }
>>> Using Self inside the containing type would always mean as one would refer 
>>> to the dynamic type, like the magical syntax function type(of:) does.
>>> 
>>> Current can only refer to the current containing type.
>>> 
>>> On classes Self has always the contract of returning self.
>>> 
>>> Self could be discouraged in favor of Current on value types, as a 
>>> shorthand to refer to the containing type.
>>> 
>>> Generics could benefit from Current too:
>>> 
>>> extension AReallyLongNonFinalClassName {
>>>     func casted<T : Current>() -> T { ... }
>>> }
>>> // `Self` wouldn't here, because it would refer to the dynamic type
>>> #1 Would affect a lot of protocols which implies that it would affect ABI.
>>> 
>>> These are the first ideas I had in my mind. We can polish it further if it 
>>> receives positive and constructive feedback.
>>> 
>>> Best regards, 
>>> 
>>> 
>>> 
>>> 
>>> -- 
>>> Adrian Zubarev
>>> Sent with Airmail
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> [email protected] <mailto:[email protected]>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> 
> 
> 
> _______________________________________________
> 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

Reply via email to