Помилка компілятора Swift: У випадку "enum" є один кордон як пов'язане значення, але тут є кілька шаблонів.


12

Створюючи проект у Xcode 11.4 beta 3, я отримую цю помилку компілятора Swift на перелік:

У випадку перерахунку є один кортеж як пов’язане значення, але тут є декілька шаблонів, які неявно переплітають шаблони та намагаються відповідати цьому

Вихідний код:

switch result {
case .error(let err):
    //
case .value(let staff, let locations):  // <-- error on this line
    //
}

Resultє загальним перерахуванням із пов'язаними значеннями для .errorта .value. У цьому випадку асоційоване значення є tupple.

public enum Result<T> {
    case value(T)
    case error(Error)
}

Не пригадайте, як бачили цю помилку раніше, і пошук її не дав жодних результатів. Будь-які ідеї?


1
Я оновив питання, вибачте за те, що залишив його
Енеко Алонсо

Не потрібно винаходити колесо Result; воно вже існує. developer.apple.com/documentation/swift/result
мат

Також не існує Xcode 11.4 beta 4 (поки що).
мат

Моє погано, я мав на увазі Xcode 11.4 beta 3. Що стосується Result, я згоден, це старий код, який передує Swift.Result. Однак це не має нічого спільного.
Енеко Алонсо

1
Я повністю згоден, я просто намагаюся прибрати питання. Ви піднімаєте тут хорошу точку, і це наш шанс задокументувати правильні підходи, які можуть знайти інші.
мат

Відповіді:


14

Я виявив, що ви можете також заглушити цю помилку, обробляючи пов’язане значення більше як кортеж, загортаючи його в додатковий набір дужок:

switch result {
case .error(let err):
    //
case .value((let staff, let locations)):  
    //
}

1
Це приємно, мені це подобається, дякую.
Енеко Алонсо

2
Подумайте про переміщення let, якщо ви збираєтесь все зв'язати: case let .value( (staff, locations) ):і case .value( let (staff, locations) ):обидва компілюють. Оберіть свою подорож!
Джессі

1
Супер другорядний, але я стилістично не погоджуюся з вищезазначеним коментарем щодо зв’язування всього одним дозволом. Дозволити лише ліворуч від прив’язаної речі простіше читати та швидко розуміти, до чого пов’язані речі. Інакше вам потрібно подумки екстраполювати те, що нехай є обов'язковим. Керівні принципи кодування Google для швидкого використання також радять проти єдиного каскадного дозволу
ToddH

2
Вказівки "Google": /
Gee.E

9

Гаразд, зрозумів це. Схоже, що enumз пов’язаними значеннями, де тип значення є tupple, більше не може відповідати оператору перемикача таким чином:

// Works on Xcode 11.3.1, yields error on 11.4 (Swift 5.2)
switch result {
case .error(let err):
    //
case .value(let staff, let locations):  
    //
}

Рішення

Значення з tupple повинні бути вилучені вручну в Xcode 11.4 (Swift 5.2):

// Works on Xcode 11.4
switch result {
case .error(let err):
    //
case .value(let tupple):  
    let (staff, locations) = tupple
    // 
}

Це, безумовно, одне рішення.
мат

3

Це відома проблема: https://developer.apple.com/documentation/xcode_release_notes/xcode_11_4_release_notes

Код, який спирається на компілятор, який автоматично перетворює шаблон, може призвести до помилки компілятора під час оновлення до Xcode 11.4, навіть незважаючи на те, що код, складений раніше. (58425942)

Наприклад, вимикання круглих дужок при включенні опціонального типу кортежу викликає помилку компілятора:

switch x { // error: switch must be exhaustive
case .some((let a, let b), let c): // warning: the enum case has a
     // single tuple as an associated value, but there are several
     // patterns here, implicitly tupling the patterns and trying
     // to match that instead
...

}

Обхід : Додайте додаткові дужки, щоб явно змінити шаблон:

switch x {
case .some(((let a, let b), let c)): // Notice the extra pair of parentheses.
...

}


Дякуємо за додаткову інформацію та посилання на нотатки до випуску. Я пропустив це.
Енеко Алонсо

0

Якщо я можу, я хотів би додати відповідь і для if caseверсії.

if case let .value(staff, error) = result {
    // Do something
}

а потім, звичайно, ігнорування випадку:

if case let .value(staff, _) = result {
    // Do something
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.