[Draft] Introducing StaticSelf, an Invariant Self


(Thorsten Seitz) #1

Why did you decide to drop the `#` ? As `StaticSelf` will be resolved on
compilation time like #file etc ? I feel like this is inconsistent solution.

# is not needed just like it is not needed for generic type parameters which are also resolved at compilation time.
#file etc. insert information about artefacts outside of the language (i.e. the name of the file wherein the code resides) which is very different.

-Thorsten

Also, do you expect this will work:

protocol A {
func g()->StaticSelf
}

class B: A {
func g()->StaticSelf {return B()}
}

class C: B {
//func f(s: C) {}
}

func x(a: A ){
var xx : A = a.g() // ?
print(xx)
}

func z<T: A>(t: T) {
let u = t.g() // ?
print(u)
}

let c = C()
z(c)
x(c)

Erica Sadun and I have written a proposal are following up the recent
discussion thread "[RFC] #Self” with a proposal to introduce StaticSelf, an
invariant Self.

The recent discussion can be found
here: http://thread.gmane.org/gmane.comp.lang.swift.evolution/16565

The proposal can be found
here: https://github.com/anandabits/swift-evolution/blob/static-self/proposals/NNNN-static-self.md

We look forward to continuing the discussion. We plan to submit a PR in
the near future after incorporating your final feedback.

Thanks,
Matthew

Introducing StaticSelf, an Invariant Self

* Proposal: TBD
* Authors: Matthew Johnson <https://github.com/anandabits>, Erica Sadun
<https://github.com/erica>

* Status: TBD
* Review manager: TBD

Introduction

This proposal introduces a new keyword that provides consistent invariant
type semantics in all contexts.

/The Swift-evolution thread about this topic can be found here: [RFC] #Self
<http://thread.gmane.org/gmane.comp.lang.swift.evolution/16565>/

Motivation

The distinction between covariant and non-covariant type references come
into play when
conforming non-final classes to protocols. Fixing a protocol requirement to
a covarying type
means that a method returning |Self| must be overriden by all subclasses in
order to return
the correct, matching type.

This proposal builds on the covariant construct |Self| accepted in SE–0068
<https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md>

to introduce an invariant type identifier. It enables protocol declarations
to consistently
refer to a type that is fixed at compile time. This ensures that subclasses
can inherit
protocol implementations without having to re-implement that code at each
level of
inheritance.

Under this proposal, a new identifier keyword is fixed in use /at the point
of protocol conformance/
to the static type of that construct.

class A: MyProtocol|

The invariant |StaticSelf| identifier will always refer to |A|,
unlike |Self|, which is covarying and refers to
the type of the actual instance. Since multiple inheritance for
non-protocol types is disallowed,
this establishes this invariant type identifier with no possibility for
conflict.

Consider the following example, under the current system:

protocol StringCreatable { static func createWithString(s: String) -> Self

} extension NSURL: StringCreatable { // cannot conform because NSURL is
non-final // error: method 'createWithString' in non-final class 'NSURL'
must return `Self` to conform to protocol 'A' }|

Introducing a static, invariant version of |Self| permits the desired
conformance:

protocol StringCreatable { static func createWithString(s: String) ->

StaticSelf } extension NSURL: StringCreatable { // can now conform conform
because NSURL is fixed and matches the static // type of the conforming
construct. Subclasses need not re-implement // NOTE: the return type can be
declared as StaticSelf *or* as NSURL // they are interchangeable static
func createWithString(s: String) -> StaticSelf { // ... } }|

Additional Utility

The utility of |StaticSelf| is not limited to protocols. A secondary use
enables code to refer to the lexical context’s current type without
explicitly mentioning its name. This provides a useful shortcut when
referencing static type members with especially long names and when
re-purposing code between types.

class StructWithAVeryLongName { static func foo() -> String { // ... } func

bar() { // ... let s = StaticSelf.foo() // } }|

Detailed Design

This proposal introduces |StaticSelf|, a new keyword that may be used in
protocols to refer to the invariant static type of a conforming
construct. |StaticSelf| may also be used in the lexical context of any type
declaration. In such use, the keyword is identical to spelling out the full
name of that type.

Impact on existing code

Being additive, there should be no impact on existing code.

Alternatives considered

The keyword is not fixed at this time. Alternatives that have been
discussed include |StaticType|, |InvariantSelf|, |SelfType|, or |Type|. The
community is welcome to bikeshed on the most clear and concise name for
this keyword.

···

Am 13. Mai 2016 um 09:36 schrieb "Vladimir.S via swift-evolution" <swift-evolution@swift.org>:
On 13.05.2016 3:49, Matthew Johnson via swift-evolution wrote:

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org

https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution