将未命名的默认参数的通用结构传递给垃圾属性。

时间:2021-03-20 11:11:34

I'm seeing some odd behaviour in a class I created a while ago, where it seems that a struct's properties are changing immediately after being passed (copied) to a method.

我在之前创建的类中看到了一些奇怪的行为,在这个类中,结构的属性在被传递(复制)到方法后立即发生变化。

I've boiled it down to a simple test case that can be run in a playground:

我把它归结为一个可以在操场上运行的简单测试用例:

struct StructToPass<T> {
    let x: T
}

class MyClass<T> {
    func createAndPassStructWithValue(value: T) {
        let structToPass = StructToPass(x: value)
        println("Before passing to method: \(structToPass.x)")
        passStruct(structToPass)
    }

    func passStruct(_ theStruct: StructToPass<T>? = nil) {
        println("Inside method: \(theStruct!.x)")
    }
}

let myClass = MyClass<Int>()
myClass.createAndPassStructWithValue(42)

Looking at the relevant printed statements, it shows that the struct's x property has changed:

看一下相关的打印报表,它显示了struct的x属性发生了变化:

// Before passing to method: 42
// Inside method: 140734543799888


Creating the struct outside the class and calling passStruct(_:) directly causes the playground to crash, as does writing passStruct(_:) as a function:

在类之外创建结构体并调用passStruct(_:)直接导致游乐场崩溃,将passStruct(_:)作为函数编写也一样:

// Causes playground to crash:
let aStruct = StructToPass(x: 42)
myClass.passStruct(aStruct)

// Also causes playground to crash:
func passStruct<T>(_ theStruct: StructToPass<T>? = nil) {}
passStruct(aStruct)


Changing the passStruct(_:) method/function to use the default external parameter name fixes the issue, as does introducing another parameter (before/after the default parameter):

更改passStruct(_:)方法/函数以使用默认的外部参数名称来修复问题,同时引入另一个参数(在默认参数之前/之后):

// This works:
func passStruct<T>(theStruct: StructToPass<T>? = nil) {
    println("Inside function: \(theStruct!.x)")
}
passStruct(theStruct: aStruct)

// This also works:
func passStruct<T>(_ theStruct: StructToPass<T>? = nil, someOtherParam: Int) {
    println("Inside function: \(theStruct!.x)")
}
passStruct(aStruct, 42)


Is this a compiler bug? It seems the compiler doesn't like it when a generic function/method with a single argument with a default value doesn't use an external parameter name. It's a specific case, but I think it ought to work. If it shouldn't work, there ought to be a compiler warning.

这是编译错误吗?当具有默认值的单个参数的泛型函数/方法不使用外部参数名称时,编译器似乎不喜欢它。这是一个具体的案例,但我认为它应该行得通。如果它不应该工作,应该有一个编译器警告。

1 个解决方案

#1


2  

110% compiler bug. I've even tried this out of Playground. It all happily compiles until you want to add a line which actually does something, like sending a passStruct. There's all kinds of things wrong with this. I even had this fail:

110%的编译器错误。我甚至在操场上试过。它会愉快地编译,直到您想要添加一个实际执行某些操作的行,比如发送passStruct。这有各种各样的问题。我甚至失败了:

func passStruct<T>(_ theStruct: StructToPass<T>? = (nil as StructToPass<T>?)) {
    println("Inside function: \(theStruct!.x)")
}

which I kinda thought might be the problem (even though it shouldn't be I've had that elsewhere).

我认为这可能是问题所在(尽管我在别处应该没有)。

Well found! Report it. They're clearly not finished with generics. In my experiments I found that generic class properties aren't allowed.

准备好了的!报告。他们显然还没有完成泛型。在我的实验中,我发现不允许泛型类属性。

static let nilStruct: StructToPass<T>? = nil

does not compile, with one of the "not yet supported" error messages.

不编译,使用“尚未支持”的错误消息之一。

#1


2  

110% compiler bug. I've even tried this out of Playground. It all happily compiles until you want to add a line which actually does something, like sending a passStruct. There's all kinds of things wrong with this. I even had this fail:

110%的编译器错误。我甚至在操场上试过。它会愉快地编译,直到您想要添加一个实际执行某些操作的行,比如发送passStruct。这有各种各样的问题。我甚至失败了:

func passStruct<T>(_ theStruct: StructToPass<T>? = (nil as StructToPass<T>?)) {
    println("Inside function: \(theStruct!.x)")
}

which I kinda thought might be the problem (even though it shouldn't be I've had that elsewhere).

我认为这可能是问题所在(尽管我在别处应该没有)。

Well found! Report it. They're clearly not finished with generics. In my experiments I found that generic class properties aren't allowed.

准备好了的!报告。他们显然还没有完成泛型。在我的实验中,我发现不允许泛型类属性。

static let nilStruct: StructToPass<T>? = nil

does not compile, with one of the "not yet supported" error messages.

不编译,使用“尚未支持”的错误消息之一。