Skip to content

Commit 1a1afeb

Browse files
authored
Merge pull request #61909 from apple/egorzhdan/cxx-synthesize-rac
[cxx-interop] Synthesize conformances to `CxxRandomAccessCollection`
2 parents 6f78e21 + 3cf8421 commit 1a1afeb

File tree

8 files changed

+70
-21
lines changed

8 files changed

+70
-21
lines changed

include/swift/AST/KnownProtocols.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ PROTOCOL(DistributedTargetInvocationDecoder)
105105
PROTOCOL(DistributedTargetInvocationResultHandler)
106106

107107
// C++ Standard Library Overlay:
108+
PROTOCOL(CxxRandomAccessCollection)
108109
PROTOCOL(CxxSequence)
109110
PROTOCOL(UnsafeCxxInputIterator)
110111
PROTOCOL(UnsafeCxxRandomAccessIterator)

include/swift/AST/KnownStdlibTypes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ KNOWN_STDLIB_TYPE_DECL(ArraySlice, NominalTypeDecl, 1)
5353
KNOWN_STDLIB_TYPE_DECL(_ContiguousArrayStorage, ClassDecl, 1)
5454
KNOWN_STDLIB_TYPE_DECL(Set, NominalTypeDecl, 1)
5555
KNOWN_STDLIB_TYPE_DECL(Sequence, NominalTypeDecl, 1)
56+
KNOWN_STDLIB_TYPE_DECL(Slice, NominalTypeDecl, 1)
57+
KNOWN_STDLIB_TYPE_DECL(Range, NominalTypeDecl, 1)
5658
KNOWN_STDLIB_TYPE_DECL(Dictionary, NominalTypeDecl, 2)
5759
KNOWN_STDLIB_TYPE_DECL(CollectionDifference, NominalTypeDecl, 1)
5860
KNOWN_STDLIB_TYPE_DECL(AnyHashable, NominalTypeDecl, 0)

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,7 @@ ProtocolDecl *ASTContext::getProtocol(KnownProtocolKind kind) const {
11191119
case KnownProtocolKind::DistributedTargetInvocationResultHandler:
11201120
M = getLoadedModule(Id_Distributed);
11211121
break;
1122+
case KnownProtocolKind::CxxRandomAccessCollection:
11221123
case KnownProtocolKind::CxxSequence:
11231124
case KnownProtocolKind::UnsafeCxxInputIterator:
11241125
case KnownProtocolKind::UnsafeCxxRandomAccessIterator:

lib/ClangImporter/ClangDerivedConformances.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,4 +382,50 @@ void swift::conformToCxxSequenceIfNeeded(
382382
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("RawIterator"),
383383
rawIteratorTy);
384384
impl.addSynthesizedProtocolAttrs(decl, {KnownProtocolKind::CxxSequence});
385+
386+
// Try to conform to CxxRandomAccessCollection if possible.
387+
388+
auto cxxRAIteratorProto =
389+
ctx.getProtocol(KnownProtocolKind::UnsafeCxxRandomAccessIterator);
390+
if (!cxxRAIteratorProto ||
391+
!ctx.getProtocol(KnownProtocolKind::CxxRandomAccessCollection))
392+
return;
393+
394+
// Check if `begin()` and `end()` are non-mutating.
395+
if (begin->isMutating() || end->isMutating())
396+
return;
397+
398+
// Check if RawIterator conforms to UnsafeCxxRandomAccessIterator.
399+
auto rawIteratorRAConformanceRef =
400+
decl->getModuleContext()->lookupConformance(rawIteratorTy,
401+
cxxRAIteratorProto);
402+
if (!isConcreteAndValid(rawIteratorRAConformanceRef, module))
403+
return;
404+
405+
// CxxRandomAccessCollection always uses Int as an Index.
406+
auto indexTy = ctx.getIntType();
407+
408+
auto sliceTy = ctx.getSliceType();
409+
sliceTy = sliceTy.subst(
410+
[&](SubstitutableType *dependentType) {
411+
if (dependentType->isEqual(cxxSequenceSelfTy))
412+
return declSelfTy;
413+
return Type(dependentType);
414+
},
415+
LookUpConformanceInModule(module));
416+
417+
auto indicesTy = ctx.getRangeType();
418+
indicesTy = indicesTy.subst(
419+
[&](SubstitutableType *dependentType) {
420+
if (dependentType->isEqual(cxxSequenceSelfTy))
421+
return indexTy;
422+
return Type(dependentType);
423+
},
424+
LookUpConformanceInModule(module));
425+
426+
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("Index"), indexTy);
427+
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("Indices"), indicesTy);
428+
impl.addSynthesizedTypealias(decl, ctx.getIdentifier("SubSequence"), sliceTy);
429+
impl.addSynthesizedProtocolAttrs(
430+
decl, {KnownProtocolKind::CxxRandomAccessCollection});
385431
}

lib/IRGen/GenMeta.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5884,6 +5884,7 @@ SpecialProtocol irgen::getSpecialProtocolID(ProtocolDecl *P) {
58845884
case KnownProtocolKind::DistributedTargetInvocationEncoder:
58855885
case KnownProtocolKind::DistributedTargetInvocationDecoder:
58865886
case KnownProtocolKind::DistributedTargetInvocationResultHandler:
5887+
case KnownProtocolKind::CxxRandomAccessCollection:
58875888
case KnownProtocolKind::CxxSequence:
58885889
case KnownProtocolKind::UnsafeCxxInputIterator:
58895890
case KnownProtocolKind::UnsafeCxxRandomAccessIterator:
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-swift-ide-test -print-module -module-to-print=CustomSequence -source-filename=x -I %S/Inputs -enable-experimental-cxx-interop -module-cache-path %t | %FileCheck %s
2+
3+
// CHECK: struct SimpleArrayWrapper : CxxRandomAccessCollection, CxxSequence {
4+
// CHECK: typealias Element = UnsafePointer<Int32>.Pointee
5+
// CHECK: typealias Iterator = CxxIterator<SimpleArrayWrapper>
6+
// CHECK: typealias RawIterator = UnsafePointer<Int32>
7+
// CHECK: }
8+
9+
// CHECK: struct SimpleCollectionNoSubscript : CxxRandomAccessCollection, CxxSequence {
10+
// CHECK: typealias Element = ConstRACIterator.Pointee
11+
// CHECK: typealias Iterator = CxxIterator<SimpleCollectionNoSubscript>
12+
// CHECK: typealias RawIterator = SimpleCollectionNoSubscript.iterator
13+
// CHECK: }
14+
15+
// CHECK: struct SimpleCollectionReadOnly : CxxRandomAccessCollection, CxxSequence {
16+
// CHECK: typealias Element = ConstRACIteratorRefPlusEq.Pointee
17+
// CHECK: typealias Iterator = CxxIterator<SimpleCollectionReadOnly>
18+
// CHECK: typealias RawIterator = SimpleCollectionReadOnly.iterator
19+
// CHECK: }

test/Interop/Cxx/stdlib/overlay/custom-collection.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,18 @@ import Cxx
99

1010
var CxxCollectionTestSuite = TestSuite("CxxCollection")
1111

12-
// === SimpleCollectionNoSubscript ===
13-
14-
extension SimpleCollectionNoSubscript : CxxRandomAccessCollection {
15-
}
16-
1712
CxxCollectionTestSuite.test("SimpleCollectionNoSubscript as Swift.Collection") {
1813
let c = SimpleCollectionNoSubscript()
1914
expectEqual(c.first, 1)
2015
expectEqual(c.last, 5)
2116
}
2217

23-
// === SimpleCollectionReadOnly ===
24-
25-
extension SimpleCollectionReadOnly : CxxRandomAccessCollection {
26-
}
27-
2818
CxxCollectionTestSuite.test("SimpleCollectionReadOnly as Swift.Collection") {
2919
let c = SimpleCollectionReadOnly()
3020
expectEqual(c.first, 1)
3121
expectEqual(c.last, 5)
3222
}
3323

34-
// === SimpleArrayWrapper ===
35-
36-
extension SimpleArrayWrapper : CxxRandomAccessCollection {
37-
}
38-
3924
CxxCollectionTestSuite.test("SimpleArrayWrapper as Swift.Collection") {
4025
let c = SimpleArrayWrapper()
4126
expectEqual(c.first, 10)

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,6 @@
1212
// CHECK: typealias RawIterator = ConstIteratorOutOfLineEq
1313
// CHECK: }
1414

15-
// CHECK: struct SimpleArrayWrapper : CxxSequence {
16-
// CHECK: typealias Element = UnsafePointer<Int32>.Pointee
17-
// CHECK: typealias Iterator = CxxIterator<SimpleArrayWrapper>
18-
// CHECK: typealias RawIterator = UnsafePointer<Int32>
19-
// CHECK: }
20-
2115
// CHECK: struct SimpleArrayWrapperNullableIterators : CxxSequence {
2216
// CHECK: typealias Element = Optional<UnsafePointer<Int32>>.Pointee
2317
// CHECK: typealias Iterator = CxxIterator<SimpleArrayWrapperNullableIterators>

0 commit comments

Comments
 (0)