summary refs log tree commit diff stats
path: root/doc/manual
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2017-05-12 21:27:32 +0300
committerZahary Karadjov <zahary@gmail.com>2017-05-12 21:27:32 +0300
commit7e0c66ffe79f1616c1c821ede5f50f03406feabe (patch)
treef94ad5b1bc9f30eafddabb4e3895011f548f0ef8 /doc/manual
parent2106598d30f990db18c67d87ea08514cf21ffc1c (diff)
downloadNim-7e0c66ffe79f1616c1c821ede5f50f03406feabe.tar.gz
manual additions for the covariant generic parameters
Diffstat (limited to 'doc/manual')
-rw-r--r--doc/manual/type_rel.txt89
1 files changed, 87 insertions, 2 deletions
diff --git a/doc/manual/type_rel.txt b/doc/manual/type_rel.txt
index 1a753d773..0c49f4e7f 100644
--- a/doc/manual/type_rel.txt
+++ b/doc/manual/type_rel.txt
@@ -117,13 +117,98 @@ Covariance
 Covariance in Nim can be introduced only though pointer-like types such
 as ``ptr`` and ``ref``. Sequence, Array and OpenArray types, instantiated
 with pointer-like types will be considered covariant if and only if they
-are also immutable. The introduction of a ``var`` modifier or addional
+are also immutable. The introduction of a ``var`` modifier or additional
 ``ptr`` or ``ref`` indirections would result in invariant treatment of
 these types.
 
-``proc`` types are curently always invariant, but future version of Nim
+``proc`` types are currently always invariant, but future versions of Nim
 may relax this rule.
 
+User-defined generic types may also be covariant with respect to some of
+their parameters. By default, all generic params are considered invariant,
+but you may choose the apply the prefix modifier ``in`` to a parameter to
+make it contravariant or ``out`` to make it covariant:
+
+.. code-block:: nim
+  type
+    AnnotatedPtr[out T] =
+      metadata: MyTypeInfo
+      p: ref T
+
+    RingBuffer[out T] =
+      startPos: int
+      data: seq[T]
+
+    Action {.importcpp: "std::function<void ('0)>".} [in T] = object
+
+When the designated generic parameter is used to instantiate a pointer-like
+type as in the case of `AnnotatedPtr` above, the resulting generic type will
+also have pointer-like covariance:
+
+.. code-block:: nim
+  type
+    GuiWidget = object of TObject
+    Button = object of GuiWidget
+    ComboBox = object of GuiWidget
+
+  var
+    widgetPtr: AnnotatedPtr[GuiWidget]
+    buttonPtr: AnnotatedPtr[Button]
+
+  ...
+
+  proc drawWidget[T](x: AnnotatedPtr[GuiWidget]) = ...
+
+  # you can call procs expecting base types by supplying a derived type
+  drawWidget(buttonPtr)
+
+  # and you can convert more-specific pointer types to more general ones
+  widgetPtr = buttonPtr
+
+Just like with regular pointers, covariance will be enabled only for immutable
+values:
+
+.. code-block:: nim
+  proc makeComboBox[T](x: var AnnotatedPtr[GuiWidget]) =
+    x.p = new(ComboBox)
+
+  makeComboBox(buttonPtr) # Error, AnnotatedPtr[Button] cannot be modified
+                          # to point to a ComboBox
+
+On the other hand, in the `RingBuffer` example above, the designated generic
+param is used to instantiate the non-pointer ``seq`` type, which means that
+the resulting generic type will have covariance that mimics an array or
+sequence (i.e. it will be covariant only when instantiated with ``ptr`` and
+``ref`` types):
+
+.. code-block:: nim
+
+  type
+    Base = object of TObject
+    Derived = object of Base
+
+  proc consumeBaseValues(b: RingBuffer[Base]) = ...
+
+  var derivedValues: RingBuffer[Derived]
+
+  consumeBaseValues(derivedValues) # Error, Base and Derived values may differ
+                                   # in size
+
+  proc consumeBasePointers(b: RingBuffer[ptr Base]) = ...
+
+  var derivedPointers: RingBuffer[ptr Derived]
+
+  consumeBaseValues(derivedPointers) # This is legal
+
+Please note that Nim will treat the user-defined pointer-like types as
+proper alternatives to the built-in pointer types. That is, types such
+as `seq[AnnotatedPtr[T]]` or `RingBuffer[AnnotatedPtr[T]]` will also be
+considered covariant and you can create new pointer-like types by instantiating
+other user-defined pointer-like types.
+
+The contravariant parameters introduced with the ``in`` modifier are currently
+useful only when interfacing with imported types having such semantics.
+
 
 Convertible relation
 --------------------
class='oid'>8c8c21f ^
80e891a ^
6728a11 ^
80e891a ^
8c8c21f ^
6728a11 ^
80e891a ^
8c8c21f ^
80e891a ^
d35213e ^
8c8c21f ^

80e891a ^


8c8c21f ^

80e891a ^

8c8c21f ^

80e891a ^
5b2e3a0 ^
80e891a ^
8c8c21f ^
80e891a ^
8c8c21f ^




8c8c21f ^




80e891a ^
8c8c21f ^




5b2e3a0 ^
8c8c21f ^



80e891a ^

5b2e3a0 ^
6728a11 ^
8c8c21f ^
5b2e3a0 ^
8c8c21f ^



5b2e3a0 ^

8c8c21f ^

80e891a ^





d35213e ^




8c8c21f ^
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