Permalink
Fetching contributors…
Cannot retrieve contributors at this time
96 lines (74 sloc) 3.13 KB

Constraining AnySequence.init

Introduction

In order to allow AnySequence delegate calls to the underlying sequence, its initializer should have extra constraints.

Swift Evolution Discussion

Motivation

At the moment AnySequence does not delegate calls to SequenceType protocol methods to the underlying base sequence, which results in dynamic downcasts in places where this behavior is needed (see default implementations of SequenceType.dropFirst or SequenceType.prefix). Besides, and this is even more important, customized implementations of SequenceType methods would be ignored without delegation.

Proposed solution

See the implementation in this PR.

In order for this kind of delegation to become possible, _SequenceBox needs to be able to 'wrap' not only the base sequence but also its associated SubSequence. So instead of being declared like this:

internal class _SequenceBox<S : SequenceType>
    : _AnySequenceBox<S.Generator.Element> { ... }

it would become this:

internal class _SequenceBox<
  S : SequenceType
  where
    S.SubSequence : SequenceType,
    S.SubSequence.Generator.Element == S.Generator.Element,
    S.SubSequence.SubSequence == S.SubSequence
> : _AnySequenceBox<S.Generator.Element> { ... }

Which, in its turn, will lead to AnySequence.init getting a new set of constraints as follows.

Before the change:

public struct AnySequence<Element> : SequenceType {
  public init<
    S: SequenceType
    where
      S.Generator.Element == Element
  >(_ base: S) { ... }
}

After the change:

public struct AnySequence<Element> : SequenceType {
  public init<
    S: SequenceType
    where
      S.Generator.Element == Element,
      S.SubSequence : SequenceType,
      S.SubSequence.Generator.Element == Element,
      S.SubSequence.SubSequence == S.SubSequence
  >(_ base: S) { ... }
}

These constraints, in fact, should be applied to SequenceType protocol itself (although, that is not currently possible), as we expect every SequenceType implementation to satisfy them already. Worth mentioning that technically S.SubSequence.SubSequence == S.SubSequence does not have to be this strict, as any sequence with the same element type would do, but that is currently not representable.

Impact on existing code

New constraints do not affect any built-in types that conform to SequenceType protocol as they are essentially constructed like this (SubSequence.SubSequence == SubSequence). 3rd party collections, if they use the default SubSequence (i.e. Slice), should also be fine. Those having custom SubSequences may stop conforming to the protocol.