隐式公共访问(布尔值)内部类型"Builtin.Int1":将'Int1'实例追加到数组时运行时异常



问题

  • 我知道我可能不应该摆弄内置类型,但我很好奇,Builtin.Int1类型真的应该像下面这样公开访问吗?如果是这样的话,为什么将它用作数组元素会导致Swift崩溃

我很好奇,因为我从来没有遇到过我自己无法存储在数组中的自定义类型(但我想内置类型与我可以使用"public Swift"构建的类型不同)。

我使用的是Swift 2.2和Xcode 7.3。


详细信息

查看swift/stdlib/public/core/Bol.swift的源代码,我们注意到,我们可以隐式地访问内部类型Builtin.Int1(1位整数),它构成swift中Bool类型的基础。

public struct Bool {
    internal var _value: Builtin.Int1
    // ...
}
extension Bool : Boolean {
    // ...
    public func _getBuiltinLogicValue() -> Builtin.Int1 {
        return _value
    }
    // ...
}

因此,使用_getBuiltinLogicValue(),我们可以构造Builtin.Int1类型的值,并使用它声明[Builtin.Int1]类型的空数组。

/* public access to _getBuiltinLogicValue() ... */
let bar = false._getBuiltinLogicValue()
print(bar.dynamicType)
    /* '<<<opaque type>>>' */
    /* Alt-click: 'Int1' type */
print(_getBool(bar)) // false, OK
/* construct an empty array of 'Int1':s         */
func foo<T>(val: T, arr: [T] = []) -> [T] {
    return arr
}
var arr = foo(bar)
print(arr.dynamicType)
    /* 'Array<<<<opaque type>>>>' */
    /* Alt-click: '[Int1]' type */

然而,如果我们试图将任何Builtint.Int1元素添加到这个数组中,Swift就会崩溃(运行时异常)

/* however any attempt to fill such an array (or initialize
   one as none-empty) will yield a runtime exception         */
//arr.append(bar)   // runtime error
//let arr2 = [bar]  // runtime error

执行中断,原因:EXC_BAD_ACCESS(代码=1,地址=0x10)

我最后注意到,在源swift/stdlib/public/core/Builtin.swift中,

// Definitions that make elements of Builtin usable in real code
// without gobs of boilerplate.

这可能表明我们应该能够使用上面的内置类型。

调用带前导下划线的方法时,就不再调用公共方法。它有一个public属性的事实通常是由于语言限制,要求它是这样的。将其与_ArrayType进行比较,后者在技术上也是public,但这只是因为Swift无法隐藏实现细节。你仍然不应该直接使用它。他们强调这些事情是有原因的。(我在自己的代码中遇到过这种情况。创建依赖非公共属性的协议扩展通常很困难或不可能;当你完成时,许多你想要成为privateinternal的东西必须是public,否则它就无法编译。)

你最初的断言"我可能不应该摆弄内置类型"在这个时候是正确的。在未来,可能会有更多的内置产品。但事实上,你必须欺骗编译器,甚至允许通过泛型实现这一点,这应该是你的问题的答案。不可以。您不应该期望能够以这种方式使用内置类型。

最新更新