From 561836a6e625953af6280d5e182e9a70423eb0ac Mon Sep 17 00:00:00 2001 From: Jonathan Grynspan Date: Fri, 10 Oct 2025 08:38:23 -0400 Subject: [PATCH] [6.2] Add `Equatable` and `Hashable` conformance to `GUID`. --- stdlib/public/Windows/WinSDK.swift | 28 ++++++++++++++++++++++++++++ test/stdlib/WinSDK_GUID.swift | 22 ++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 test/stdlib/WinSDK_GUID.swift diff --git a/stdlib/public/Windows/WinSDK.swift b/stdlib/public/Windows/WinSDK.swift index 57b162390eeaa..fc031e21778ec 100644 --- a/stdlib/public/Windows/WinSDK.swift +++ b/stdlib/public/Windows/WinSDK.swift @@ -318,3 +318,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 new file mode 100644 index 0000000000000..d34febf0e7d42 --- /dev/null +++ b/test/stdlib/WinSDK_GUID.swift @@ -0,0 +1,22 @@ +// 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 +// /shared and not in /um. + +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