[swift-evolution] [RFC] #Self

Vladimir.S svabox at gmail.com
Thu May 12 10:19:43 CDT 2016


Inline

On 11.05.2016 21:31, Matthew Johnson wrote:
>
>
> Sent from my iPad
>
>> On May 11, 2016, at 11:43 AM, Vladimir.S <svabox at gmail.com> wrote:
>>
>> Well, I believe I understand now what *you mean* under #Self. OK.
>> Thank you for clarifications. In my terminology 'this' could be called
>> BaseSelf. Your "thing" just can not be called #Self. IMO in initial
>> proposal #Self means not more than placeholder for the concrete type
>> name(inside type declaration or inside protocol).
>>
>> You propose just something different, more advanced than initial
>> #Self, you propose not some static "thing" but extended behavior if
>> #Self is a return type of protocol requirement.
>>
>> I strictly against to couple the initial proposal of #Self and your
>> proposal for extended features (for protocol conformance of
>> `->#Self`). Please be clear and obvious regarding the name of that
>> feature. I really think the behavior you propose can not be called
>> #Self(or Type)
>>
>> What I suggest: de-couple these proposals to:
>>
>> a) initial proposal of #Self as placeholder for concrete type name.
>> Choose the name for it. Probably StaticSelf, or Type, or somehting
>> else
>>
>> b) your proposal for BaseSelf feature. I'll definitely support it with
>> just name changed to clearly reflect its propose.
>
> I don't believe the initial proposal stated how it would behave in a
> protocol.  However I do believe the feature I am talking about covers
> all of the use cases Erica had in mind while also providing useful
> semantics when used in a protocol requirement.  Erica, please correct me
> if I'm wrong.

Well.. Yes, I also don't see statements regarding how `->#Self` would 
behave in a protocol in initial proposal. *This is why* I suggest to 
de-couple what *was* in initial proposall, and what you are suggesting as 
*addition* to the proposal.

Again. I fully support the behavior you suggest, but I strongly feel like 
'that' #Self can't be named #Self, as some derived(from conformed class) 
class X does not return 'self'. It return 'self or one of base classes'. 
Let's call it 'SelfOrBase' for now.

What we have now:

protocol A {
   func f1() -> Self
   func f2(s: Self)
}

struct S: A {
   func f1() -> S/*#Self*/ {return self}
   func f2(s: S/*#Self*/) {}
}

class C: A {
   func f1() -> Self /*only Self, can't write C here*/ {return self}
   func f2(s: C/*#Self*/) {}
}

final class FC: A {
   func f1() -> Self /*can write FC here, ==#Self*/ {return self}
   func f2(s: FC/*#Self*/) {}
}

I believe, for clarity, after we introduce #Self(or whatever name it will 
have) we need to require `#Self` in protocol as type of method parameter:

protocol A {
   func f1() -> Self // this could be Self and could be #Self
   func f2(s: #Self) // this always will be #Self in implementation

   // this should not be allowed any more
   //func f2(s: Self)
}

struct S: A {
   // as you see we'd have `->#Self` in implementation
   func f1() -> #Self {return self}
   func f2(s: #Self) {}
}

class C: A {
   func f1() -> Self /*only Self, can't write C here*/ {return self}
   func f2(s: #Self) {}
}

final class FC: A {
   func f1() -> Self /*can write FC here, ==#Self*/ {return self}
   func f2(s: #Self) {}
}

The above is what *I think* was in initial proposal regarding #Self.

About your suggestion. I just trying to understand it in details.
Please point me where I understand your suggestion incorrectly.

Do you think about such start points? :

class Base {
   func f() -> Base  {return Base()}
}

class Derived1: Base {
   override func f() -> Derived1  {return Derived1()}
}

class Derived2: Base {
   override func f() -> Derived2  {return Derived2()}
}

If so, do you want to introduce such a protocol:

protocol A {
     func f() -> #Self
}

and then conforms Base class to it? :

extension Base : A {}

To be able to use :

let a : A = Derived2()
let some = a.f() // you expect some.dynamicType is Derived2

I understand correctly?

At this point you say that all is OK and #Self works as expected, each 
class returns really #Self and protocol conformation applied.
But I believe this is not true. We *can* have this:

class Derived3: Base {
   // no override for f(). will be used from base class
}

Now. What does Derived3().f() returns? It returns instance of Base.
Is #Self for Derived3 equals to `Base` ? No.
Does Derived3 conforms to protocol `A` in this case? No.
But it *must* conform as you think you can conform its base class.
This is the problem I see.

This is why I think it must be something separate from #Self, like 
SelfOrBase - in this case, protocol will looks like:

protocol A {
     func f() -> SelfOrBase
}

then you can conform Base to A,

extension Base : A {}

and Derived3 fully conforms to this protocol(it returns instance of base 
class), all is OK and all is consistent.

If I'm wrong somewhere please point me with clarification. Thank you.

>
> You want to make the semantics of #Self / Type be covariant when used in
> a protocol requirement.  This makes no sense to me as it is explicitly
> *not* covariant when used within a class declaration.  We already have a
> covariant construct (Self) and the proposal is to introduce an invariant
> construct (#Self or Type).  The invariant semantic should be consistent
> regardless of whether it is used in a protocol requirement or a type
> declaration.
>
> IMO BaseSelf is a poor choice of name for something that is supposed to
> be valid syntax in value types as well as classes.
>
>>
>>> On 11.05.2016 18:58, Matthew Johnson wrote: 'f' would return E for
>>> E, F and G.  Because the conformance is declared by E the
>>> requirement to return #Self is fixed as an invariant requirement to
>>> return E for all potential subclasses.
>>>
>>>>>
>>>>> Probably you(we) need another proposal, like BaseSelf (or
>>>>> SuperSelf) that means "this class or any its base class", then I
>>>>> understand how such a `f()->BaseSelf` protocol requirement can
>>>>> be applied to E class and also be true for F&G classes (as f()
>>>>> inherited from base class will return instance of E which is
>>>>> base for both).
>>> This is exactly what #Self (or Type) does.  The behavior you have
>>> been describing is the behavior of Self which already exists.
>>>
>
>


More information about the swift-evolution mailing list