Skip to content

Commit 70c3e43

Browse files
authored
Merge pull request #73055 from apple/egorzhdan/ncg-unsafepointer
[cxx-interop] Import `NonCopyable*` as `OpaquePointer` if noncopyable generics are disabled
2 parents 0dd20fd + 6140ba1 commit 70c3e43

File tree

8 files changed

+61
-6
lines changed

8 files changed

+61
-6
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5728,6 +5728,8 @@ DeclAttributes cloneImportedAttributes(ValueDecl *decl, ASTContext &context) {
57285728

57295729
static ValueDecl *
57305730
cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
5731+
ASTContext &context = decl->getASTContext();
5732+
57315733
if (auto fn = dyn_cast<FuncDecl>(decl)) {
57325734
// TODO: function templates are specialized during type checking so to
57335735
// support these we need to tell Swift to type check the synthesized bodies.
@@ -5745,7 +5747,6 @@ cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
57455747
return nullptr;
57465748
}
57475749

5748-
ASTContext &context = decl->getASTContext();
57495750
auto out = FuncDecl::createImplicit(
57505751
context, fn->getStaticSpelling(), fn->getName(),
57515752
fn->getNameLoc(), fn->hasAsync(), fn->hasThrows(),
@@ -5781,6 +5782,20 @@ cloneBaseMemberDecl(ValueDecl *decl, DeclContext *newContext) {
57815782
}
57825783

57835784
if (auto var = dyn_cast<VarDecl>(decl)) {
5785+
auto oldContext = var->getDeclContext();
5786+
auto oldTypeDecl = oldContext->getSelfNominalTypeDecl();
5787+
// If the base type is non-copyable, and non-copyable generics are disabled,
5788+
// we cannot synthesize the accessor, because its implementation would use
5789+
// `UnsafePointer<BaseTy>`.
5790+
// We cannot use `ty->isNoncopyable()` here because that would create a
5791+
// cyclic dependency between ModuleQualifiedLookupRequest and
5792+
// LookupConformanceInModuleRequest, so we check for the presence of
5793+
// move-only attribute that is implicitly added to non-copyable C++ types by
5794+
// ClangImporter.
5795+
if (oldTypeDecl->getAttrs().hasAttribute<MoveOnlyAttr>() &&
5796+
!context.LangOpts.hasFeature(Feature::NoncopyableGenerics))
5797+
return nullptr;
5798+
57845799
auto rawMemory = allocateMemoryForDecl<VarDecl>(var->getASTContext(),
57855800
sizeof(VarDecl), false);
57865801
auto out =

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

test/Interop/Cxx/class/move-only/inherited-field-access-irgen.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %target-swift-emit-irgen -I %S/Inputs -cxx-interoperability-mode=swift-6 %s -validate-tbd-against-ir=none -Xcc -fignore-exceptions | %FileCheck %s
2-
// RUN: %target-swift-emit-irgen -I %S/Inputs -cxx-interoperability-mode=upcoming-swift %s -validate-tbd-against-ir=none -Xcc -fignore-exceptions | %FileCheck %s
1+
// RUN: %target-swift-emit-irgen -I %S/Inputs -cxx-interoperability-mode=swift-6 -enable-experimental-feature NoncopyableGenerics %s -validate-tbd-against-ir=none -Xcc -fignore-exceptions | %FileCheck %s
2+
// RUN: %target-swift-emit-irgen -I %S/Inputs -cxx-interoperability-mode=upcoming-swift -enable-experimental-feature NoncopyableGenerics %s -validate-tbd-against-ir=none -Xcc -fignore-exceptions | %FileCheck %s
33

44
import MoveOnlyCxxValueType
55

test/Interop/Cxx/class/move-only/inherited-field-access-silgen.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %target-swift-emit-sil -I %S/Inputs -cxx-interoperability-mode=swift-6 %s -validate-tbd-against-ir=none | %FileCheck %s
2-
// RUN: %target-swift-emit-sil -I %S/Inputs -cxx-interoperability-mode=upcoming-swift %s -validate-tbd-against-ir=none | %FileCheck %s
1+
// RUN: %target-swift-emit-sil -I %S/Inputs -cxx-interoperability-mode=swift-6 -enable-experimental-feature NoncopyableGenerics %s -validate-tbd-against-ir=none | %FileCheck %s
2+
// RUN: %target-swift-emit-sil -I %S/Inputs -cxx-interoperability-mode=upcoming-swift -enable-experimental-feature NoncopyableGenerics %s -validate-tbd-against-ir=none | %FileCheck %s
33

44
import MoveOnlyCxxValueType
55

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>

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=upcoming-swift)
2+
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=upcoming-swift -enable-experimental-feature NoncopyableGenerics -D HAS_NONCOPYABLE_GENERICS)
23
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=swift-6 -O)
4+
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=swift-6 -O -enable-experimental-feature NoncopyableGenerics -D HAS_NONCOPYABLE_GENERICS)
35

4-
//
56
// REQUIRES: executable_test
67

78
import MoveOnlyCxxValueType
@@ -27,10 +28,12 @@ MoveOnlyCxxValueType.test("Test derived move only type member access") {
2728
var k = c.method(-3)
2829
expectEqual(k, -6)
2930
expectEqual(c.method(1), 2)
31+
#if HAS_NONCOPYABLE_GENERICS
3032
k = c.x
3133
expectEqual(k, 2)
3234
c.x = 11
3335
expectEqual(c.x, 11)
36+
#endif
3437
k = c.mutMethod(-13)
3538
expectEqual(k, -13)
3639
}
@@ -56,6 +59,7 @@ MoveOnlyCxxValueType.test("Test move only field access in holder") {
5659
expectEqual(c.x.x, 5)
5760
}
5861

62+
#if HAS_NONCOPYABLE_GENERICS
5963
MoveOnlyCxxValueType.test("Test move only field access in derived holder") {
6064
var c = NonCopyableHolderDerivedDerived(-11)
6165
var k = borrowNC(c.x)
@@ -69,5 +73,6 @@ MoveOnlyCxxValueType.test("Test move only field access in derived holder") {
6973
c.x.mutMethod(5)
7074
expectEqual(c.x.x, 5)
7175
}
76+
#endif
7277

7378
runAllTests()

test/Interop/Cxx/operators/move-only/move-only-synthesized-properties.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=swift-6)
22
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=upcoming-swift)
3+
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=upcoming-swift -enable-experimental-feature NoncopyableGenerics -D HAS_NONCOPYABLE_GENERICS)
34
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=swift-6 -O)
45
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=upcoming-swift -O)
6+
// RUN: %target-run-simple-swift(-I %S/Inputs/ -cxx-interoperability-mode=upcoming-swift -O -enable-experimental-feature NoncopyableGenerics -D HAS_NONCOPYABLE_GENERICS)
57
//
68
// REQUIRES: executable_test
79

@@ -88,6 +90,7 @@ MoveOnlyCxxOperators.test("testNonCopyableHolderValueMutDeref pointee value") {
8890
expectEqual(k.x, k2.x)
8991
}
9092

93+
#if HAS_NONCOPYABLE_GENERICS
9194
MoveOnlyCxxOperators.test("NonCopyableHolderConstDerefDerivedDerived pointee borrow") {
9295
let holder = NonCopyableHolderConstDerefDerivedDerived(11)
9396
var k = borrowNC(holder.pointee)
@@ -155,5 +158,6 @@ MoveOnlyCxxOperators.test("testNonCopyableHolderValueMutDerefDerivedDerived poin
155158
var k2 = holder.pointee
156159
expectEqual(k.x, k2.x)
157160
}
161+
#endif
158162

159163
runAllTests()

0 commit comments

Comments
 (0)