Skip to content

Commit 276a232

Browse files
authored
Merge pull request #67536 from apple/egorzhdan/unsafe-cxx-mutable-input-iterator
[cxx-interop] Add `UnsafeCxxMutableInputIterator` protocol
2 parents 632f0a3 + 8d7d0ef commit 276a232

File tree

7 files changed

+84
-3
lines changed

7 files changed

+84
-3
lines changed

include/swift/AST/KnownProtocols.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ PROTOCOL(CxxRandomAccessCollection)
116116
PROTOCOL(CxxSequence)
117117
PROTOCOL(CxxUniqueSet)
118118
PROTOCOL(UnsafeCxxInputIterator)
119+
PROTOCOL(UnsafeCxxMutableInputIterator)
119120
PROTOCOL(UnsafeCxxRandomAccessIterator)
120121

121122
PROTOCOL(AsyncSequence)

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,7 @@ ProtocolDecl *ASTContext::getProtocol(KnownProtocolKind kind) const {
11401140
case KnownProtocolKind::CxxSequence:
11411141
case KnownProtocolKind::CxxUniqueSet:
11421142
case KnownProtocolKind::UnsafeCxxInputIterator:
1143+
case KnownProtocolKind::UnsafeCxxMutableInputIterator:
11431144
case KnownProtocolKind::UnsafeCxxRandomAccessIterator:
11441145
M = getLoadedModule(Id_Cxx);
11451146
break;

lib/ClangImporter/ClangDerivedConformances.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,11 @@ void swift::conformToCxxIteratorIfNeeded(
432432
if (!pointee || pointee->isGetterMutating() || pointee->getType()->hasError())
433433
return;
434434

435+
// Check if `var pointee: Pointee` is settable. This is required for the
436+
// conformance to UnsafeCxxMutableInputIterator but is not necessary for
437+
// UnsafeCxxInputIterator.
438+
bool pointeeSettable = pointee->isSettable(nullptr);
439+
435440
// Check if present: `func successor() -> Self`
436441
auto successorId = ctx.getIdentifier("successor");
437442
auto successor =
@@ -469,8 +474,13 @@ void swift::conformToCxxIteratorIfNeeded(
469474

470475
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("Pointee"),
471476
pointee->getType());
472-
impl.addSynthesizedProtocolAttrs(decl,
473-
{KnownProtocolKind::UnsafeCxxInputIterator});
477+
if (pointeeSettable)
478+
impl.addSynthesizedProtocolAttrs(
479+
decl, {KnownProtocolKind::UnsafeCxxMutableInputIterator});
480+
else
481+
impl.addSynthesizedProtocolAttrs(
482+
decl, {KnownProtocolKind::UnsafeCxxInputIterator});
483+
474484
if (!isRandomAccessIterator ||
475485
!ctx.getProtocol(KnownProtocolKind::UnsafeCxxRandomAccessIterator))
476486
return;

lib/IRGen/GenMeta.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6311,6 +6311,7 @@ SpecialProtocol irgen::getSpecialProtocolID(ProtocolDecl *P) {
63116311
case KnownProtocolKind::CxxSequence:
63126312
case KnownProtocolKind::CxxUniqueSet:
63136313
case KnownProtocolKind::UnsafeCxxInputIterator:
6314+
case KnownProtocolKind::UnsafeCxxMutableInputIterator:
63146315
case KnownProtocolKind::UnsafeCxxRandomAccessIterator:
63156316
case KnownProtocolKind::Executor:
63166317
case KnownProtocolKind::SerialExecutor:

stdlib/public/Cxx/UnsafeCxxIterators.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ extension Optional: UnsafeCxxInputIterator where Wrapped: UnsafeCxxInputIterator
5757
}
5858
}
5959

60+
public protocol UnsafeCxxMutableInputIterator: UnsafeCxxInputIterator {
61+
override var pointee: Pointee { get set }
62+
}
63+
6064
/// Bridged C++ iterator that allows computing the distance between two of its
6165
/// instances, and advancing an instance by a given number of elements.
6266
///

test/Interop/Cxx/stdlib/overlay/Inputs/custom-iterator.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,4 +866,60 @@ struct InputOutputIterator {
866866
}
867867
};
868868

869+
struct MutableRACIterator {
870+
private:
871+
int value;
872+
873+
public:
874+
struct iterator_category : std::random_access_iterator_tag,
875+
std::output_iterator_tag {};
876+
using value_type = int;
877+
using pointer = int *;
878+
using reference = const int &;
879+
using difference_type = int;
880+
881+
MutableRACIterator(int value) : value(value) {}
882+
MutableRACIterator(const MutableRACIterator &other) = default;
883+
884+
const int &operator*() const { return value; }
885+
int &operator*() { return value; }
886+
887+
MutableRACIterator &operator++() {
888+
value++;
889+
return *this;
890+
}
891+
MutableRACIterator operator++(int) {
892+
auto tmp = MutableRACIterator(value);
893+
value++;
894+
return tmp;
895+
}
896+
897+
void operator+=(difference_type v) { value += v; }
898+
void operator-=(difference_type v) { value -= v; }
899+
MutableRACIterator operator+(difference_type v) const {
900+
return MutableRACIterator(value + v);
901+
}
902+
MutableRACIterator operator-(difference_type v) const {
903+
return MutableRACIterator(value - v);
904+
}
905+
friend MutableRACIterator operator+(difference_type v,
906+
const MutableRACIterator &it) {
907+
return it + v;
908+
}
909+
int operator-(const MutableRACIterator &other) const {
910+
return value - other.value;
911+
}
912+
913+
bool operator<(const MutableRACIterator &other) const {
914+
return value < other.value;
915+
}
916+
917+
bool operator==(const MutableRACIterator &other) const {
918+
return value == other.value;
919+
}
920+
bool operator!=(const MutableRACIterator &other) const {
921+
return value != other.value;
922+
}
923+
};
924+
869925
#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_CUSTOM_ITERATOR_H

test/Interop/Cxx/stdlib/overlay/custom-iterator-module-interface.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,15 @@
126126
// CHECK: struct InheritedTemplatedConstRACIteratorOutOfLineOps<Int32> : UnsafeCxxRandomAccessIterator, UnsafeCxxInputIterator {
127127
// CHECK: }
128128

129-
// CHECK: struct InputOutputIterator : UnsafeCxxInputIterator {
129+
// CHECK: struct InputOutputIterator : UnsafeCxxMutableInputIterator {
130130
// CHECK: func successor() -> InputOutputIterator
131131
// CHECK: var pointee: Int32
132+
// CHECK: typealias Pointee = Int32
133+
// CHECK: }
134+
135+
// CHECK: struct MutableRACIterator : UnsafeCxxRandomAccessIterator, UnsafeCxxMutableInputIterator {
136+
// CHECK: func successor() -> MutableRACIterator
137+
// CHECK: var pointee: Int32
138+
// CHECK: typealias Pointee = Int32
139+
// CHECK: typealias Distance = Int32
132140
// CHECK: }

0 commit comments

Comments
 (0)