The code below shows the warning:
❯ 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 }
The enum PlaybackSpeed should have the functions resetSettings()
& hash(into:)
from the default implementation so this warning should not be generated.
Is my understanding wrong or is this a compiler bug?
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"
}
}
}
This code has two default implementations for hash(into:)
. One from Int, and one from SettingSelectable.
I'm not certain if this is defined behavior. My expectation is that the Int implementation is used and the SettingsSelectable extension is ignored. In any case, the diagnostic is not very good. I suggest opening a defect about that.
You can fix this error by removing the Int
, or by explicitly implementing hash(into:)
so it's clear which one you mean. Or you could create another layer of protocols:
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 { ... }