Skip to content

Commit e4cc22f

Browse files
authored
Merge pull request swiftlang#62992 from apple/egorzhdan/cxx-overlay-improvements
[cxx-interop] Various improvements to the stdlib overlay
2 parents a96e5d0 + ed70f30 commit e4cc22f

File tree

7 files changed

+43
-35
lines changed

7 files changed

+43
-35
lines changed

benchmark/cxx-source/CxxStringConversion.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public func run_swiftToCxx(_ n: Int) {
5454
public func run_cxxToSwift(_ n: Int) {
5555
let str = cxxString!
5656
for _ in 0..<n {
57-
let x = String(cxxString: str)
57+
let x = String(str)
5858
blackHole(x)
5959
}
6060
}

lib/ClangImporter/ClangDerivedConformances.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ void swift::conformToCxxSequenceIfNeeded(
500500
},
501501
LookUpConformanceInModule(module));
502502

503+
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("Element"), pointeeTy);
503504
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("Index"), indexTy);
504505
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("Indices"), indicesTy);
505506
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("SubSequence"),
@@ -516,9 +517,11 @@ void swift::conformToCxxSequenceIfNeeded(
516517
// copy of the sequence's elements) by conforming the type to
517518
// CxxCollectionConvertible. This enables an overload of Array.init declared
518519
// in the Cxx module.
519-
if (!conformedToRAC && cxxConvertibleProto)
520+
if (!conformedToRAC && cxxConvertibleProto) {
521+
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("Element"), pointeeTy);
520522
impl.addSynthesizedProtocolAttrs(
521523
decl, {KnownProtocolKind::CxxConvertibleToCollection});
524+
}
522525
}
523526

524527
void swift::conformToCxxSetIfNeeded(ClangImporter::Implementation &impl,

stdlib/public/Cxx/CxxConvertibleToCollection.swift

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
/// A C++ type that can be converted to a Swift collection.
14-
public protocol CxxConvertibleToCollection {
14+
public protocol CxxConvertibleToCollection<Element> {
15+
associatedtype Element
1516
associatedtype RawIterator: UnsafeCxxInputIterator
17+
where RawIterator.Pointee == Element
1618

1719
/// Do not implement this function manually in Swift.
1820
mutating func __beginUnsafe() -> RawIterator
@@ -21,52 +23,51 @@ public protocol CxxConvertibleToCollection {
2123
mutating func __endUnsafe() -> RawIterator
2224
}
2325

24-
@inlinable @inline(__always)
25-
internal func forEachElement<C: CxxConvertibleToCollection>(
26-
of c: C,
27-
body: (C.RawIterator.Pointee) -> Void
28-
) {
29-
var mutableC = c
30-
withExtendedLifetime(mutableC) {
31-
var rawIterator = mutableC.__beginUnsafe()
32-
let endIterator = mutableC.__endUnsafe()
26+
extension CxxConvertibleToCollection {
27+
@inlinable
28+
internal func forEach(_ body: (RawIterator.Pointee) -> Void) {
29+
var mutableSelf = self
30+
var rawIterator = mutableSelf.__beginUnsafe()
31+
let endIterator = mutableSelf.__endUnsafe()
3332
while rawIterator != endIterator {
3433
body(rawIterator.pointee)
3534
rawIterator = rawIterator.successor()
3635
}
36+
withExtendedLifetime(mutableSelf) {}
3737
}
3838
}
3939

40-
extension Array {
41-
/// Creates an array containing the elements of a C++ container.
40+
extension RangeReplaceableCollection {
41+
/// Creates a collection containing the elements of a C++ container.
4242
///
43-
/// This initializes the array by copying every element of the C++ container.
43+
/// This initializes the collection by copying every element of the C++
44+
/// container.
4445
///
4546
/// - Complexity: O(*n*), where *n* is the number of elements in the C++
4647
/// container when each element is copied in O(1). Note that this might not
4748
/// be true for certain C++ types, e.g. those with a custom copy
4849
/// constructor that performs additional logic.
49-
public init<C: CxxConvertibleToCollection>(_ c: C)
50+
public init<C: CxxConvertibleToCollection>(_ elements: C)
5051
where C.RawIterator.Pointee == Element {
5152

5253
self.init()
53-
forEachElement(of: c) { self.append($0) }
54+
elements.forEach { self.append($0) }
5455
}
5556
}
5657

57-
extension Set {
58-
/// Creates an set containing the elements of a C++ container.
58+
extension SetAlgebra {
59+
/// Creates a set containing the elements of a C++ container.
5960
///
6061
/// This initializes the set by copying every element of the C++ container.
6162
///
6263
/// - Complexity: O(*n*), where *n* is the number of elements in the C++
6364
/// container when each element is copied in O(1). Note that this might not
6465
/// be true for certain C++ types, e.g. those with a custom copy
6566
/// constructor that performs additional logic.
66-
public init<C: CxxConvertibleToCollection>(_ c: C)
67+
public init<C: CxxConvertibleToCollection>(_ elements: C)
6768
where C.RawIterator.Pointee == Element {
6869

6970
self.init()
70-
forEachElement(of: c) { self.insert($0) }
71+
elements.forEach { self.insert($0) }
7172
}
7273
}

stdlib/public/Cxx/CxxRandomAccessCollection.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ extension UnsafePointer: UnsafeCxxRandomAccessIterator {}
2828

2929
extension UnsafeMutablePointer: UnsafeCxxRandomAccessIterator {}
3030

31-
public protocol CxxRandomAccessCollection: CxxSequence, RandomAccessCollection {
31+
public protocol CxxRandomAccessCollection<Element>: CxxSequence, RandomAccessCollection {
32+
override associatedtype Element
3233
override associatedtype RawIterator: UnsafeCxxRandomAccessIterator
34+
where RawIterator.Pointee == Element
3335
override associatedtype Iterator = CxxIterator<Self>
34-
override associatedtype Element = RawIterator.Pointee
3536
override associatedtype Index = Int
3637
override associatedtype Indices = Range<Int>
3738
override associatedtype SubSequence = Slice<Self>
@@ -67,7 +68,7 @@ extension CxxRandomAccessCollection {
6768
// Not using CxxIterator here to avoid making a copy of the collection.
6869
var rawIterator = __beginUnsafe()
6970
rawIterator += RawIterator.Distance(index)
70-
yield rawIterator.pointee as! Element
71+
yield rawIterator.pointee
7172
}
7273
}
7374
}

stdlib/public/Cxx/CxxSequence.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,15 @@ extension UnsafeMutablePointer: UnsafeCxxInputIterator {}
4040
extension Optional: UnsafeCxxInputIterator where Wrapped: UnsafeCxxInputIterator {
4141
public typealias Pointee = Wrapped.Pointee
4242

43+
@inlinable
4344
public var pointee: Pointee {
4445
if let value = self {
4546
return value.pointee
4647
}
4748
fatalError("Could not dereference nullptr")
4849
}
4950

51+
@inlinable
5052
public func successor() -> Self {
5153
if let value = self {
5254
return value.successor()
@@ -63,9 +65,10 @@ extension Optional: UnsafeCxxInputIterator where Wrapped: UnsafeCxxInputIterator
6365
/// This requires the C++ sequence type to define const methods `begin()` and
6466
/// `end()` which return input iterators into the C++ sequence. The iterator
6567
/// types must conform to `UnsafeCxxInputIterator`.
66-
public protocol CxxSequence: Sequence {
68+
public protocol CxxSequence<Element>: Sequence {
69+
override associatedtype Element
6770
associatedtype RawIterator: UnsafeCxxInputIterator
68-
override associatedtype Element = RawIterator.Pointee
71+
where RawIterator.Pointee == Element
6972
override associatedtype Iterator = CxxIterator<Self>
7073

7174
// `begin()` and `end()` have to be mutating, otherwise calling

stdlib/public/Cxx/std/String.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ extension std.string: ExpressibleByStringLiteral {
3131

3232
extension std.string: CustomDebugStringConvertible {
3333
public var debugDescription: String {
34-
return "std.string(\(String(cxxString: self)))"
34+
return "std.string(\(String(self)))"
3535
}
3636
}
3737

3838
extension std.string: CustomStringConvertible {
3939
public var description: String {
40-
return String(cxxString: self)
40+
return String(self)
4141
}
4242
}
4343

@@ -49,7 +49,7 @@ extension String {
4949
/// (`"\u{FFFD}"`).
5050
///
5151
/// - Complexity: O(*n*), where *n* is the number of bytes in the C++ string.
52-
public init(cxxString: std.string) {
52+
public init(_ cxxString: std.string) {
5353
let buffer = UnsafeBufferPointer<CChar>(
5454
start: cxxString.__c_strUnsafe(),
5555
count: cxxString.size())

test/Interop/Cxx/stdlib/overlay/std-string-overlay.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ var StdStringOverlayTestSuite = TestSuite("std::string overlay")
1010

1111
StdStringOverlayTestSuite.test("std::string <=> Swift.String") {
1212
let cxx1 = std.string()
13-
let swift1 = String(cxxString: cxx1)
13+
let swift1 = String(cxx1)
1414
expectEqual(swift1, "")
1515

1616
let cxx2 = std.string("something123")
17-
let swift2 = String(cxxString: cxx2)
17+
let swift2 = String(cxx2)
1818
expectEqual(swift2, "something123")
1919

2020
let cxx3: std.string = "literal"
@@ -23,25 +23,25 @@ StdStringOverlayTestSuite.test("std::string <=> Swift.String") {
2323
// Non-ASCII characters are represented by more than one CChar.
2424
let cxx4: std.string = "тест"
2525
expectEqual(cxx4.size(), 8)
26-
let swift4 = String(cxxString: cxx4)
26+
let swift4 = String(cxx4)
2727
expectEqual(swift4, "тест")
2828

2929
let cxx5: std.string = "emoji_🤖"
3030
expectEqual(cxx5.size(), 10)
31-
let swift5 = String(cxxString: cxx5)
31+
let swift5 = String(cxx5)
3232
expectEqual(swift5, "emoji_🤖")
3333

3434
let cxx6 = std.string("xyz\0abc")
3535
expectEqual(cxx6.size(), 7)
36-
let swift6 = String(cxxString: cxx6)
36+
let swift6 = String(cxx6)
3737
expectEqual(swift6, "xyz\0abc")
3838

3939
var cxx7 = std.string()
4040
let bytes: [UInt8] = [0xE1, 0xC1, 0xAC]
4141
for byte in bytes {
4242
cxx7.push_back(CChar(bitPattern: byte))
4343
}
44-
let swift7 = String(cxxString: cxx7)
44+
let swift7 = String(cxx7)
4545
expectEqual(swift7, "���")
4646
}
4747

0 commit comments

Comments
 (0)