Передача общей структуры для неименованного параметра по умолчанию приводит к свойствам мусора

Я вижу некоторое нечетное поведение в классе, который я создал некоторое время назад, когда кажется, что свойства структуры меняются сразу же после передачи (копирования) методу.

Я перевернул его до простого тестового примера, который можно запустить на игровой площадке:

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)

Посмотрев на соответствующие печатные заявления, он показывает, что свойство struct x изменилось:

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


Создание структуры вне класса и вызов 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)


Изменение метода/функции 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)


Это ошибка компилятора? Кажется, компилятору это не нравится, когда общая функция/метод с единственным аргументом со значением по умолчанию не использует имя внешнего параметра. Это конкретный случай, но я думаю, что он должен работать. Если это не должно работать, должно быть предупреждение о компиляторе.

Ответ 1

Ошибка компилятора 110%. Я даже пробовал это из игровой площадки. Все это с радостью компилируется, пока вы не захотите добавить строку, которая на самом деле что-то делает, например, отправив passStruct. Там все в этом не так. У меня даже не получилось:

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

который, как я думал, может быть проблемой (хотя это не должно быть у меня в другом месте).

Хорошо! Доложите об этом. Они явно не закончены с дженериками. В моих экспериментах я обнаружил, что свойства универсального класса не допускаются.

static let nilStruct: StructToPass<T>? = nil

не компилируется с одним из сообщений об ошибке "еще не поддерживаемые".