Skip to content

Commit 312ac1b

Browse files
committed
NCGenerics: handle MoveOnlyClasses correctly
1 parent a816489 commit 312ac1b

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

lib/Sema/TypeCheckInvertible.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,13 @@ ProtocolConformance *deriveConformanceForInvertible(Evaluator &evaluator,
441441
};
442442

443443
switch (*ip) {
444-
case InvertibleProtocolKind::Escapable:
445444
case InvertibleProtocolKind::Copyable:
445+
// If move-only classes is enabled, we'll check the markings.
446+
if (ctx.LangOpts.hasFeature(Feature::MoveOnlyClasses))
447+
break;
448+
449+
LLVM_FALLTHROUGH;
450+
case InvertibleProtocolKind::Escapable:
446451
// Always derive unconditional IP conformance for classes
447452
if (isa<ClassDecl>(nominal))
448453
return generateConformance(nominal);
@@ -462,8 +467,10 @@ ProtocolConformance *deriveConformanceForInvertible(Evaluator &evaluator,
462467
return nullptr; // No positive IP conformance will be inferred.
463468

464469
case InverseMarking::Kind::Inferred:
465-
return generateConditionalConformance();
470+
if (!isa<ClassDecl>(nominal))
471+
return generateConditionalConformance();
466472

473+
LLVM_FALLTHROUGH;
467474
case InverseMarking::Kind::None:
468475
// All types already start with conformances to the invertible protocols in
469476
// this case, within `NominalTypeDecl::prepareConformanceTable`.

test/Generics/inverse_classes1.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %target-typecheck-verify-swift \
2+
// RUN: -parse-stdlib -module-name Swift \
3+
// RUN: -enable-experimental-feature MoveOnlyClasses \
4+
// RUN: -enable-experimental-feature NoncopyableGenerics
5+
6+
// NOTE: -parse-stdlib is a transitional workaround and should not be required.
7+
8+
@_moveOnly
9+
class KlassLegacy {}
10+
11+
class KlassModern: ~Copyable {}
12+
13+
class Konditional<T: ~Copyable> {}
14+
15+
func checks<T: ~Copyable, C>(
16+
_ a: KlassLegacy, // expected-error {{parameter of noncopyable type 'KlassLegacy' must specify ownership}} // expected-note 3{{add}}
17+
_ b: KlassModern, // expected-error {{parameter of noncopyable type 'KlassModern' must specify ownership}} // expected-note 3{{add}}
18+
_ c: Konditional<T>,
19+
_ d: Konditional<C>) {}

test/Generics/inverse_classes2.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-typecheck-verify-swift \
2+
// RUN: -parse-stdlib -module-name Swift \
3+
// RUN: -enable-experimental-feature NoncopyableGenerics
4+
5+
// NOTE: -parse-stdlib is a transitional workaround and should not be required.
6+
7+
@_moveOnly // expected-error {{'@_moveOnly' attribute is only valid on structs or enums}}
8+
class KlassLegacy {}
9+
10+
class KlassModern: ~Copyable {} // expected-error {{classes cannot be '~Copyable'}}
11+
12+
class Konditional<T: ~Copyable> {}
13+
14+
func checks<T: ~Copyable, C>(
15+
_ a: KlassLegacy,
16+
_ b: KlassModern,
17+
_ c: Konditional<T>,
18+
_ d: Konditional<C>) {}

0 commit comments

Comments
 (0)