diff --git a/benchmark/cxx-source/CxxSetToCollection.swift b/benchmark/cxx-source/CxxSetToCollection.swift index 876fcdaa0ec..3fa30a16530 100644 --- a/benchmark/cxx-source/CxxSetToCollection.swift +++ b/benchmark/cxx-source/CxxSetToCollection.swift @@ -36,6 +36,11 @@ public let benchmarks = [ runFunction: run_CxxSetOfU32_to_Set, tags: [.validation, .bridging, .cxxInterop], setUpFunction: makeSetOnce), + BenchmarkInfo( + name: "CxxSetU32.forEach", + runFunction: run_CxxSetOfU32_forEach, + tags: [.validation, .bridging, .cxxInterop], + setUpFunction: makeSetOnce), ] func makeSetOnce() { @@ -58,4 +63,13 @@ public func run_CxxSetOfU32_to_Set(_ n: Int) { } } +@inline(never) +public func run_CxxSetOfU32_forEach(_ n: Int) { + for _ in 0.. { extension CxxConvertibleToCollection { @inlinable - internal func forEach(_ body: (RawIterator.Pointee) -> Void) { + public func forEach(_ body: (RawIterator.Pointee) throws -> Void) rethrows { var rawIterator = __beginUnsafe() let endIterator = __endUnsafe() while rawIterator != endIterator { - body(rawIterator.pointee) + try body(rawIterator.pointee) rawIterator = rawIterator.successor() } } } +// Break the ambiguity between Sequence.forEach and CxxConvertibleToCollection.forEach. +extension CxxConvertibleToCollection where Self: Sequence { + @inlinable + public func forEach(_ body: (Element) throws -> Void) rethrows { + for element in self { + try body(element) + } + } +} + extension RangeReplaceableCollection { /// Creates a collection containing the elements of a C++ container. /// diff --git a/test/Interop/Cxx/stdlib/overlay/custom-collection.swift b/test/Interop/Cxx/stdlib/overlay/custom-collection.swift index 8ed059e5cd2..774565bcb59 100644 --- a/test/Interop/Cxx/stdlib/overlay/custom-collection.swift +++ b/test/Interop/Cxx/stdlib/overlay/custom-collection.swift @@ -18,6 +18,12 @@ CxxCollectionTestSuite.test("SimpleCollectionNoSubscript as Swift.Collection") { expectEqual(c[0], 1) expectEqual(c[1], 2) expectEqual(c[4], 5) + + var array: [Int32] = [] + c.forEach { + array.append($0) + } + expectEqual([1, 2, 3, 4, 5] as [Int32], array) } CxxCollectionTestSuite.test("SimpleCollectionReadOnly as Swift.Collection") { diff --git a/test/Interop/Cxx/stdlib/overlay/custom-convertible-to-collection.swift b/test/Interop/Cxx/stdlib/overlay/custom-convertible-to-collection.swift index 27c4f352d26..687f2ef2d7c 100644 --- a/test/Interop/Cxx/stdlib/overlay/custom-convertible-to-collection.swift +++ b/test/Interop/Cxx/stdlib/overlay/custom-convertible-to-collection.swift @@ -39,4 +39,13 @@ CxxSequenceTestSuite.test("SimpleEmptySequence to Swift.Set") { expectTrue(set.isEmpty) } +CxxSequenceTestSuite.test("SimpleSequence.forEach") { + let seq = SimpleSequence() + var array: [Int32] = [] + seq.forEach { + array.append($0) + } + expectEqual([1, 2, 3, 4] as [Int32], array) +} + runAllTests()