File: Generics.rst

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (950 lines) | stat: -rw-r--r-- 39,303 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
.. _Generics:

Generics in Swift
=================

Motivation
----------

Most types and functions in code are expressed in terms of a single, concrete
set of sets. Generics generalize this notion by allowing one to express types
and functions in terms of an abstraction over a (typically unbounded) set of
types, allowing improved code reuse. A typical example of a generic type is a
linked list of values, which can be used with any type of value. In C++, this
might be expressed as::

  template<typename T>
  class List {
  public:
    struct Node {
      T value;
      Node *next;
    };

    Node *first;
  };

where List<Int>, List<String>, and List<DataRecord> are all distinct types that
provide a linked list storing integers, strings, and DataRecords,
respectively. Given such a data structure, one also needs to be able to
implement generic functions that can operate on a list of any kind of elements,
such as a simple, linear search algorithm::

  template<typename T>
  typename List<T>::Node *find(const List<T>&list, const T& value) {
    for (typename List<T>::Node *result = list.first; result; result = result->next)
      if (result->value == value)
        return result;

    return 0;
  }

.. @test('compile', howmany = 'all', cmake_args = ['COMPILER', '${CMAKE_CXX_COMPILER}'])

Generics are important for the construction of useful libraries, because they
allow the library to adapt to application-specific data types without losing
type safety. This is especially important for foundational libraries containing
common data structures and algorithms, since these libraries are used across
nearly every interesting application.

The alternatives to generics tend to lead to poor solutions:

* Object-oriented languages tend to use "top" types (id in Objective-C,
  java.lang.Object in pre-generics Java, etc.) for their containers and
  algorithms, which gives up static type safety. Pre-generics Java forced the
  user to introduce run-time-checked type casts when interacting with containers
  (which is overly verbose), while Objective-C relies on id's unsound implicit
  conversion behavior to eliminate the need for casts.
* Many languages bake common data structures (arrays, dictionaries, tables) into
  the language itself. This is unfortunate both because it significantly
  increases the size of the core language and because users then tend to use
  this limited set of data structures for *every* problem, even when another
  (not-baked-in) data structure would be better.

Swift is intended to be a small, expressive language with great support for
building libraries. We'll need generics to be able to build those libraries
well.

Goals
-----

* Generics should enable the development of rich generic libraries that feel
  similar to first-class language features
* Generics should work on any type, whether it is a value type or some kind of
  object type
* Generic code should be almost as easy to write as non-generic code
* Generic code should be compiled such that it can be executed with any data
  type without requiring a separate "instantiation" step
* Generics should interoperate cleanly with run-time polymorphism
* Types should be able to retroactively modified to meet the requirements of a
  generic algorithm or data structure

As important as the goals of a feature are the explicit non-goals, which we
don't want or don't need to support:

* Compile-time "metaprogramming" in any form
* Expression-template tricks a la Boost.Spirit, POOMA

Polymorphism
------------

Polymorphism allows one to use different data types with a uniform
interface. Overloading already allows a form of polymorphism (ad hoc
polymorphism) in Swift. For example, given::

  func +(x : Int, y : Int) -> Int { add... }
  func +(x : String, y : String) -> String { concat... }

.. @example.replace('add...','return 1')
   example.replace('concat...','return ""')
   test()

we can write the expression "x + y", which will work for both integers and
strings.

However, we want the ability to express an algorithm or data structure
independently of mentioning any data type. To do so, we need a way to express
the essential interface that algorithm or data structure requires. For example,
an accumulation algorithm would need to express that for any type T, one can
write the expression "x + y" (where x and y are both of type T) and it will
produce another T.

Protocols
---------

Most languages that provide some form of polymorphism also have a way to
describe abstract interfaces that cover a range of types: Java and C#
interfaces, C++ abstract base classes, Objective-C protocols, Scala traits,
Haskell type classes, C++ concepts (briefly), and many more.  All allow one to
describe functions or methods that are part of the interface, and provide some
way to re-use or extend a previous interface by adding to it. We'll start with
that core feature, and build onto it what we need.

In Swift, I suggest that we use the term protocol for this feature, because I
expect the end result to be similar enough to Objective-C protocols that our
users will benefit, and (more importantly) different enough from Java/C#
interfaces and C++ abstract base classes that those terms will be harmful. The
term trait comes with the wrong connotation for C++ programmers, and none of our
users know Scala.

In its most basic form, a protocol is a collection of function signatures::

  protocol Document {
    func title() -> String
  }

Document describes types that have a title() operation that accepts no arguments
and returns a String. Note that there is implicitly a 'self' type,
which is the type that conforms to the protocol itself. This follows how most
object-oriented languages describe interfaces, but deviates from Haskell type
classes and C++ concepts, which require explicit type parameters for all of the
types. We'll revisit this decision later.

Protocol Inheritance
--------------------

Composition of protocols is important to help programmers organize and
understand a large number of protocols and the data types that conform to those
protocols. For example, we could extend our Document protocol to cover documents
that support versioning::

  protocol VersionedDocument : Document {
    func version() -> Int
  }

Multiple inheritance is permitted, allowing us to form a directed acyclic graph
of protocols::

  protocol PersistentDocument : VersionedDocument, Serializable {
    func saveToFile(_ filename : path)
  }

.. @example.prepend('struct path {} ; protocol Serializable {}')
    test(howmany='all')

Any type that conforms to PersistentDocument also conforms to VersionedDocument,
Document, and Serializable, which gives us substitutability.

Self Types
----------

Protocols thus far do not give us an easy way to express simple binary
operations. For example, let's try to write a Comparable protocol that could be
used to search for a generic find() operation::

  protocol Comparable {
    func isEqual(_ other : ???) -> Bool
  }

Our options for filling in ??? are currently very poor. We could use the syntax
for saying "any type" or "any type that is comparable", as one must do most OO
languages, including Java, C#, and Objective-C, but that's not expressing what
we want: that the type of both of the arguments be the same. This is sometimes
referred to as the binary method problem
(http://www.cis.upenn.edu/~bcpierce/papers/binary.ps has a discussion of this
problem, including the solution I'm proposing below).

Neither C++ concepts nor Haskell type classes have this particular problem,
because they don't have the notion of an implicit 'Self' type. Rather,
they explicitly parameterize everything. In C++ concepts::

  concept Comparable<typename T> {
    bool T::isEqual(T);
  }

.. @ignore()
.. We don't have a compiler for ConceptC++

Java and C# programmers work around this issue by parameterizing the
interface, e.g. (in Java)::

  abstract class Comparable<THIS extends Comparable<THIS>> {
    public bool isEqual(THIS other);
  }

.. @ignore()
.. This test just doesn't compile at the moment, but that represents a
   bug in Swift

and then a class X that wants to be Comparable will inherit from
Comparable<X>. This is ugly and has a number of pitfalls; see
http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6479372.

Scala and Strongtalk have the notion of the 'Self' type, which effectively
allows one to refer to the eventual type of 'self' (which we call
'self'). 'Self' (which we call 'Self' in Swift) allows us to express the
Comparable protocol in a natural way::

  protocol Comparable {
    func isEqual(_ other : Self) -> Bool
  }

By expressing Comparable in this way, we know that if we have two objects of
type T where T conforms to Comparable, comparison between those two objects with
isEqual is well-typed. However, if we have objects of different types T and U,
we cannot compare those objects with isEqual even if both T and U are
Comparable.

Self types are not without their costs, particularly in the case where Self is
used as a parameter type of a class method that will be subclassed. Here, the
parameter type ends up being (implicitly) covariant, which tightens up
type-checking but may also force us into more dynamic type checks. We can
explore this separately; within protocols, type-checking for Self is more
direct.

Associated Types
----------------

In addition to Self, a protocol's operations often need to refer to types that
are related to the type of 'Self', such as a type of data stored in a
collection, or the node and edge types of a graph. For example, this would allow
us to cleanly describe a protocol for collections::

  protocol Collection {
    typealias Element
    func forEach(_ callback : (value : Element) -> Void)
    func add(_ value : Element)
  }

It is important here that a generic function that refers to a given type T,
which is known to be a collection, can access the associated types corresponding
to T. For example, one could implement an "accumulate" operation for an
arbitrary Collection, but doing so requires us to specify some constraints on
the Value type of the collection. We'll return to this later.

Operators, Properties, and Subscripting
---------------------------------------

As previously noted, protocols can contain both function requirements (which are
in effect requirements for instance methods) and associated type
requirements. Protocols can also contain operators, properties, and subscript
operators::

  protocol RandomAccessContainer : Collection {
    var count: Int
    func == (lhs: Self, rhs: Self)
    subscript(i: Int) -> Element
  }

Operator requirements can be satisfied by operator definitions, property
requirements can be satisfied by either variables or properties, and subscript
requirements can be satisfied by subscript operators.

Conforming to a Protocol
------------------------

Thus far, we have not actually shown how a type can meet the requirements of a
protocol. The most syntactically lightweight approach is to allow implicit
conformance. This is essentially duck typing, where a type is assumed to conform
to a protocol if it meets the syntactic requirements of the protocol. For
example, given::

  protocol Shape {
    func draw()
  }

One could write a Circle struct such as::

  struct Circle {
    var center : Point
    var radius : Int

    func draw() {
      // draw it
    }
  }

Circle provides a draw() method with the same input and result types as required
by the Shape protocol. Therefore, Circle conforms to Shape.

Implicit protocol conformance is convenient, because it requires no additional
typing. However, it can run into some trouble when an entity that syntactically
matches a protocol doesn't provide the required semantics. For example, Cowboys
also know how to "draw!"::

  struct Cowboy {
    var gun : SixShooter

    func draw() {
      // draw!
    }
  }

It is unlikely that Cowboy is meant to conform to Shape, but the method name and
signatures match, so implicit conformance deduces that Cowboy conforms to
Shape. Random collisions between types are fairly rare. However, when one is
using protocol inheritance with fine-grained (semantic or mostly-semantic)
differences between protocols in the hierarchy, they become more common. See
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1798.html for examples
of this problem as it surfaced with C++ concepts. It is not clear at this time
whether we want implicit conformance in Swift: there's no existing code to worry
about, and explicit conformance (described below) provides some benefits.

Explicit Protocol Conformance
-----------------------------

Type authors often implement types that are intended to conform to a particular
protocol. For example, if we want a linked-list type to conform to Collection,
we can specify that it is by adding a protocol conformance annotation to the
type::

  struct EmployeeList : Collection { // EmployeeList is a collection
    typealias Element = T
    func forEach(_ callback : (value : Element) -> Void) { /* Implement this */ }
    func add(_ value : Element) { /* Implement this */ }
  }

This explicit protocol conformance declaration forces the compiler to check that
EmployeeList actually does meet the requirements of the Collection protocol. If
we were missing an operation (say, forEach) or had the wrong signature, the
definition of 'EmployeeList' would be ill-formed. Therefore, explicit
conformance provides both documentation for the user of EmployeeList and
checking for the author and future maintainers of EmployeeList.

Any nominal type (such as an enum, struct, or class) can be specified to conform
to one or more protocols in this manner. Additionally, a typealias can be
specified to conform to one or more protocols, e.g.,::

  typealias NSInteger : Numeric = Int

While not technically necessary due to retroactive modeling (below), this can be
used to document and check that a particular type alias does in fact meet some
basic, important requirements. Moreover, it falls out of the syntax that places
requirements on associated types.

Retroactive Modeling
--------------------

When using a set of libraries, it's fairly common that one library defines a
protocol (and useful generic entities requiring that protocol) while another
library provides a data type that provides similar functionality to that
protocol, but under a different name.  Retroactive modeling is the process by
which the type is retrofitted (without changing the type) to meet the
requirements of the protocol.

In Swift, we provide support for retroactive modeling by allowing
extensions, e.g.,::

  extension String : Collection {
    typealias Element = char
    func forEach(_ callback : (value : Element) -> Void) { /* use existing String routines to enumerate characters */ }
    func add(_ value : Element) { self += value /* append character */ }
  }

Once an extension is defined, the extension now conforms to the Collection
protocol, and can be used anywhere a Collection is expected.

Default Implementations
-----------------------

The functions declared within a protocol are requirements that any type must
meet if it wants to conform to the protocol. There is a natural tension here,
then, between larger protocols that make it easier to write generic algorithms,
and smaller protocols that make it easier to write conforming types. For
example, should a Numeric protocol implement all operations, e.g.,::

  protocol Numeric {
    func +(lhs : Self, rhs : Self) -> Self
    func -(lhs : Self, rhs : Self) -> Self
    func +(x : Self) -> Self
    func -(x : Self) -> Self
  }

which would make it easy to write general numeric algorithms, but requires the
author of some BigInt class to implement a lot of functionality, or should the
numeric protocol implement just the core operations::

  protocol Numeric {
    func +(lhs : Self, rhs : Self) -> Self
    func -(x : Self) -> Self
  }

to make it easier to adopt the protocol (but harder to write numeric
algorithms)? Both of the protocols express the same thing (semantically),
because one can use the core operations (binary +, unary -) to implement the
other algorithms. However, it's far easier to allow the protocol itself to
provide default implementations::

  protocol Numeric {
    func +(lhs : Self, rhs : Self) -> Self
    func -(lhs : Self, rhs : Self) -> Self { return lhs + -rhs }
    func +(x : Self) -> Self { return x }
    func -(x : Self) -> Self
  }

This makes it easier both to implement generic algorithms (which can use the
most natural syntax) and to make a new type conform to the protocol. For
example, if we were to define only the core algorithms in our BigNum type::

  struct BigNum : Numeric {
    func +(lhs : BigNum, rhs : BigNum) -> BigNum { ... }
    func -(x : BigNum) -> BigNum { ... }
  }

the compiler will automatically synthesize the other operations needed for the
protocol. Moreover, these operations will be available to uses of the BigNum
class as if they had been written in the type itself (or in an extension of the
type, if that feature is used), which means that protocol conformance actually
makes it easier to define types that conform to protocols, rather than just
providing additional checking.

Subtype Polymorphism
--------------------

Subtype polymorphism is based on the notion of substitutability. If a type S is
a subtype of a type T, then a value of type S can safely be used where a value
of type T is expected. Object-oriented languages typically use subtype
polymorphism, where the subtype relationship is based on inheritance: if the
class Dog inherits from the class Animal, then Dog is a subtype of
Animal. Subtype polymorphism is generally dynamic, in the sense that the
substitution occurs at run-time, even if it is statically type-checked.

In Swift, we consider protocols to be types. A value of protocol type has an
existential type, meaning that we don't know the concrete type until run-time
(and even then it varies), but we know that the type conforms to the given
protocol. Thus, a variable can be declared with type "Serializable", e.g.,::

  var x : Serializable = // value of any Serializable type
  x.serialize() // okay: serialize() is part of the Serializable protocol

Naturally, such polymorphism is dynamic, and will require boxing of value types
to implement. We can now see how Self types interact with subtype
polymorphism. For example, say we have two values of type Comparable, and we try
to compare them::

  var x : Comparable = ...
  var y : Comparable = ...
  if x.isEqual(y) { // well-typed?
  }

Whether x.isEqual(y) is well-typed is not statically determinable, because the
dynamic type of x may different from the dynamic type of y, even if they are
both comparable (e.g., one is an Int and the other a String). It can be
implemented by the compiler as a dynamic type check, with some general failure
mode (aborting, throwing an exception, etc.) if the dynamic type check fails.

To express types that meet the requirements of several protocols, one can just
create a new protocol aggregating those protocols::

  protocol SerializableDocument : Document, Serializable { }
  var doc : SerializableDocument
  print(doc.title()) // okay: title() is part of the Document protocol, so we can call it
  doc.serialize(stout) // okay: serialize() is part of the Serializable protocol

However, this only makes sense when the resulting protocol is a useful
abstraction. A SerializableDocument may or may not be a useful abstraction. When
it is not useful, one can instead use '&' types to compose different protocols, e.g.,::

  var doc : Document & Serializable

Here, doc has an existential type that is known to conform to both the Document
and Serializable protocols. This gives rise to a natural "top" type, such that
every type in the language is a subtype of "top". Java has java.lang.Object, C#
has object, Objective-C has "id" (although "id" is weird, because it is also
convertible to everything; it's best not to use it as a model). In Swift, the
"top" type is simply an empty protocol composition: ``Any``::

  var value : Any = 17 // an any can hold an integer
  value = "hello" // or a String
  value = (42, "hello", Red) // or anything else

Bounded Parametric Polymorphism
-------------------------------

Parametric polymorphism is based on the idea of providing type parameters for a
generic function or type. When using that function or type, one substitutes
concrete types for the type parameters. Strictly speaking, parametric
polymorphism allows *any* type to be substituted for a type parameter, but it's
useless in practice because that means that generic functions or types cannot do
anything to the type parameters: they must instead rely on first-class functions
passed into the generic function or type to perform any meaningful work.

Far more useful (and prevalent) is bounded parametric polymorphism, which allows
the generic function or type to specify constraints (bounds) on the type
parameters. By specifying these bounds, it becomes far easier to write and use
these generic functions and types.  Haskell type classes, Java and C# generics,
C++ concepts, and many other language features support bounded parametric
polymorphism.

Protocols provide a natural way to express the constraints of a generic function
in Swift. For example, one could define a generic linked list as::

  struct ListNode<T> {
    var Value : T
    enum NextNode { case Node : ListNode<T>, End }
    var Next : NextNode
  }

  struct List<T > {
    var First : ListNode<T>::NextNode
  }

This list works on any type T. One could then add a generic function that
inserts at the beginning of the list::

  func insertAtBeginning<T>(_ list : List<T>, value : T) {
    list.First = ListNode<T>(value, list.First)
  }

Expressing Constraints
----------------------

Within the type parameter list of a generic type or function (e.g., the <T> in
ListNode<T>), the 'T' introduces a new type parameter and the (optional) ":
type" names a protocol (or protocol composition) to which 'T' must
conform. Within the body of the generic type or function, any of the functions
or types described by the constraints are available. For example, let's
implement a find() operation on lists::

  func find<T : Comparable>(_ list : List<T>, value : T) -> Int {
    var index = 0
    var current
    for (current = list.First; current is Node; current = current.Next) {
      if current.Value.isEqual(value) { // okay: T is Comparable
        return index
      }
      index = index + 1
    }
    return -1
  }

In addition to providing constraints on the type parameters, we also need to be
able to constrain associated types. To do so, we introduce the notion of a
"where" clause, which follows the signature of the generic type or
function. For example, let's generalize our find algorithm to work on any
ordered collection::

  protocol OrderedCollection : Collection {
    func size() -> Int
    func getAt(_ index : Int) -> Element // Element is an associated type
  }

  func find<C : OrderedCollection where C.Element : Comparable>(
         _ collection : C, value : C.Element) -> Int
  {
    for index in 0...collection.size() {
      if (collection.getAt(index) == value) { // okay: we know that C.Element is Comparable
        return index
      }
    }
    return -1
  }

The where clause is actually the more general way of expressing constraints,
and the constraints expressed in the angle brackets (e.g., <C :
OrderedCollection>) are just sugar for a where clause.  For example, the
above find() signature is equivalent to::

  func find<C where C : OrderedCollection, C.Element : Comparable>(
         _ collection : C, value : C.Element) -> Int

Note that find<C> is shorthand for (and equivalent to) find<C : Any>, since
every type conforms to the Any protocol composition.

There are two other important kinds of constraints that need to be
expressible. Before we get to those, consider a simple "Enumerator" protocol that
lets us describe an iteration of values of some given value type::

  protocol Enumerator {
    typealias Element
    func isEmpty() -> Bool
    func next() -> Element
  }

Now, we want to express the notion of an enumerable collection, which provides
iteration, which we do by adding requirements into the protocol::

  protocol EnumerableCollection : Collection {
    typealias EnumeratorType : Enumerator
    where EnumeratorType.Element == Element
    func getEnumeratorType() -> EnumeratorType
  }

Here, we are specifying constraints on an associated type (EnumeratorType must
conform to the Enumerator protocol), by adding a conformance clause (: Enumerator)
to the associated type definition. We also use a separate where clause to
require that the type of values produced by querying the enumerator is the same as
the type of values stored in the container. This is important, for example, for
use with the Comparable protocol (and any protocol using Self types), because it
maintains type identity within the generic function or type.

Constraint Inference
--------------------

Generic types often constrain their type parameters. For example, a
SortedDictionary, which provides dictionary functionality using some kind of
balanced binary tree (as in C++'s std::map), would require that its key type be
Comparable::

  class SortedDictionary<Key : Comparable, Value> {
    // ...
  }

Naturally, one any generic operation on a SortedDictionary<K,V> would also require
that K be Comparable, e.g.,::

  func forEachKey<Key : Comparable, Value>(_ c : SortedDictionary<Key, Value>,
                                           f : (Key) -> Void) { /* ... */ }

However, explicitly requiring that Key conform to Comparable is redundant: one
could not provide an argument for 'c' without the Key type of the
SortedDictionary conforming to Comparable, because the SortedDictionary type
itself could not be formed. Constraint inference infers these additional
constraints within a generic function from the parameter and return types of the
function, simplifying the specification of forEachKey::

  func forEachKey<Key, Value>(_ c : SortedDictionary<Key, Value>,
                              f : (Key) -> Void) { /* ... */ }

Type Parameter Deduction
------------------------

As noted above, type arguments will be deduced from the call arguments to a
generic function::

  var values : list<Int>
  insertAtBeginning(values, 17) // deduces T = Int

Since Swift already has top-down type inference (as well as the C++-like
bottom-up inference), we can also deduce type arguments from the result type::

  func cast<T, U>(_ value : T) -> U { ... }
  var x : Any
  var y : Int = cast(x) // deduces T = Any, U = Int

We require that all type parameters for a generic function be deducible. We
introduce this restriction so that we can avoid introducing a syntax for
explicitly specifying type arguments to a generic function, e.g.,::

  var y : Int = cast<Int>(x) // not permitted: < is the less-than operator

This syntax is horribly ambiguous in C++, and with good type argument deduction,
should not be necessary in Swift.

Implementation Model
--------------------

Because generics are constrained, a well-typed generic function or type can be
translated into object code that uses dynamic dispatch to perform each of its
operations on type parameters. This is in stark contrast to the instantiation
model of C++ templates, where each new set of template arguments requires the
generic function or type to be compiled again. This model is important for
scalability of builds, so that the time to perform type-checking and code
generation scales with the amount of code written rather than the amount of code
instantiated. Moreover, it can lead to smaller binaries and a more flexible
language (generic functions can be "virtual").

The translation model is fairly simple. Consider the generic find() we
implemented for lists, above::

  func find<T : Comparable>(_ list : List<T>, value : T) -> Int {
    var index = 0
    var current = list.First
    while current is ListNode<T> { // now I'm just making stuff up
      if current.value.isEqual(value) { // okay: T is Comparable
        return index
      }
      current = current.Next
      index = index + 1
    }
    return -1
  }

to translate this into executable code, we form a vtable for each of the
constraints on the generic function. In this case, we'll have a vtable for
Comparable T. Every operation within the body of this generic function
type-checks to either an operation on some concrete type (e.g., the operations
on Int), to an operation within a protocol (which requires indirection through
the corresponding vtable), or to an operation on a generic type definition, all
of which can be emitted as object code.

.. _generics-specialization:

Specialization
--------------

This implementation model lends itself to optimization when we know the specific
argument types that will be used when invoking the generic function. In this
case, some or all of the vtables provided for the constraints will effectively
be constants. By specializing the generic function (at compile-time, link-time,
or (if we have a JIT) run-time) for these types, we can eliminate the cost of
the virtual dispatch, inline calls when appropriate, and eliminate the overhead
of the generic system. Such optimizations can be performed based on heuristics,
user direction, or profile-guided optimization.

An internal @_specialize function attribute allows developers to force
full specialization by listing concrete type names corresponding to the
function's generic signature. A function's generic signature is a
concatenation of its generic context and the function's own generic
type parameters.::

  struct S<T> {
    var x: T
    @_specialize(where T == Int, U == Float)
    mutating func exchangeSecond<U>(_ u: U, _ t: T) -> (U, T) {
      x = t
      return (u, x)
    }
  }

  // Substitutes: <T, U> with <Int, Float> producing:
  // S<Int>::exchangeSecond<Float>(u: Float, t: Int) -> (Float, Int)

@_specialize currently acts as a hint to the optimizer, which
generates type checks and code to dispatch to the specialized routine
without affecting the signature of the generic function. The
intention is to support efforts at evaluating the performance of
specialized code. The performance impact is not guaranteed and is
likely to change with the optimizer. This attribute should only be
used in conjunction with rigorous performance analysis. Eventually,
a similar attribute could be defined in the language, allowing it to be
exposed as part of a function's API. That would allow direct dispatch
to specialized code without type checks, even across modules.

The exact syntax of the @_specialize function attribute is defined as: ::

  @_specialize(exported: true, kind: full, where K == Int, V == Int)
  @_specialize(exported: false, kind: partial, where K: _Trivial64)
  func dictFunction<K, V>(dict: Dictionary<K, V>) {
  }

If 'exported' is set, the corresponding specialization would have a public
visibility and can be used by clients. If 'exported' is omitted, it's value
is assumed to be 'false'.

If 'kind' is 'full' it means a full specialization and the compiler will
produce an error if you forget to specify the type for some of the generic
parameters in the 'where' clause. If 'kind' is 'partial' it means a partial
specialization. If 'kind' is omitted, its value is assumed to be 'full.

The requirements in the where clause may be same-type constraints like 'T == Int',
but they may also specify so-called layout constraints like 'T: _Trivial'.

The following layout constraints are currently supported:
  * AnyObject - the actual parameter should be an instance of a class
  * _NativeClass - the actual parameter should be an instance of a Swift native
    class
  * _RefCountedObject - the actual parameter should be a reference-counted object
  * _NativeRefCountedObject - the actual parameter should be a Swift-native
    reference-counted object
  * _Trivial - the actual parameter should be of a trivial type, i.e. a type
    without any reference counted properties.
  * _Trivial(SizeInBits) - like _Trivial, but the size of the type should be
    exactly 'SizeInBits' bits.
  * _TrivialAtMost(SizeInBits) - like _Trivial, but the size of the type should
    be at most 'SizeInBits' bits.


Existential Types and Generics
------------------------------

Both existential types and generics depend on dynamic dispatching based on
protocols. A value of an existential type (say, Comparable) is a pair (value,
vtable). 'value' stores the current value either directly (if it fits in the 3
words allocated to the value) or as a pointer to the boxed representation (if
the actual representation is larger than 3 words). By itself, this value cannot
be interpreted, because its type is not known statically, and may change due to
assignment. The vtable provides the means to manipulate the value, because it
provides a mapping between the protocols to which the existential type conforms
(which is known statically) to the functions that implements that
functionality for the type of the value. The value, therefore, can only be
safely manipulated through the functions in this vtable.

A value of some generic type T uses a similar implementation model.  However,
the (value, vtable) pair is split apart: values of type T contain only the value
part (the 3 words of data), while the vtable is maintained as a separate value
that can be shared among all T's within that generic function.

Overloading
-----------

Generic functions can be overloaded based entirely on constraints. For example,
consider a binary search algorithm::

   func binarySearch<
      C : EnumerableCollection where C.Element : Comparable
   >(_ collection : C, value : C.Element)
     -> C.EnumeratorType
   {
     // We can perform log(N) comparisons, but EnumerableCollection
     // only supports linear walks, so this is linear time
   }

   protocol RandomAccessEnumerator : Enumerator {
     // splits a range in half, returning both halves
     func split() -> (Enumerator, Enumerator)
   }

   func binarySearch<
      C : EnumerableCollection
       where C.Element : Comparable,
                 C.EnumeratorType: RandomAccessEnumerator
   >(_ collection : C, value : C.Element)
     -> C.EnumeratorType
   {
     // We can perform log(N) comparisons and log(N) range splits,
     // so this is logarithmic time
   }

If binarySearch is called with a sequence whose range type conforms to
RandomAccessEnumerator, both of the generic functions match. However, the second
function is more specialized, because its constraints are a superset of the
constraints of the first function. In such a case, overloading should pick the
more specialized function.

There is a question as to when this overloading occurs. For example,
binarySearch might be called as a subroutine of another generic function with
minimal requirements::

  func doSomethingWithSearch<
    C : EnumerableCollection where C.Element : Ordered
  >(
    _ collection : C, value : C.Element
  ) -> C.EnumeratorType
  {
    binarySearch(collection, value)
  }

At the time when the generic definition of doSomethingWithSearch is
type-checked, only the first binarySearch() function applies, since we don't
know that C.EnumeratorType conforms to RandomAccessEnumerator. However, when
doSomethingWithSearch is actually invoked, C.EnumeratorType might conform to the
RandomAccessEnumerator, in which case we'd be better off picking the second
binarySearch. This amounts to run-time overload resolution, which may be
desirable, but also has downsides, such as the potential for run-time failures
due to ambiguities and the cost of performing such an expensive operation at
these call sites. Of course, that cost could be mitigated in hot generic
functions via the specialization mentioned above.

Our current proposal for this is to decide statically which function is called
(based on similar partial-ordering rules as used in C++), and avoid run-time
overload resolution. If this proves onerous, we can revisit the decision later.

Parsing Issues
--------------

The use of angle brackets to supply arguments to a generic type, while familiar
to C++/C#/Java programmers, cause some parsing problems. The problem stems from
the fact that '<', '>', and '>>' (the latter of which will show up in generic
types such as Array<Array<Int>>) match the 'operator' terminal in the grammar,
and we wish to continue using this as operators.

When we're in the type grammar, this is a minor inconvenience for the parser,
because code like this::

  var x : Array<Int>

will essentially parse the type as::

  identifier operator identifier operator

and verify that the operators are '<' and '>', respectively. Cases
involving <> are more interesting, because the type of::

  var y : Array<Array<Int>>

is effectively parsed as::

  identifier operator identifier operator identifier operator operator

by splitting the '>>' operator token into two '>' operator tokens.

However, this is manageable, and is already implemented for the (now deprecated)
protocol composition syntax (protocol<>). The larger problem occurs at expression
context, where the parser cannot disambiguate the tokens::

  Matrix<Double>(10, 10)

i.e.,::

  identifier operator identifier operator unspaced_lparen integer-literal comma integer-literal rparen

which can be interpreted as either::

  (greater_than
    (less_than
      (declref Matrix)
      (declref Double)
    (tuple
      (integer_literal 10)
      (integer_literal 10)))

or::

  (constructor Matrix<Double>
    (tuple
      (integer_literal 10)
      (integer_literal 10)))

Both Java and C# have this ambiguity. C# resolves the ambiguity by looking at
the token after the closing '>' to decide which way to go; Java seems to do the
same. We have a few options:

1. Follow C# and Java and implement the infinite lookahead needed to make this
   work. Note that we have true ambiguities, because one could make either of
   the above parse trees well-formed.

2. Introduce some kind of special rule for '<' like we have for '(', such as: an
   identifier followed by an unspaced '<' is a type, while an identifier
   followed by spacing and then '<' is an expression, or

3. Pick some syntax other than angle brackets, which is not ambiguous.  Note
   that neither '(' nor '[' work, because they too have expression forms.

4. Disambiguate between the two parses semantically.

We're going to try a variant of #1, using a variation of the disambiguation
rule used in C#. Essentially, when we see::

  identifier <

we look ahead, trying to parse a type parameter list, until parsing the type
parameter list fails or we find a closing '>'. We then look ahead an additional
token to see if the closing '>' is followed by a '(', '.', or closing bracketing
token (since types are most commonly followed by a constructor call or static
member access). If parsing the type parameter list succeeds, and the closing
angle bracket is followed by a '(', '.', or closing bracket token, then the
'<...>' sequence is parsed as a generic parameter list; otherwise, the '<'
is parsed as an operator.

.. @ignore('all')