Skip to content

Commit c53b814

Browse files
committed
[cxx-interop] Correctly check iterator conformances
To determine whether to conform a C++ type to `CxxSequence` protocol automatically, ClangImporter checks if the corresponding iterator type conforms to `UnsafeCxxInputIterator`. This logic had false-positives, e.g. `Optional<OpaquePointer>` was treated as if it conforms to `UnsafeCxxInputIterator` while it actually doesn't. This happened because `lookupConformance` returned a conformance with a conditional requirement (`Wrapped : UnsafeCxxInputIterator`) that is not satisfied for `OpaquePointer`. rdar://100265664
1 parent e51f1ff commit c53b814

File tree

4 files changed

+21
-2
lines changed

4 files changed

+21
-2
lines changed

lib/ClangImporter/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ add_swift_host_library(swiftClangImporter STATIC
2828
target_link_libraries(swiftClangImporter PRIVATE
2929
swiftAST
3030
swiftParse
31+
swiftSema
3132
clangTooling
3233
LLVMBitstreamReader)
3334

lib/ClangImporter/ClangDerivedConformances.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,9 @@ void swift::conformToCxxSequenceIfNeeded(
228228
return;
229229

230230
// Check if RawIterator conforms to UnsafeCxxInputIterator.
231-
auto rawIteratorConformanceRef = decl->getModuleContext()->lookupConformance(
231+
auto rawIteratorConformanceRef = decl->getModuleContext()->conformsToProtocol(
232232
rawIteratorTy, cxxIteratorProto);
233-
if (!rawIteratorConformanceRef.isConcrete())
233+
if (!rawIteratorConformanceRef || !rawIteratorConformanceRef.isConcrete())
234234
return;
235235
auto rawIteratorConformance = rawIteratorConformanceRef.getConcrete();
236236
auto pointeeDecl =

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,16 @@ struct HasBeginEndReturnRef {
8686
const ConstIterator &end() const { return e; }
8787
};
8888

89+
template <typename A> struct NoDefinition;
90+
91+
template <typename A, typename NoDef = NoDefinition<A>>
92+
struct HasTemplatedIterator {
93+
typedef NoDef* iterator; // OpaquePointer
94+
95+
iterator begin() const;
96+
iterator end() const;
97+
};
98+
99+
typedef HasTemplatedIterator<int> HasUninstantiatableIterator;
100+
89101
#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_CUSTOM_SEQUENCE_H

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,9 @@
5858
// CHECK-NOT: typealias Iterator
5959
// CHECK-NOT: typealias RawIterator
6060
// CHECK: }
61+
// CHECK: struct __CxxTemplateInst20HasTemplatedIteratorIi12NoDefinitionIiEE {
62+
// CHECK-NOT: typealias Element
63+
// CHECK-NOT: typealias Iterator
64+
// CHECK-NOT: typealias RawIterator
65+
// CHECK: }
66+
// CHECK: typealias HasUninstantiatableIterator = __CxxTemplateInst20HasTemplatedIteratorIi12NoDefinitionIiEE

0 commit comments

Comments
 (0)