Skip to content

Commit 78eee32

Browse files
committed
[cxx-interop] Import NonCopyable* as OpaquePointer if noncopyable generics are disabled
C++ pointer type `T*` is generally imported as `Unsafe(Mutable)Pointer<T>`. However, if `T` is non-copyable in Swift (e.g. it has a deleted C++ copy constructor), using `UnsafePointer<T>` type requires noncopyable generics to be enabled. This was causing assertion failures when building SwiftCompilerSources in #72912.
1 parent a263bca commit 78eee32

File tree

3 files changed

+31
-0
lines changed

3 files changed

+31
-0
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,26 @@ namespace {
509509
return importFunctionPointerLikeType(*type, pointeeType);
510510
}
511511

512+
// If non-copyable generics are disabled, we cannot specify
513+
// UnsafePointer<T> with a non-copyable type T.
514+
// We cannot use `ty->isNoncopyable()` here because that would create a
515+
// cyclic dependency between ModuleQualifiedLookupRequest and
516+
// LookupConformanceInModuleRequest, so we check for the presence of
517+
// move-only attribute that is implicitly added to non-copyable C++ types
518+
// by ClangImporter.
519+
if (pointeeType && pointeeType->getAnyNominal() &&
520+
pointeeType->getAnyNominal()
521+
->getAttrs()
522+
.hasAttribute<MoveOnlyAttr>() &&
523+
!Impl.SwiftContext.LangOpts.hasFeature(
524+
Feature::NoncopyableGenerics)) {
525+
auto opaquePointerDecl = Impl.SwiftContext.getOpaquePointerDecl();
526+
if (!opaquePointerDecl)
527+
return Type();
528+
return {opaquePointerDecl->getDeclaredInterfaceType(),
529+
ImportHint::OtherPointer};
530+
}
531+
512532
PointerTypeKind pointerKind;
513533
if (quals.hasConst()) {
514534
pointerKind = PTK_UnsafePointer;

test/Interop/Cxx/class/move-only/Inputs/move-only-cxx-value-type.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,7 @@ struct NonCopyableHolderDerivedDerived: NonCopyableHolderDerived {
5353
}
5454
};
5555

56+
inline NonCopyable *getNonCopyablePtr() { return nullptr; }
57+
inline NonCopyableDerived *getNonCopyableDerivedPtr() { return nullptr; }
58+
5659
#endif // TEST_INTEROP_CXX_CLASS_MOVE_ONLY_VT_H
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-swift-ide-test -print-module -module-to-print=MoveOnlyCxxValueType -I %S/Inputs -cxx-interoperability-mode=upcoming-swift -source-filename=x | %FileCheck %s --check-prefix=CHECK-NO-NCG
2+
// RUN: %target-swift-ide-test -print-module -module-to-print=MoveOnlyCxxValueType -I %S/Inputs -cxx-interoperability-mode=upcoming-swift -source-filename=x -enable-experimental-feature NoncopyableGenerics | %FileCheck %s --check-prefix=CHECK-NCG
3+
4+
// CHECK-NO-NCG: func getNonCopyablePtr() -> OpaquePointer
5+
// CHECK-NO-NCG: func getNonCopyableDerivedPtr() -> OpaquePointer
6+
7+
// CHECK-NCG: func getNonCopyablePtr() -> UnsafeMutablePointer<NonCopyable>
8+
// CHECK-NCG: func getNonCopyableDerivedPtr() -> UnsafeMutablePointer<NonCopyableDerived>

0 commit comments

Comments
 (0)