Skip to content

Commit 971ce81

Browse files
committed
disallow failable initializers for noncopyable types
These initializers implicitly return an optional of the nominal type, but we can't wrap move-only / noncopyable types inside of optionals at the moment, because that would permit copying. resolves rdar://106120881
1 parent 2d20644 commit 971ce81

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6748,6 +6748,8 @@ ERROR(moveonly_enums_do_not_support_indirect,none,
67486748
"move-only enum %0 cannot be marked indirect or have indirect cases yet", (Identifier))
67496749
ERROR(moveonly_cast,none,
67506750
"move-only types cannot be conditionally cast", ())
6751+
ERROR(moveonly_failable_init,none,
6752+
"move-only types cannot have failable initializers yet", ())
67516753

67526754
//------------------------------------------------------------------------------
67536755
// MARK: Type inference from default expressions

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3608,6 +3608,16 @@ class DeclChecker : public DeclVisitor<DeclChecker> {
36083608
addDelayedFunction(CD);
36093609
}
36103610

3611+
// a move-only / noncopyable type cannot have a failable initializer, since
3612+
// that would require the ability to wrap one inside an optional
3613+
if (CD->isFailable()) {
3614+
if (auto *nom = CD->getDeclContext()->getSelfNominalTypeDecl()) {
3615+
if (nom->isMoveOnly()) {
3616+
CD->diagnose(diag::moveonly_failable_init);
3617+
}
3618+
}
3619+
}
3620+
36113621
checkDefaultArguments(CD->getParameters());
36123622
checkVariadicParameters(CD->getParameters(), CD);
36133623
}

test/Sema/moveonly_restrictions.swift

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
// RUN: %target-typecheck-verify-swift -enable-experimental-move-only -enable-experimental-feature MoveOnlyClasses
22

33
class CopyableKlass {}
4+
45
@_moveOnly
5-
class MoveOnlyKlass {}
6+
class MoveOnlyKlass {
7+
init?() {} // expected-error {{move-only types cannot have failable initializers yet}}
8+
}
9+
610
@_moveOnly
7-
class MoveOnlyStruct {}
11+
class MoveOnlyStruct {
12+
init?(one: Bool) {} // expected-error {{move-only types cannot have failable initializers yet}}
13+
init!(two: Bool) {} // expected-error {{move-only types cannot have failable initializers yet}}
14+
}
815

916
class C {
1017
var copyable: CopyableKlass? = nil
@@ -57,6 +64,16 @@ enum E { // expected-error {{enum 'E' cannot contain a move-only type without al
5764
enum EMoveOnly {
5865
case lhs(CopyableKlass)
5966
case rhs(MoveOnlyKlass)
67+
68+
init?() {} // expected-error {{move-only types cannot have failable initializers yet}}
69+
}
70+
71+
extension EMoveOnly {
72+
init!(three: Bool) {} // expected-error {{move-only types cannot have failable initializers yet}}
73+
}
74+
75+
extension MoveOnlyStruct {
76+
convenience init?(three: Bool) {} // expected-error {{move-only types cannot have failable initializers yet}}
6077
}
6178

6279
func foo() {

0 commit comments

Comments
 (0)