Casting from AnyHashable to AnyHashable should never create another wrapper (#36470)

* Casting from AnyHashable to AnyHashable should never create another wrapper

This adds a conformance for _HasCustomAnyHashableRepresentation to
AnyHashable that simply returns self.  This ensures that anytime
you try to create a new AnyHashable wrapper for an existing
AnyHashable, you just get back the original.

Resolves rdar://75180619

* Move the `Struct AnyHashable` change to `without-asserts` list

As suggested by @lorentey
This commit is contained in:
tbkka
2021-03-22 09:03:29 -07:00
committed by GitHub
parent 3d2fd566cc
commit 26ab27648e
3 changed files with 31 additions and 0 deletions

View File

@@ -260,6 +260,13 @@ extension AnyHashable: CustomReflectable {
}
}
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
extension AnyHashable: _HasCustomAnyHashableRepresentation {
public __consuming func _toCustomAnyHashable() -> AnyHashable? {
return self
}
}
/// Returns a default (non-custom) representation of `self`
/// as `AnyHashable`.
///

View File

@@ -924,4 +924,27 @@ CastsTests.test("Optional cast to AnyHashable") {
expectNotEqual(xh, yh)
}
// Repeatedly casting to AnyHashable should still test equal.
// (This was broken for a while because repeatedly casting to
// AnyHashable could end up with multiple nested AnyHashables.)
// rdar://75180619
CastsTests.test("Recursive AnyHashable") {
struct P: Hashable {
var x: Int
}
struct S {
var x: AnyHashable?
init<T: Hashable>(_ x: T?) {
self.x = x
}
}
let p = P(x: 0)
let hp = p as AnyHashable?
print(hp.debugDescription)
let s = S(hp)
print(s.x.debugDescription)
expectEqual(s.x, hp)
expectEqual(s.x, p)
}
runAllTests()

View File

@@ -48,6 +48,7 @@ Func Collection.subranges(where:) has been removed
Func MutableCollection.moveSubranges(_:to:) has been removed
Func MutableCollection.removeSubranges(_:) has been removed
Func RangeReplaceableCollection.removeSubranges(_:) has been removed
Struct AnyHashable has added a conformance to an existing protocol _HasCustomAnyHashableRepresentation
Struct DiscontiguousSlice has been removed
Struct RangeSet has been removed
Subscript Collection.subscript(_:) has been removed