Skip to content

Commit 0bc3812

Browse files
committed
[BitwiseCopyable] Ban indirect enums and cases.
Enums which are entirely indirect or which have indirect cases are never trivial and hence cannot conform to BitwiseCopyable.
1 parent d192a83 commit 0bc3812

File tree

3 files changed

+34
-0
lines changed

3 files changed

+34
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7609,6 +7609,12 @@ ERROR(escapable_requires_feature_flag,none,
76097609
())
76107610
ERROR(non_bitwise_copyable_type_class,none,
76117611
"class cannot conform to 'BitwiseCopyable'", ())
7612+
ERROR(non_bitwise_copyable_type_indirect_enum,none,
7613+
"indirect enum cannot conform to 'BitwiseCopyable'", ())
7614+
ERROR(non_bitwise_copyable_type_indirect_enum_element,none,
7615+
"enum with indirect case cannot conform to 'BitwiseCopyable'", ())
7616+
NOTE(note_non_bitwise_copyable_type_indirect_enum_element,none,
7617+
"indirect case is here", ())
76127618
ERROR(non_bitwise_copyable_type_noncopyable,none,
76137619
"noncopyable type cannot conform to 'BitwiseCopyable'", ())
76147620
ERROR(non_bitwise_copyable_type_nonescapable,none,

lib/Sema/TypeCheckBitwise.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,16 @@ bool BitwiseCopyableStorageVisitor::visitMemberDecl(ValueDecl *decl, Type ty) {
115115
storage = decl;
116116
SWIFT_DEFER { storage = nullptr; };
117117

118+
auto *element = dyn_cast<EnumElementDecl>(decl);
119+
if (element && element->isIndirect()) {
120+
if (!isImplicit(check)) {
121+
nominal->diagnose(diag::non_bitwise_copyable_type_indirect_enum_element);
122+
element->diagnose(diag::note_non_bitwise_copyable_type_indirect_enum_element);
123+
}
124+
invalid = true;
125+
return true;
126+
}
127+
118128
// Fields with unowned(unsafe) ownership are bitwise-copyable.
119129
auto *roa = decl->getAttrs().getAttribute<ReferenceOwnershipAttr>();
120130
if (roa && roa->get() == ReferenceOwnership::Unmanaged) {
@@ -244,6 +254,14 @@ static bool checkBitwiseCopyableInstanceStorage(NominalTypeDecl *nominal,
244254
return true;
245255
}
246256

257+
auto *ed = dyn_cast<EnumDecl>(nominal);
258+
if (ed && ed->isIndirect()) {
259+
if (!isImplicit(check)) {
260+
nominal->diagnose(diag::non_bitwise_copyable_type_indirect_enum);
261+
}
262+
return true;
263+
}
264+
247265
BitwiseCopyableStorageVisitor visitor(nominal, dc, check);
248266

249267
return visitor.visit(nominal, dc) || visitor.invalid;

test/Sema/bitwise_copyable_2.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,13 @@ struct S_Implicit_Noncopyable : ~Copyable {}
1515
struct S_Explicit_With_Any_BitwiseCopyable : _BitwiseCopyable {
1616
var a: any _BitwiseCopyable // expected-error {{non_bitwise_copyable_type_member}}
1717
}
18+
19+
struct S {}
20+
21+
indirect enum E_Explicit_Indirect : _BitwiseCopyable { // expected-error {{non_bitwise_copyable_type_indirect_enum}}
22+
case s(S)
23+
}
24+
25+
enum E_Explicit_Indirect_Case : _BitwiseCopyable { // expected-error {{non_bitwise_copyable_type_indirect_enum_element}}
26+
indirect case s(S) // expected-note {{note_non_bitwise_copyable_type_indirect_enum_element}}
27+
}

0 commit comments

Comments
 (0)