> 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