Convertible relation

A type a is implicitly convertible to type b iff the following algorithm returns true:

  1. proc isImplicitlyConvertible(a, b: PType): bool =
  2. if isSubtype(a, b) or isCovariant(a, b):
  3. return true
  4. if isIntLiteral(a):
  5. return b in {int8, int16, int32, int64, int, uint, uint8, uint16,
  6. uint32, uint64, float32, float64}
  7. case a.kind
  8. of int: result = b in {int32, int64}
  9. of int8: result = b in {int16, int32, int64, int}
  10. of int16: result = b in {int32, int64, int}
  11. of int32: result = b in {int64, int}
  12. of uint: result = b in {uint32, uint64}
  13. of uint8: result = b in {uint16, uint32, uint64}
  14. of uint16: result = b in {uint32, uint64}
  15. of uint32: result = b in {uint64}
  16. of float32: result = b in {float64}
  17. of float64: result = b in {float32}
  18. of seq:
  19. result = b == openArray and typeEquals(a.baseType, b.baseType)
  20. of array:
  21. result = b == openArray and typeEquals(a.baseType, b.baseType)
  22. if a.baseType == char and a.indexType.rangeA == 0:
  23. result = b == cstring
  24. of cstring, ptr:
  25. result = b == pointer
  26. of string:
  27. result = b == cstring

Implicit conversions are also performed for Nim’s range type constructor.

Let a0, b0 of type T.

Let A = range[a0..b0] be the argument’s type, F the formal parameter’s type. Then an implicit conversion from A to F exists if a0 >= low(F) and b0 <= high(F) and both T and F are signed integers or if both are unsigned integers.

A type a is explicitly convertible to type b iff the following algorithm returns true:

  1. proc isIntegralType(t: PType): bool =
  2. result = isOrdinal(t) or t.kind in {float, float32, float64}
  3. proc isExplicitlyConvertible(a, b: PType): bool =
  4. result = false
  5. if isImplicitlyConvertible(a, b): return true
  6. if typeEqualsOrDistinct(a, b): return true
  7. if isIntegralType(a) and isIntegralType(b): return true
  8. if isSubtype(a, b) or isSubtype(b, a): return true

The convertible relation can be relaxed by a user-defined type converter.

  1. converter toInt(x: char): int = result = ord(x)
  2. var
  3. x: int
  4. chr: char = 'a'
  5. # implicit conversion magic happens here
  6. x = chr
  7. echo x # => 97
  8. # one can use the explicit form too
  9. x = chr.toInt
  10. echo x # => 97

The type conversion T(a) is an L-value if a is an L-value and typeEqualsOrDistinct(T, typeof(a)) holds.