Skip to content

Commit bbfc0aa

Browse files
committed
Merge pull request swiftlang#47 from moiseev/restricted-anyseq
Proposal to constrain AnySequence to allow delegation
2 parents ebc8212 + a353c1d commit bbfc0aa

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Constraining `AnySequence.init`
2+
3+
* Proposal:
4+
* [SE-0008](https://github.com/apple/swift-evolution/blob/master/proposals/0008-constrained-AnySequence.md)
5+
* Author(s): [Max Moiseev](https://github.com/moiseev)
6+
* Status: **Review**
7+
* Review manager: TBD
8+
9+
## Introduction
10+
11+
In order to allow `AnySequence` delegate calls to the underlying sequence,
12+
its initializer should have extra constraints.
13+
14+
## Motivation
15+
16+
At the moment `AnyCollection` does not delegate calls to `SequenceType` protocol
17+
methods to the underlying base sequence, which results in dynamic downcasts in
18+
places where this behavior is needed (see default implementations of
19+
`SequenceType.dropFirst` or `SequenceType.prefix`). Besides, and this is even
20+
more important, customized implementations of `SequenceType` methods would be
21+
ignored without delegation.
22+
23+
## Proposed solution
24+
25+
See the implementation in [this PR](https://github.com/apple/swift/pull/220).
26+
27+
In order for this kind of delegation to become possible, `_SequenceBox` needs to
28+
be able to 'wrap' not only the base sequence but also it's associated
29+
`SubSequence`. So instead of being declared like this:
30+
31+
~~~~Swift
32+
internal class _SequenceBox<S : SequenceType>
33+
: _AnySequenceBox<S.Generator.Element> { ... }
34+
~~~~
35+
36+
it would become this:
37+
38+
~~~~Swift
39+
internal class _SequenceBox<
40+
S : SequenceType
41+
where
42+
S.SubSequence : SequenceType,
43+
S.SubSequence.Generator.Element == S.Generator.Element,
44+
S.SubSequence.SubSequence == S.SubSequence
45+
> : _AnySequenceBox<S.Generator.Element> { ... }
46+
~~~~
47+
48+
Which, in it's turn, will lead to `AnySequence.init` getting a new set of
49+
constraints as follows.
50+
51+
Before the change:
52+
53+
~~~~Swift
54+
public struct AnySequence<Element> : SequenceType {
55+
public init<
56+
S: SequenceType
57+
where
58+
S.Generator.Element == Element
59+
>(_ base: S) { ... }
60+
}
61+
~~~~
62+
63+
After the change:
64+
65+
~~~~Swift
66+
public struct AnySequence<Element> : SequenceType {
67+
public init<
68+
S: SequenceType
69+
where
70+
S.Generator.Element == Element,
71+
S.SubSequence : SequenceType,
72+
S.SubSequence.Generator.Element == Element,
73+
S.SubSequence.SubSequence == S.SubSequence
74+
>(_ base: S) { ... }
75+
}
76+
~~~~
77+
78+
These constraints, in fact, should be applied to `SequenceType` protocol itself
79+
(although, that is not currently possible), as we expect every `SequenceType`
80+
implementation to satisfy them already.
81+
82+
## Impact on existing code
83+
84+
New constraints do not affect any built-in types that conform to
85+
`SequenceType` protocol as they are essentially constructed like this
86+
(`SubSequence.SubSequence == SubSequence`). 3rd party collections, if they use
87+
the default `SubSequence` (i.e. `Slice`), should also be fine. Those having
88+
custom `SubSequence`s may stop conforming to the protocol.

0 commit comments

Comments
 (0)