почему я получаю это предупреждение, чтобы реализовать хэш (в :) для типа, который соответствует протоколу с реализацией по умолчанию

Код ниже показывает предупреждение:

 ❯ swiftc demo.swift                                                                                                                                                                       [13:06:57]
Swift.RawRepresentable:2:27: warning: 'Hashable.hashValue' is deprecated as a protocol requirement; conform type 'PlaybackSpeed' to 'Hashable' by implementing 'hash(into:)' instead
    @inlinable public var hashValue: Int { get }

Перечисление PlaybackSpeed ​​должно иметь функции resetSettings() & hash(into:) из реализации по умолчанию, поэтому это предупреждение не должно создаваться.

Я неправильно понимаю или это ошибка компилятора?

protocol Settingsable {
  func resetSettings()
}

protocol SettingsSelectable: Hashable, Settingsable {
  var display: String { get }
}

extension SettingsSelectable {
  func hash(into hasher: inout Hasher) {
    hasher.combine(display)
  }
}

extension SettingsSelectable {
    func resetSettings() {
      print("These have been reset")
    }
}

enum PlaybackSpeed: Int, SettingsSelectable {
  case half
  case standard
  case onePointFive
  case double

  var display: String {
    switch self {
    case .half:
      return "0.5x"
    case .standard:
      return "1.0x"
    case .onePointFive:
      return "1.5x"
    case .double:
      return "2.0x"
    }
  }
}

1 ответ

Решение

Этот код имеет две реализации по умолчанию для hash(into:). Один из Int и один из SettingSelectable.

Я не уверен, определено ли это поведение. Я ожидаю, что используется реализация Int, а расширение SettingsSelectable игнорируется. В любом случае диагностика не очень хорошая. Предлагаю открыть дефект по этому поводу.

Вы можете исправить эту ошибку, удалив Int, или явно реализовав hash(into:)так что понятно, о чем вы говорите. Или вы можете создать другой уровень протоколов:

protocol SettingsSelectableBase: Hashable, Settingsable {
  var display: String { get }
}

protocol SettingsSelectable: SettingsSelectableBase {}

// Only give the default to things that ask for it, not to Base conformers
extension SettingsSelectable {
  func hash(into hasher: inout Hasher) {
    hasher.combine(display)
  }
}

extension SettingsSelectableBase {
    func resetSettings() {
      print("These have been reset")
    }
}

enum PlaybackSpeed: Int, SettingsSelectableBase { ... }
Другие вопросы по тегам