From 9c44e01e07fcde8be723101ebc584af13a5fd637 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 12 Dec 2024 23:15:16 -0800 Subject: [PATCH] [cxx-interop][stdlib] windows - use new hash inline functions like other platforms The PR https://github.com/swiftlang/swift/pull/77857 added windows-specific workaround for https://github.com/swiftlang/swift/issues/77856, that happened after https://github.com/swiftlang/swift/pull/77843. Unfortunately this caused a new issue on windows - https://github.com/swiftlang/swift/issues/78119. It looks like windows is suffering from a similar serialization issue as libstdc++, although its even more complex as the callAsFunction is not only a derived function from a base class, the base class although has a static call operator. In any case, the libstdc++ callAsFunction deserialization fix should align with the static operator () deserialization too, so for now make windows use the same workaround as other platforms to avoid the deserialization crash (77856). This change was tested on i686 windows too, ensuring that IR verifier crash no longer happens --- stdlib/public/Cxx/cxxshim/libcxxstdlibshim.h | 6 +++--- stdlib/public/Cxx/std/String.swift | 12 ----------- .../Cxx/stdlib/Inputs/module.modulemap | 6 ++++++ .../Cxx/stdlib/Inputs/std-string-and-vector.h | 11 ++++++++++ .../Cxx/stdlib/use-std-string-with-opts.swift | 20 +++++++++++++++++++ 5 files changed, 40 insertions(+), 15 deletions(-) create mode 100644 test/Interop/Cxx/stdlib/Inputs/std-string-and-vector.h create mode 100644 test/Interop/Cxx/stdlib/use-std-string-with-opts.swift diff --git a/stdlib/public/Cxx/cxxshim/libcxxstdlibshim.h b/stdlib/public/Cxx/cxxshim/libcxxstdlibshim.h index b457d793214df..90bb57fe315ed 100644 --- a/stdlib/public/Cxx/cxxshim/libcxxstdlibshim.h +++ b/stdlib/public/Cxx/cxxshim/libcxxstdlibshim.h @@ -4,19 +4,19 @@ /// Used for std::string conformance to Swift.Hashable typedef std::hash __swift_interopHashOfString; -inline std::size_t __swift_interopComputeHashOfString(std::string str) { +inline std::size_t __swift_interopComputeHashOfString(const 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) { +inline std::size_t __swift_interopComputeHashOfU16String(const 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) { +inline std::size_t __swift_interopComputeHashOfU32String(const std::u32string &str) { return __swift_interopHashOfU32String()(str); } diff --git a/stdlib/public/Cxx/std/String.swift b/stdlib/public/Cxx/std/String.swift index 1963aa610cebc..3d379e81cd17b 100644 --- a/stdlib/public/Cxx/std/String.swift +++ b/stdlib/public/Cxx/std/String.swift @@ -198,11 +198,7 @@ extension std.string: Hashable { @_alwaysEmitIntoClient public func hash(into hasher: inout Hasher) { // Call std::hash::operator() -#if os(Windows) // FIXME: https://github.com/swiftlang/swift/issues/77856 - let cxxHash = __swift_interopHashOfString().callAsFunction(self) -#else let cxxHash = __swift_interopComputeHashOfString(self) -#endif hasher.combine(cxxHash) } } @@ -211,11 +207,7 @@ extension std.u16string: Hashable { @_alwaysEmitIntoClient public func hash(into hasher: inout Hasher) { // Call std::hash::operator() -#if os(Windows) // FIXME: https://github.com/swiftlang/swift/issues/77856 - let cxxHash = __swift_interopHashOfU16String().callAsFunction(self) -#else let cxxHash = __swift_interopComputeHashOfU16String(self) -#endif hasher.combine(cxxHash) } } @@ -224,11 +216,7 @@ extension std.u32string: Hashable { @_alwaysEmitIntoClient public func hash(into hasher: inout Hasher) { // Call std::hash::operator() -#if os(Windows) // FIXME: https://github.com/swiftlang/swift/issues/77856 - let cxxHash = __swift_interopHashOfU32String().callAsFunction(self) -#else let cxxHash = __swift_interopComputeHashOfU32String(self) -#endif hasher.combine(cxxHash) } } diff --git a/test/Interop/Cxx/stdlib/Inputs/module.modulemap b/test/Interop/Cxx/stdlib/Inputs/module.modulemap index 6234bd4bcdc7c..57f7eae3bb670 100644 --- a/test/Interop/Cxx/stdlib/Inputs/module.modulemap +++ b/test/Interop/Cxx/stdlib/Inputs/module.modulemap @@ -40,6 +40,12 @@ module StdString { export * } +module StdStringAndVector { + header "std-string-and-vector.h" + requires cplusplus + export * +} + module StdStringView { header "std-string-view.h" requires cplusplus diff --git a/test/Interop/Cxx/stdlib/Inputs/std-string-and-vector.h b/test/Interop/Cxx/stdlib/Inputs/std-string-and-vector.h new file mode 100644 index 0000000000000..610f86f7a217c --- /dev/null +++ b/test/Interop/Cxx/stdlib/Inputs/std-string-and-vector.h @@ -0,0 +1,11 @@ +#include +#include + +struct Item { + std::vector keys; + std::vector values; +}; + +inline Item get_item() { + return {}; +} diff --git a/test/Interop/Cxx/stdlib/use-std-string-with-opts.swift b/test/Interop/Cxx/stdlib/use-std-string-with-opts.swift new file mode 100644 index 0000000000000..5b06bd3cf1f81 --- /dev/null +++ b/test/Interop/Cxx/stdlib/use-std-string-with-opts.swift @@ -0,0 +1,20 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs -cxx-interoperability-mode=default -Xcc -std=c++20 -O) +// +// REQUIRES: executable_test + +// Tests optimizations related to CxxStdlib. + +import StdlibUnittest +import CxxStdlib +import StdStringAndVector + +var StdStringOptTestSuite = TestSuite("StdStringWithOpts") + +StdStringOptTestSuite.test("std::string with Hashable conformance optimized") { + let item = get_item() + let dict = Dictionary(uniqueKeysWithValues: zip(item.keys, item.values).lazy) + + expectEqual(dict.count, 0) +} + +runAllTests()