类型关系

以下部分定义描述了编译器完成类型检查所需要的几种类型关系。

类型相等性

Nim 对大多数类型使用结构类型相等。仅对对象、枚举和 distinct 类型以及泛型类型使用名称相等。

Subtype关系

如果对象 a 继承自 b , a 将是 b 的子类型。

子类型关系被延伸到类型 var , ref , prt 。如果 A 是 B 的子类型, A 和 B 是 object 类型那么:

  • var A是var B的子类型
  • ref A是ref B的子类型
  • ptr A是ptr B的子类型。

注意: 从子类型到父类型的赋值,需要上述指针注解之一,以防止 “对象切割” 。

转换关系

如果以下算法返回 true,则类型 a 隐式 可转换为类型 b :

  1. proc isImplicitlyConvertible(a, b: PType): bool =
  2. if isSubtype(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
  28. of proc:
  29. result = typeEquals(a, b) or compatibleParametersAndEffects(a, b)

我们使用判断 typeEquals(a, b) 表示 “类型相等” 属性,使用判断 isSubtype(a, b) 表示 “子类型关系”。compatibleParametersAndEffects(a, b) 当前未指定。

Nim 的 range 类型构造器也执行隐式转换。

让 a0, b0 为类型 T 。

让 A = range[a0..b0] 为实参类型, F 为形参类型。如果 a0 >= low(F) and b0 <= high(F) 并且 T 和 F 都是有符号整数或两者都是无符号整数,则存在从 A 到 F 隐式转换。

如果下列算法返回 true,则类型 a 是显示转换为类型 b :

  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 typeEquals(a, b): return true
  7. if a == distinct and typeEquals(a.baseType, b): return true
  8. if b == distinct and typeEquals(b.baseType, a): return true
  9. if isIntegralType(a) and isIntegralType(b): return true
  10. if isSubtype(a, b) or isSubtype(b, a): return true

可转换关系可以通过用户定义的类型 converter “转换器”放宽。

  1. converter toInt(x: char): int = result = ord(x)
  2. var
  3. x: int
  4. chr: char = 'a'
  5. # 这里产生隐式转换
  6. x = chr
  7. echo x # => 97
  8. # 也可以使用显式形式
  9. x = chr.toInt
  10. echo x # => 97

如果 a 是左值,并且 typeEqualsOrDistinct(T, typeof(a)) 成立,则类型转换 T(a) 是左值。

赋值兼容

一个表达式 b 可以被赋值给一个表达式 a 如果 a 是一个 l-value 并且保持 isImplicitlyConvertible(b.typ, a.typ) 。