type_rel.txt 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. Type relations
  2. ==============
  3. The following section defines several relations on types that are needed to
  4. describe the type checking done by the compiler.
  5. Type equality
  6. -------------
  7. Nim uses structural type equivalence for most types. Only for objects,
  8. enumerations and distinct types name equivalence is used. The following
  9. algorithm, *in pseudo-code*, determines type equality:
  10. .. code-block:: nim
  11. proc typeEqualsAux(a, b: PType,
  12. s: var HashSet[(PType, PType)]): bool =
  13. if (a,b) in s: return true
  14. incl(s, (a,b))
  15. if a.kind == b.kind:
  16. case a.kind
  17. of int, intXX, float, floatXX, char, string, cstring, pointer,
  18. bool, nil, void:
  19. # leaf type: kinds identical; nothing more to check
  20. result = true
  21. of ref, ptr, var, set, seq, openarray:
  22. result = typeEqualsAux(a.baseType, b.baseType, s)
  23. of range:
  24. result = typeEqualsAux(a.baseType, b.baseType, s) and
  25. (a.rangeA == b.rangeA) and (a.rangeB == b.rangeB)
  26. of array:
  27. result = typeEqualsAux(a.baseType, b.baseType, s) and
  28. typeEqualsAux(a.indexType, b.indexType, s)
  29. of tuple:
  30. if a.tupleLen == b.tupleLen:
  31. for i in 0..a.tupleLen-1:
  32. if not typeEqualsAux(a[i], b[i], s): return false
  33. result = true
  34. of object, enum, distinct:
  35. result = a == b
  36. of proc:
  37. result = typeEqualsAux(a.parameterTuple, b.parameterTuple, s) and
  38. typeEqualsAux(a.resultType, b.resultType, s) and
  39. a.callingConvention == b.callingConvention
  40. proc typeEquals(a, b: PType): bool =
  41. var s: HashSet[(PType, PType)] = {}
  42. result = typeEqualsAux(a, b, s)
  43. Since types are graphs which can have cycles, the above algorithm needs an
  44. auxiliary set ``s`` to detect this case.
  45. Type equality modulo type distinction
  46. -------------------------------------
  47. The following algorithm (in pseudo-code) determines whether two types
  48. are equal with no respect to ``distinct`` types. For brevity the cycle check
  49. with an auxiliary set ``s`` is omitted:
  50. .. code-block:: nim
  51. proc typeEqualsOrDistinct(a, b: PType): bool =
  52. if a.kind == b.kind:
  53. case a.kind
  54. of int, intXX, float, floatXX, char, string, cstring, pointer,
  55. bool, nil, void:
  56. # leaf type: kinds identical; nothing more to check
  57. result = true
  58. of ref, ptr, var, set, seq, openarray:
  59. result = typeEqualsOrDistinct(a.baseType, b.baseType)
  60. of range:
  61. result = typeEqualsOrDistinct(a.baseType, b.baseType) and
  62. (a.rangeA == b.rangeA) and (a.rangeB == b.rangeB)
  63. of array:
  64. result = typeEqualsOrDistinct(a.baseType, b.baseType) and
  65. typeEqualsOrDistinct(a.indexType, b.indexType)
  66. of tuple:
  67. if a.tupleLen == b.tupleLen:
  68. for i in 0..a.tupleLen-1:
  69. if not typeEqualsOrDistinct(a[i], b[i]): return false
  70. result = true
  71. of distinct:
  72. result = typeEqualsOrDistinct(a.baseType, b.baseType)
  73. of object, enum:
  74. result = a == b
  75. of proc:
  76. result = typeEqualsOrDistinct(a.parameterTuple, b.parameterTuple) and
  77. typeEqualsOrDistinct(a.resultType, b.resultType) and
  78. a.callingConvention == b.callingConvention
  79. elif a.kind == distinct:
  80. result = typeEqualsOrDistinct(a.baseType, b)
  81. elif b.kind == distinct:
  82. result = typeEqualsOrDistinct(a, b.baseType)
  83. Subtype relation
  84. ----------------
  85. If object ``a`` inherits from ``b``, ``a`` is a subtype of ``b``. This subtype
  86. relation is extended to the types ``var``, ``ref``, ``ptr``:
  87. .. code-block:: nim
  88. proc isSubtype(a, b: PType): bool =
  89. if a.kind == b.kind:
  90. case a.kind
  91. of object:
  92. var aa = a.baseType
  93. while aa != nil and aa != b: aa = aa.baseType
  94. result = aa == b
  95. of var, ref, ptr:
  96. result = isSubtype(a.baseType, b.baseType)
  97. .. XXX nil is a special value!
  98. Covariance
  99. ----------
  100. Covariance in Nim can be introduced only though pointer-like types such
  101. as ``ptr`` and ``ref``. Sequence, Array and OpenArray types, instantiated
  102. with pointer-like types will be considered covariant if and only if they
  103. are also immutable. The introduction of a ``var`` modifier or additional
  104. ``ptr`` or ``ref`` indirections would result in invariant treatment of
  105. these types.
  106. ``proc`` types are currently always invariant, but future versions of Nim
  107. may relax this rule.
  108. User-defined generic types may also be covariant with respect to some of
  109. their parameters. By default, all generic params are considered invariant,
  110. but you may choose the apply the prefix modifier ``in`` to a parameter to
  111. make it contravariant or ``out`` to make it covariant:
  112. .. code-block:: nim
  113. type
  114. AnnotatedPtr[out T] =
  115. metadata: MyTypeInfo
  116. p: ref T
  117. RingBuffer[out T] =
  118. startPos: int
  119. data: seq[T]
  120. Action {.importcpp: "std::function<void ('0)>".} [in T] = object
  121. When the designated generic parameter is used to instantiate a pointer-like
  122. type as in the case of `AnnotatedPtr` above, the resulting generic type will
  123. also have pointer-like covariance:
  124. .. code-block:: nim
  125. type
  126. GuiWidget = object of RootObj
  127. Button = object of GuiWidget
  128. ComboBox = object of GuiWidget
  129. var
  130. widgetPtr: AnnotatedPtr[GuiWidget]
  131. buttonPtr: AnnotatedPtr[Button]
  132. ...
  133. proc drawWidget[T](x: AnnotatedPtr[GuiWidget]) = ...
  134. # you can call procs expecting base types by supplying a derived type
  135. drawWidget(buttonPtr)
  136. # and you can convert more-specific pointer types to more general ones
  137. widgetPtr = buttonPtr
  138. Just like with regular pointers, covariance will be enabled only for immutable
  139. values:
  140. .. code-block:: nim
  141. proc makeComboBox[T](x: var AnnotatedPtr[GuiWidget]) =
  142. x.p = new(ComboBox)
  143. makeComboBox(buttonPtr) # Error, AnnotatedPtr[Button] cannot be modified
  144. # to point to a ComboBox
  145. On the other hand, in the `RingBuffer` example above, the designated generic
  146. param is used to instantiate the non-pointer ``seq`` type, which means that
  147. the resulting generic type will have covariance that mimics an array or
  148. sequence (i.e. it will be covariant only when instantiated with ``ptr`` and
  149. ``ref`` types):
  150. .. code-block:: nim
  151. type
  152. Base = object of RootObj
  153. Derived = object of Base
  154. proc consumeBaseValues(b: RingBuffer[Base]) = ...
  155. var derivedValues: RingBuffer[Derived]
  156. consumeBaseValues(derivedValues) # Error, Base and Derived values may differ
  157. # in size
  158. proc consumeBasePointers(b: RingBuffer[ptr Base]) = ...
  159. var derivedPointers: RingBuffer[ptr Derived]
  160. consumeBaseValues(derivedPointers) # This is legal
  161. Please note that Nim will treat the user-defined pointer-like types as
  162. proper alternatives to the built-in pointer types. That is, types such
  163. as `seq[AnnotatedPtr[T]]` or `RingBuffer[AnnotatedPtr[T]]` will also be
  164. considered covariant and you can create new pointer-like types by instantiating
  165. other user-defined pointer-like types.
  166. The contravariant parameters introduced with the ``in`` modifier are currently
  167. useful only when interfacing with imported types having such semantics.
  168. Convertible relation
  169. --------------------
  170. A type ``a`` is **implicitly** convertible to type ``b`` iff the following
  171. algorithm returns true:
  172. .. code-block:: nim
  173. # XXX range types?
  174. proc isImplicitlyConvertible(a, b: PType): bool =
  175. if isSubtype(a, b) or isCovariant(a, b):
  176. return true
  177. case a.kind
  178. of int: result = b in {int8, int16, int32, int64, uint, uint8, uint16,
  179. uint32, uint64, float, float32, float64}
  180. of int8: result = b in {int16, int32, int64, int}
  181. of int16: result = b in {int32, int64, int}
  182. of int32: result = b in {int64, int}
  183. of uint: result = b in {uint32, uint64}
  184. of uint8: result = b in {uint16, uint32, uint64}
  185. of uint16: result = b in {uint32, uint64}
  186. of uint32: result = b in {uint64}
  187. of float: result = b in {float32, float64}
  188. of float32: result = b in {float64, float}
  189. of float64: result = b in {float32, float}
  190. of seq:
  191. result = b == openArray and typeEquals(a.baseType, b.baseType)
  192. of array:
  193. result = b == openArray and typeEquals(a.baseType, b.baseType)
  194. if a.baseType == char and a.indexType.rangeA == 0:
  195. result = b = cstring
  196. of cstring, ptr:
  197. result = b == pointer
  198. of string:
  199. result = b == cstring
  200. A type ``a`` is **explicitly** convertible to type ``b`` iff the following
  201. algorithm returns true:
  202. .. code-block:: nim
  203. proc isIntegralType(t: PType): bool =
  204. result = isOrdinal(t) or t.kind in {float, float32, float64}
  205. proc isExplicitlyConvertible(a, b: PType): bool =
  206. result = false
  207. if isImplicitlyConvertible(a, b): return true
  208. if typeEqualsOrDistinct(a, b): return true
  209. if isIntegralType(a) and isIntegralType(b): return true
  210. if isSubtype(a, b) or isSubtype(b, a): return true
  211. The convertible relation can be relaxed by a user-defined type
  212. `converter`:idx:.
  213. .. code-block:: nim
  214. converter toInt(x: char): int = result = ord(x)
  215. var
  216. x: int
  217. chr: char = 'a'
  218. # implicit conversion magic happens here
  219. x = chr
  220. echo x # => 97
  221. # you can use the explicit form too
  222. x = chr.toInt
  223. echo x # => 97
  224. The type conversion ``T(a)`` is an L-value if ``a`` is an L-value and
  225. ``typeEqualsOrDistinct(T, type(a))`` holds.
  226. Assignment compatibility
  227. ------------------------
  228. An expression ``b`` can be assigned to an expression ``a`` iff ``a`` is an
  229. `l-value` and ``isImplicitlyConvertible(b.typ, a.typ)`` holds.
  230. Overloading resolution
  231. ======================
  232. In a call ``p(args)`` the routine ``p`` that matches best is selected. If
  233. multiple routines match equally well, the ambiguity is reported at compiletime.
  234. Every arg in args needs to match. There are multiple different categories how an
  235. argument can match. Let ``f`` be the formal parameter's type and ``a`` the type
  236. of the argument.
  237. 1. Exact match: ``a`` and ``f`` are of the same type.
  238. 2. Literal match: ``a`` is an integer literal of value ``v``
  239. and ``f`` is a signed or unsigned integer type and ``v`` is in ``f``'s
  240. range. Or: ``a`` is a floating point literal of value ``v``
  241. and ``f`` is a floating point type and ``v`` is in ``f``'s
  242. range.
  243. 3. Generic match: ``f`` is a generic type and ``a`` matches, for
  244. instance ``a`` is ``int`` and ``f`` is a generic (constrained) parameter
  245. type (like in ``[T]`` or ``[T: int|char]``.
  246. 4. Subrange or subtype match: ``a`` is a ``range[T]`` and ``T``
  247. matches ``f`` exactly. Or: ``a`` is a subtype of ``f``.
  248. 5. Integral conversion match: ``a`` is convertible to ``f`` and ``f`` and ``a``
  249. is some integer or floating point type.
  250. 6. Conversion match: ``a`` is convertible to ``f``, possibly via a user
  251. defined ``converter``.
  252. These matching categories have a priority: An exact match is better than a
  253. literal match and that is better than a generic match etc. In the following
  254. ``count(p, m)`` counts the number of matches of the matching category ``m``
  255. for the routine ``p``.
  256. A routine ``p`` matches better than a routine ``q`` if the following
  257. algorithm returns true::
  258. for each matching category m in ["exact match", "literal match",
  259. "generic match", "subtype match",
  260. "integral match", "conversion match"]:
  261. if count(p, m) > count(q, m): return true
  262. elif count(p, m) == count(q, m):
  263. discard "continue with next category m"
  264. else:
  265. return false
  266. return "ambiguous"
  267. Some examples:
  268. .. code-block:: nim
  269. proc takesInt(x: int) = echo "int"
  270. proc takesInt[T](x: T) = echo "T"
  271. proc takesInt(x: int16) = echo "int16"
  272. takesInt(4) # "int"
  273. var x: int32
  274. takesInt(x) # "T"
  275. var y: int16
  276. takesInt(y) # "int16"
  277. var z: range[0..4] = 0
  278. takesInt(z) # "T"
  279. If this algorithm returns "ambiguous" further disambiguation is performed:
  280. If the argument ``a`` matches both the parameter type ``f`` of ``p``
  281. and ``g`` of ``q`` via a subtyping relation, the inheritance depth is taken
  282. into account:
  283. .. code-block:: nim
  284. type
  285. A = object of RootObj
  286. B = object of A
  287. C = object of B
  288. proc p(obj: A) =
  289. echo "A"
  290. proc p(obj: B) =
  291. echo "B"
  292. var c = C()
  293. # not ambiguous, calls 'B', not 'A' since B is a subtype of A
  294. # but not vice versa:
  295. p(c)
  296. proc pp(obj: A, obj2: B) = echo "A B"
  297. proc pp(obj: B, obj2: A) = echo "B A"
  298. # but this is ambiguous:
  299. pp(c, c)
  300. Likewise for generic matches the most specialized generic type (that still
  301. matches) is preferred:
  302. .. code-block:: nim
  303. proc gen[T](x: ref ref T) = echo "ref ref T"
  304. proc gen[T](x: ref T) = echo "ref T"
  305. proc gen[T](x: T) = echo "T"
  306. var ri: ref int
  307. gen(ri) # "ref T"
  308. Overloading based on 'var T'
  309. ----------------------------
  310. If the formal parameter ``f`` is of type ``var T`` in addition to the ordinary
  311. type checking, the argument is checked to be an `l-value`:idx:. ``var T``
  312. matches better than just ``T`` then.
  313. .. code-block:: nim
  314. proc sayHi(x: int): string =
  315. # matches a non-var int
  316. result = $x
  317. proc sayHi(x: var int): string =
  318. # matches a var int
  319. result = $(x + 10)
  320. proc sayHello(x: int) =
  321. var m = x # a mutable version of x
  322. echo sayHi(x) # matches the non-var version of sayHi
  323. echo sayHi(m) # matches the var version of sayHi
  324. sayHello(3) # 3
  325. # 13
  326. Automatic dereferencing
  327. -----------------------
  328. If the `experimental mode <#pragmas-experimental-pragma>`_ is active and no other match
  329. is found, the first argument ``a`` is dereferenced automatically if it's a
  330. pointer type and overloading resolution is tried with ``a[]`` instead.
  331. Automatic self insertions
  332. -------------------------
  333. Starting with version 0.14 of the language, Nim supports ``field`` as a
  334. shortcut for ``self.field`` comparable to the `this`:idx: keyword in Java
  335. or C++. This feature has to be explicitly enabled via a ``{.this: self.}``
  336. statement pragma. This pragma is active for the rest of the module:
  337. .. code-block:: nim
  338. type
  339. Parent = object of RootObj
  340. parentField: int
  341. Child = object of Parent
  342. childField: int
  343. {.this: self.}
  344. proc sumFields(self: Child): int =
  345. result = parentField + childField
  346. # is rewritten to:
  347. # result = self.parentField + self.childField
  348. Instead of ``self`` any other identifier can be used too, but
  349. ``{.this: self.}`` will become the default directive for the whole language
  350. eventually.
  351. In addition to fields, routine applications are also rewritten, but only
  352. if no other interpretation of the call is possible:
  353. .. code-block:: nim
  354. proc test(self: Child) =
  355. echo childField, " ", sumFields()
  356. # is rewritten to:
  357. echo self.childField, " ", sumFields(self)
  358. # but NOT rewritten to:
  359. echo self, self.childField, " ", sumFields(self)
  360. Lazy type resolution for untyped
  361. --------------------------------
  362. **Note**: An `unresolved`:idx: expression is an expression for which no symbol
  363. lookups and no type checking have been performed.
  364. Since templates and macros that are not declared as ``immediate`` participate
  365. in overloading resolution it's essential to have a way to pass unresolved
  366. expressions to a template or macro. This is what the meta-type ``untyped``
  367. accomplishes:
  368. .. code-block:: nim
  369. template rem(x: untyped) = discard
  370. rem unresolvedExpression(undeclaredIdentifier)
  371. A parameter of type ``untyped`` always matches any argument (as long as there is
  372. any argument passed to it).
  373. But one has to watch out because other overloads might trigger the
  374. argument's resolution:
  375. .. code-block:: nim
  376. template rem(x: untyped) = discard
  377. proc rem[T](x: T) = discard
  378. # undeclared identifier: 'unresolvedExpression'
  379. rem unresolvedExpression(undeclaredIdentifier)
  380. ``untyped`` and ``varargs[untyped]`` are the only metatype that are lazy in this sense, the other
  381. metatypes ``typed`` and ``typedesc`` are not lazy.
  382. Varargs matching
  383. ----------------
  384. See `Varargs`_.