From 5846e8f6a4a4d23d6b5a96af33f71d5d18832c6b Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 10 Oct 2025 08:34:34 -0400 Subject: [PATCH] Add `Equatable` and `Hashable` conformance to `GUID`. (#84792) On Windows, `GUID` is a currency type and (along with its various typedefs) is used pervasively Windows offers `IsEqualGUID()` and `UuidHash()` for comparing and hashing them, respectively, but `IsEqualGUID()` is a macro in C mode and `UuidHash()` only provides a 16-bit hash. We should provide conformance to these protocols in the WinSDK overlay to provide equivalent functionality in Swift. --- stdlib/public/Windows/WinSDK.swift | 28 ++++++++++++++++++++++++++++ test/stdlib/WinSDK_GUID.swift | 15 ++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/stdlib/public/Windows/WinSDK.swift b/stdlib/public/Windows/WinSDK.swift index cfa0f2fdee6..435adbad3c5 100644 --- a/stdlib/public/Windows/WinSDK.swift +++ b/stdlib/public/Windows/WinSDK.swift @@ -319,3 +319,31 @@ func _convertWindowsBoolToBool(_ b: WindowsBool) -> Bool { return b.boolValue } +// GUID + +extension GUID { + @usableFromInline @_transparent + internal var uint128Value: UInt128 { + unsafe withUnsafeBytes(of: self) { buffer in + // GUID is 32-bit-aligned only, so use loadUnaligned(). + unsafe buffer.baseAddress!.loadUnaligned(as: UInt128.self) + } + } +} + +// These conformances are marked @retroactive because the GUID type nominally +// comes from the _GUIDDef clang module rather than the WinSDK clang module. + +extension GUID: @retroactive Equatable { + @_transparent + public static func ==(lhs: Self, rhs: Self) -> Bool { + lhs.uint128Value == rhs.uint128Value + } +} + +extension GUID: @retroactive Hashable { + @_transparent + public func hash(into hasher: inout Hasher) { + hasher.combine(uint128Value) + } +} diff --git a/test/stdlib/WinSDK_GUID.swift b/test/stdlib/WinSDK_GUID.swift index 63188815700..d34febf0e7d 100644 --- a/test/stdlib/WinSDK_GUID.swift +++ b/test/stdlib/WinSDK_GUID.swift @@ -1,4 +1,7 @@ -// RUN: %target-build-swift %s +// RUN: %target-build-swift %s -o %t.exe +// RUN: %target-codesign %t.exe +// RUN: %target-run %t.exe +// REQUIRES: executable_test // REQUIRES: OS=windows-msvc // Make sure that importing WinSDK brings in the GUID type, which is declared in @@ -7,3 +10,13 @@ import WinSDK public func usesGUID(_ x: GUID) {} + +// Make sure equating and hashing GUIDs works. + +let guid: GUID = GUID_NULL +assert(guid == guid) +assert(guid.hashValue == guid.hashValue) + +let guid2: GUID = IID_IUnknown +assert(guid != guid2) +assert(guid.hashValue != guid2.hashValue) // well, probably