我想您刚刚发现了一个编译器错误!
通常,对于这样的for
循环,编译器会生成从UIntRange
获取iterator
的代码,并执行while (iterator.hasNext())
循环.
然而,看看生成的Java字节码(这种行为无法在Kotlin/JS上重现),编译器似乎试图将其优化为类似于以下Java(伪)代码的C风格for循环:
for (UInt b = UByte.MIN_VALUE ; b <= UByte.MAX_VALUE ; b++) {
// ...
}
然而,它没有执行b <= UByte.MAX_VALUE
,而是生成b <= UInt.MAX_VALUE
.以下是字节码示例:
5: iconst_0
6: istore_1
7: iload_1
8: iconst_m1
9: invokestatic #18 // Method kotlin/UnsignedKt.uintCompare:(II)I
12: ifgt 28
15: iload_1
16: istore_2
17: iload_2
18: iconst_m1
19: if_icmpeq 28
22: iinc 1, 1
25: goto 15
28: return
注意iconst_m1
,这将-1推入为int
(这是无符号int的最大值).
为了实现正确的结果,您可以首先将范围表达分配给某个本地val
,因此编译器不会进行这种优化(尽管这在技术上无法保证).
这显然违反了Kotlin规范规定的for
循环应该做的事情.根据spec,for
循环相当于:
when(val iter = (UByte.MIN_VALUE..UByte.MAX_VALUE).iterator()) {
else -> while (iter.hasNext()) {
val b = iter.next()
// loop body goes here...
}
}
但这只能从0到255循环,这是正确的.