Skip to content

Commit 94b4fb2

Browse files
authored
Merge pull request #72779 from DougGregor/failability-init-of-noncopyable-6.0
2 parents 34a8bf4 + 898491a commit 94b4fb2

File tree

9 files changed

+193
-75
lines changed

9 files changed

+193
-75
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7731,8 +7731,6 @@ ERROR(noncopyable_enums_do_not_support_indirect,none,
77317731
"noncopyable enum %0 cannot be marked indirect or have indirect cases yet", (Identifier))
77327732
ERROR(noncopyable_cast,none,
77337733
"noncopyable types cannot be conditionally cast", ())
7734-
ERROR(noncopyable_failable_init,none,
7735-
"noncopyable types cannot have failable initializers yet", ())
77367734
ERROR(noncopyable_objc_enum, none,
77377735
"noncopyable enums cannot be marked '@objc'", ())
77387736
ERROR(moveOnly_not_allowed_here,none,

lib/IRGen/GenEnum.cpp

Lines changed: 97 additions & 51 deletions
Large diffs are not rendered by default.

lib/IRGen/GenEnum.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,17 @@ class EnumImplStrategy {
153153
TypeInfoKind TIK;
154154
IsFixedSize_t AlwaysFixedSize;
155155
IsABIAccessible_t ElementsAreABIAccessible;
156+
IsTriviallyDestroyable_t TriviallyDestroyable;
157+
IsCopyable_t Copyable;
158+
IsBitwiseTakable_t BitwiseTakable;
156159
unsigned NumElements;
157160

158161
EnumImplStrategy(IRGenModule &IGM,
159162
TypeInfoKind tik,
160163
IsFixedSize_t alwaysFixedSize,
164+
IsTriviallyDestroyable_t triviallyDestroyable,
165+
IsCopyable_t copyable,
166+
IsBitwiseTakable_t bitwiseTakable,
161167
unsigned NumElements,
162168
std::vector<Element> &&ElementsWithPayload,
163169
std::vector<Element> &&ElementsWithNoPayload);

lib/IRGen/StructLayout.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,10 +178,10 @@ StructLayout::StructLayout(IRGenModule &IGM, std::optional<CanType> type,
178178
SpareBits.clear();
179179
IsFixedLayout = true;
180180
IsLoadable = true;
181-
IsKnownTriviallyDestroyable = deinit;
182-
IsKnownBitwiseTakable = IsBitwiseTakable;
183-
IsKnownAlwaysFixedSize = IsFixedSize;
184-
IsKnownCopyable = copyable;
181+
IsKnownTriviallyDestroyable = deinit & builder.isTriviallyDestroyable();
182+
IsKnownBitwiseTakable = builder.isBitwiseTakable();
183+
IsKnownAlwaysFixedSize = builder.isAlwaysFixedSize();
184+
IsKnownCopyable = copyable & builder.isCopyable();
185185
Ty = (typeToFill ? typeToFill : IGM.OpaqueTy);
186186
} else {
187187
MinimumAlign = builder.getAlignment();

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 {}

test/IRGen/moveonly_deinits.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,3 +373,52 @@ public func testKlassEnumPairWithDeinit() {
373373
consumeKlassEnumPairWithDeinit(f)
374374
}
375375
}
376+
377+
struct EmptyMoveOnlyWithDeinit: ~Copyable {
378+
deinit {}
379+
}
380+
381+
struct EnclosesEmptyMoveOnlyWithDeinit: ~Copyable {
382+
var stored: EmptyMoveOnlyWithDeinit
383+
}
384+
385+
// IR-LABEL: define {{.*}}swiftcc void @"$s16moveonly_deinits35testEnclosesEmptyMoveOnlyWithDeinityyF"()
386+
func testEnclosesEmptyMoveOnlyWithDeinit() {
387+
// CHECK-NOT: ret
388+
// CHECK: call swiftcc void @"$s16moveonly_deinits23EmptyMoveOnlyWithDeinitVfD"()
389+
_ = EnclosesEmptyMoveOnlyWithDeinit(stored: EmptyMoveOnlyWithDeinit())
390+
}
391+
392+
enum ESingle: ~Copyable {
393+
case a(EmptyMoveOnlyWithDeinit)
394+
}
395+
396+
struct OtherEmptyMoveOnlyWithDeinit: ~Copyable {
397+
deinit {}
398+
}
399+
400+
enum EMulti: ~Copyable {
401+
case a(EmptyMoveOnlyWithDeinit)
402+
case b(OtherEmptyMoveOnlyWithDeinit)
403+
}
404+
405+
406+
// IR-LABEL: define {{.*}} swiftcc void @"$s16moveonly_deinits14testSingleEnumyyF"()
407+
func testSingleEnum() {
408+
// IR: call swiftcc void @"$s16moveonly_deinits23EmptyMoveOnlyWithDeinitVfD"()
409+
_ = ESingle.a(EmptyMoveOnlyWithDeinit())
410+
}
411+
412+
413+
// IR-LABEL: define {{.*}}swiftcc void @"$s16moveonly_deinits13testMultiEnumyyF"()
414+
func testMultiEnum() {
415+
// IR: call void @"$s16moveonly_deinits6EMultiOWOe"(i1 true)
416+
_ = EMulti.b(OtherEmptyMoveOnlyWithDeinit())
417+
}
418+
419+
// IR-LABEL: define {{.*}}void @"$s16moveonly_deinits6EMultiOWOe"
420+
// IR: br i1
421+
// IR: 1:
422+
// IR: call swiftcc void @"$s16moveonly_deinits23EmptyMoveOnlyWithDeinitVfD"()
423+
// IR: 2:
424+
// IR: call swiftcc void @"$s16moveonly_deinits28OtherEmptyMoveOnlyWithDeinitVfD"()
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)