Skip to content

Commit bd696f9

Browse files
committed
Enable failable initializers for noncopyable types
Noncopyable types were prevented from having failable initializers because `Optional` itself didn't support noncopyable types. Now `Optional` does, so lift this restriction and add a test.
1 parent b19a325 commit bd696f9

File tree

5 files changed

+37
-20
lines changed

5 files changed

+37
-20
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7743,8 +7743,6 @@ ERROR(noncopyable_enums_do_not_support_indirect,none,
77437743
"noncopyable enum %0 cannot be marked indirect or have indirect cases yet", (Identifier))
77447744
ERROR(noncopyable_cast,none,
77457745
"noncopyable types cannot be conditionally cast", ())
7746-
ERROR(noncopyable_failable_init,none,
7747-
"noncopyable types cannot have failable initializers yet", ())
77487746
ERROR(noncopyable_objc_enum, none,
77497747
"noncopyable enums cannot be marked '@objc'", ())
77507748
ERROR(moveOnly_not_allowed_here,none,

lib/Sema/TypeCheckDeclPrimary.cpp

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

4038-
// a move-only / noncopyable type cannot have a failable initializer, since
4039-
// that would require the ability to wrap one inside an optional
4040-
if (CD->isFailable()) {
4041-
if (auto *nom = CD->getDeclContext()->getSelfNominalTypeDecl()) {
4042-
if (!nom->canBeCopyable()) {
4043-
CD->diagnose(diag::noncopyable_failable_init);
4044-
}
4045-
}
4046-
}
4047-
40484038
checkDefaultArguments(CD->getParameters());
40494039
checkVariadicParameters(CD->getParameters(), CD);
40504040

test/Generics/inverse_generics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ struct NeverCopyableDeinit<T: ~Copyable>: ~Copyable {
109109
}
110110

111111
protocol Test: ~Copyable {
112-
init?() // expected-error {{noncopyable types cannot have failable initializers yet}}
112+
init?()
113113
}
114114

115115
struct NoncopyableAndSendable: ~Copyable, Sendable {}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %target-swift-emit-sil -module-name test %s | %FileCheck %s --enable-var-scope
2+
3+
struct MoveWithDeinit: ~Copyable {
4+
deinit { }
5+
}
6+
7+
struct MyType: ~Copyable {
8+
var handle: MoveWithDeinit
9+
10+
// CHECK-LABEL: sil hidden @$s4test6MyTypeV6handleACSgAA14MoveWithDeinitVSg_tcfC : $@convention(method) (@owned Optional<MoveWithDeinit>, @thin MyType.Type) -> @owned Optional<MyType>
11+
// CHECK: bb0(%0 : $Optional<MoveWithDeinit>, %1 : $@thin MyType.Type):
12+
init?(handle: consuming MoveWithDeinit?) {
13+
// CHECK: switch_enum [[SUBJECT:%.*]] : $Optional<MoveWithDeinit>, case #Optional.some!enumelt: bb2, case #Optional.none!enumelt: bb1
14+
guard let handle = consume handle else {
15+
// CHECK: bb1:
16+
// CHECK: [[NONE:%.*]] = enum $Optional<MyType>, #Optional.none!enumelt
17+
// CHECK: br bb3([[NONE]] : $Optional<MyType>)
18+
return nil
19+
}
20+
21+
// CHECK: bb2([[WRAPPED:%.*]] : $MoveWithDeinit):
22+
// CHECK: br bb3
23+
self.handle = handle
24+
}
25+
}
26+
27+
func test() -> MyType? {
28+
return MyType(handle: MoveWithDeinit())
29+
}

test/Sema/moveonly_restrictions.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ class CopyableKlass {}
66

77
@_moveOnly
88
class MoveOnlyKlass { // expected-note 6{{class 'MoveOnlyKlass' has '~Copyable' constraint preventing 'Copyable' conformance}}
9-
init?() {} // expected-error {{noncopyable types cannot have failable initializers yet}}
9+
init?() {}
1010
}
1111

1212
@_moveOnly
1313
struct MoveOnlyStruct { // expected-note {{struct 'MoveOnlyStruct' has '~Copyable' constraint preventing 'Copyable' conformance}}
14-
init?(one: Bool) {} // expected-error {{noncopyable types cannot have failable initializers yet}}
15-
init!(two: Bool) {} // expected-error {{noncopyable types cannot have failable initializers yet}}
14+
init?(one: Bool) {}
15+
init!(two: Bool) {}
1616
}
1717

1818
class C {
@@ -78,19 +78,19 @@ enum EMoveOnly {
7878
case lhs(CopyableKlass)
7979
case rhs(MoveOnlyKlass)
8080

81-
init?() {} // expected-error {{noncopyable types cannot have failable initializers yet}}
81+
init?() {}
8282
}
8383

8484
extension EMoveOnly {
85-
init!(three: Bool) {} // expected-error {{noncopyable types cannot have failable initializers yet}}
85+
init!(three: Bool) {}
8686
}
8787

8888
extension MoveOnlyKlass {
89-
convenience init?(three: Bool) {} // expected-error {{noncopyable types cannot have failable initializers yet}}
89+
convenience init?(three: Bool) {}
9090
}
9191

9292
extension MoveOnlyStruct {
93-
init?(three: Bool) {} // expected-error {{noncopyable types cannot have failable initializers yet}}
93+
init?(three: Bool) {}
9494
}
9595

9696
func foo() {

0 commit comments

Comments
 (0)