From c57756168fcee43725bf5ab4b9bbfb5709ca9bf0 Mon Sep 17 00:00:00 2001 From: Egor Zhdan Date: Tue, 26 Nov 2024 16:27:05 +0000 Subject: [PATCH] [cxx-interop] Workaround a deserialization error for CxxStdlib on Linux In certain versions of libstdc++, `std::hash` defines `operator()` in a base class. It looks like Swift is not correctly deserializing an inherited `operator()` for inlinable functions. This change sidesteps the issue by moving the call to `callAsFunction`/`operator()` to the C++ shim layer. rdar://140358388 --- stdlib/public/Cxx/cxxshim/libcxxstdlibshim.h | 9 +++++++++ stdlib/public/Cxx/std/String.swift | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/stdlib/public/Cxx/cxxshim/libcxxstdlibshim.h b/stdlib/public/Cxx/cxxshim/libcxxstdlibshim.h index 2cae724ff287b..b457d793214df 100644 --- a/stdlib/public/Cxx/cxxshim/libcxxstdlibshim.h +++ b/stdlib/public/Cxx/cxxshim/libcxxstdlibshim.h @@ -4,12 +4,21 @@ /// Used for std::string conformance to Swift.Hashable typedef std::hash __swift_interopHashOfString; +inline std::size_t __swift_interopComputeHashOfString(std::string str) { + return __swift_interopHashOfString()(str); +} /// Used for std::u16string conformance to Swift.Hashable typedef std::hash __swift_interopHashOfU16String; +inline std::size_t __swift_interopComputeHashOfU16String(std::u16string str) { + return __swift_interopHashOfU16String()(str); +} /// Used for std::u32string conformance to Swift.Hashable typedef std::hash __swift_interopHashOfU32String; +inline std::size_t __swift_interopComputeHashOfU32String(std::u32string str) { + return __swift_interopHashOfU32String()(str); +} inline std::chrono::seconds __swift_interopMakeChronoSeconds(int64_t seconds) { return std::chrono::seconds(seconds); diff --git a/stdlib/public/Cxx/std/String.swift b/stdlib/public/Cxx/std/String.swift index e0ef78b981e0d..3d379e81cd17b 100644 --- a/stdlib/public/Cxx/std/String.swift +++ b/stdlib/public/Cxx/std/String.swift @@ -198,7 +198,7 @@ extension std.string: Hashable { @_alwaysEmitIntoClient public func hash(into hasher: inout Hasher) { // Call std::hash::operator() - let cxxHash = __swift_interopHashOfString().callAsFunction(self) + let cxxHash = __swift_interopComputeHashOfString(self) hasher.combine(cxxHash) } } @@ -207,7 +207,7 @@ extension std.u16string: Hashable { @_alwaysEmitIntoClient public func hash(into hasher: inout Hasher) { // Call std::hash::operator() - let cxxHash = __swift_interopHashOfU16String().callAsFunction(self) + let cxxHash = __swift_interopComputeHashOfU16String(self) hasher.combine(cxxHash) } } @@ -216,7 +216,7 @@ extension std.u32string: Hashable { @_alwaysEmitIntoClient public func hash(into hasher: inout Hasher) { // Call std::hash::operator() - let cxxHash = __swift_interopHashOfU32String().callAsFunction(self) + let cxxHash = __swift_interopComputeHashOfU32String(self) hasher.combine(cxxHash) } }