Type equality

Nim uses structural type equivalence for most types. Only for objects, enumerations and distinct types name equivalence is used. The following algorithm, in pseudo-code, determines type equality:

  1. proc typeEqualsAux(a, b: PType,
  2. s: var HashSet[(PType, PType)]): bool =
  3. if (a,b) in s: return true
  4. incl(s, (a,b))
  5. if a.kind == b.kind:
  6. case a.kind
  7. of int, intXX, float, floatXX, char, string, cstring, pointer,
  8. bool, nil, void:
  9. # leaf type: kinds identical; nothing more to check
  10. result = true
  11. of ref, ptr, var, set, seq, openarray:
  12. result = typeEqualsAux(a.baseType, b.baseType, s)
  13. of range:
  14. result = typeEqualsAux(a.baseType, b.baseType, s) and
  15. (a.rangeA == b.rangeA) and (a.rangeB == b.rangeB)
  16. of array:
  17. result = typeEqualsAux(a.baseType, b.baseType, s) and
  18. typeEqualsAux(a.indexType, b.indexType, s)
  19. of tuple:
  20. if a.tupleLen == b.tupleLen:
  21. for i in 0..a.tupleLen-1:
  22. if not typeEqualsAux(a[i], b[i], s): return false
  23. result = true
  24. of object, enum, distinct:
  25. result = a == b
  26. of proc:
  27. result = typeEqualsAux(a.parameterTuple, b.parameterTuple, s) and
  28. typeEqualsAux(a.resultType, b.resultType, s) and
  29. a.callingConvention == b.callingConvention
  30. proc typeEquals(a, b: PType): bool =
  31. var s: HashSet[(PType, PType)] = {}
  32. result = typeEqualsAux(a, b, s)

Since types are graphs which can have cycles, the above algorithm needs an auxiliary set s to detect this case.