Skip to content

Instantly share code, notes, and snippets.

@Anton3
Created November 8, 2016 20:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Anton3/ba56a29986c59e9595368be3cb02fb1b to your computer and use it in GitHub Desktop.
Save Anton3/ba56a29986c59e9595368be3cb02fb1b to your computer and use it in GitHub Desktop.

Nil struct

Introduction

Change nil literal type from () to Nil. Before:

public protocol ExpressibleByNilLiteral {
  init(nilLiteral: ())
}

After:

public struct Nil {
  init()
}
public protocol ExpressibleByNilLiteral {
  associatedtype NilLiteralType = Nil
  init(nilLiteral: NilLiteralType)
}

Swift-evolution thread: Discussion thread topic for that proposal

Motivation

Currently, nil differs from other literals: it doesn't have its own type. But in some cases we want to deal directly with it, without creating any instances.

The most important use case is comparison of an Optional to nil. Currently, this operation is implemented using a hidden struct _OptionalNilComparisonType, which is needed precisely because because nil does not have its own type. Removal of such underscored types is one of the goals stated in Generics manifesto.

Additionally, declaration of ExpressibleByNilLiteral differs from all other Expressibles, because it doesn't have a Literal type. It is generally beneficial to eliminate special cases.

Proposed solution

Introduce a struct Nil, which becomes the default type for nil literals:

public struct Nil : ExpressibleByNilLiteral {
  init()
  init(nilLiteral: NilLiteralType)
}

let a = nil
print(type(of: a))   //=> Nil

Rewrite ExpressibleByNilLiteral:

public protocol ExpressibleByNilLiteral {
  associatedtype NilLiteralType = Nil
  init(nilLiteral: NilLiteralType)
}

Make use of Nil in the standard library:

public func == <T>(left: T?, right: Nil)
public func == <T>(left: Nil, right: T?)
public func != <T>(left: T?, right: Nil)
public func != <T>(left: Nil, right: T?)
public func ~= <T>(left: Nil, right: T?)

Source compatibility

Nil identifier is taken, therefore applications that already use it will stop compiling. Automatic migration is somewhat possible by renaming of the old entity; manual migration is recommended.

Applications that use declare ExpressibleByNilLiteral conformances will stop compiling. Automatic migration is possible.

Effect on ABI stability

Applications that use Nil identifier will have to make ABI-breaking changes.

Otherwise, the change can mostly be applied in an ABI-compatible manner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment