Skip to content

Commit 20b23d6

Browse files
committed
Diagnose borrow/mutate accessors in enums
We don't have support for borrowing switch on Copyable types. It is supported for ~Copyable types, but the return expression emission for borrow accessors is not yet implemented. Diagnose instead of crashing the compiler.
1 parent 6f7d420 commit 20b23d6

File tree

5 files changed

+37
-33
lines changed

5 files changed

+37
-33
lines changed

include/swift/AST/DiagnosticsCommon.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,8 @@ ERROR(lookup_outputs_dont_match,none,
280280
// MARK: Accessor diagnostics
281281
//------------------------------------------------------------------------------
282282

283-
ERROR(accessor_not_supported_in_decl,none,
284-
"%0 is supported only on a struct or enum", (StringRef))
283+
ERROR(borrow_mutate_accessor_not_supported_in_decl, none,
284+
"%0 is supported only on a struct", (StringRef))
285285

286286
//------------------------------------------------------------------------------
287287
// MARK: bridged diagnostics

lib/Parse/ParseDecl.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8131,9 +8131,8 @@ bool Parser::parseAccessorAfterIntroducer(
81318131
}
81328132

81338133
if (Kind == AccessorKind::Borrow || Kind == AccessorKind::Mutate) {
8134-
if (!Flags.contains(PD_InStruct) && !Flags.contains(PD_InEnum) &&
8135-
!Flags.contains(PD_InExtension)) {
8136-
diagnose(Tok, diag::accessor_not_supported_in_decl,
8134+
if (!Flags.contains(PD_InStruct) && !Flags.contains(PD_InExtension)) {
8135+
diagnose(Tok, diag::borrow_mutate_accessor_not_supported_in_decl,
81378136
getAccessorNameForDiagnostic(Kind, /*article*/ true,
81388137
/*underscored*/ false));
81398138
}

lib/Sema/TypeCheckStorage.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4324,16 +4324,22 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
43244324
if (borrow || mutate) {
43254325
if (auto *extDecl = dyn_cast<ExtensionDecl>(DC)) {
43264326
auto extNominal = extDecl->getExtendedNominal();
4327-
if (!isa<StructDecl>(extNominal) && !isa<EnumDecl>(extNominal)) {
4327+
if (!isa<StructDecl>(extNominal)) {
43284328
if (borrow) {
43294329
storage->getASTContext().Diags.diagnose(
4330-
borrow->getLoc(), diag::accessor_not_supported_in_decl,
4331-
"a borrow accessor");
4330+
borrow->getLoc(),
4331+
diag::borrow_mutate_accessor_not_supported_in_decl,
4332+
getAccessorNameForDiagnostic(borrow->getAccessorKind(),
4333+
/*article*/ true,
4334+
/*underscored*/ false));
43324335
}
43334336
if (mutate) {
43344337
storage->getASTContext().Diags.diagnose(
4335-
mutate->getLoc(), diag::accessor_not_supported_in_decl,
4336-
"a mutate accessor");
4338+
mutate->getLoc(),
4339+
diag::borrow_mutate_accessor_not_supported_in_decl,
4340+
getAccessorNameForDiagnostic(mutate->getAccessorKind(),
4341+
/*article*/ true,
4342+
/*underscored*/ false));
43374343
}
43384344
}
43394345
}

test/Parse/borrow_and_mutate_accessors.swift

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -80,31 +80,14 @@ struct Wrapper {
8080
var i: Int
8181

8282
var i_accessor: Int {
83-
borrow { // expected-error{{a 'borrow' accessor is supported only on a struct or enum}}
83+
borrow { // expected-error{{a 'borrow' accessor is supported only on a struct}}
8484
fatalError()
8585
}
86-
mutate { // expected-error{{a 'mutate' accessor is supported only on a struct or enum}}
86+
mutate { // expected-error{{a 'mutate' accessor is supported only on a struct}}
8787
return &i // expected-error{{'&' may only be used to pass an argument to inout parameter}}
8888
}
8989
}
9090

91-
var _count: Int = 0
92-
93-
enum Color {
94-
case red
95-
case green
96-
case blue
97-
98-
var count: Int {
99-
borrow {
100-
return _count
101-
}
102-
mutate {
103-
return &_count
104-
}
105-
}
106-
}
107-
10891
class KlassWrapper {
10992
var _k: Klass
11093

@@ -113,10 +96,10 @@ class KlassWrapper {
11396
}
11497

11598
var k: Klass {
116-
borrow {// expected-error{{a 'borrow' accessor is supported only on a struct or enum}}
99+
borrow {// expected-error{{a 'borrow' accessor is supported only on a struct}}
117100
return _k
118101
}
119-
mutate {// expected-error{{a 'mutate' accessor is supported only on a struct or enum}}
102+
mutate {// expected-error{{a 'mutate' accessor is supported only on a struct}}
120103
return &_k
121104
}
122105
}

test/Sema/borrow_and_mutate_accessors.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ struct Struct {
4141

4242
extension Klass {
4343
var i: Int {
44-
borrow { // expected-error{{a borrow accessor is supported only on a struct or enum}}
44+
borrow { // expected-error{{a 'borrow' accessor is supported only on a struct}}
4545
return 0
4646
}
47-
mutate { // expected-error{{a mutate accessor is supported only on a struct or enum}}
47+
mutate { // expected-error{{a 'mutate' accessor is supported only on a struct}}
4848
return &_i
4949
}
5050
}
@@ -67,3 +67,19 @@ protocol P {
6767
var phone: String { mutate } // expected-error{{property in protocol must have explicit { get } or { get set } specifier}} // expected-error{{expected get, read, or set in a protocol property}}
6868
}
6969

70+
enum OrderStatus: ~Copyable {
71+
case processing(trackingNumber: String)
72+
case cancelled(reason: String)
73+
74+
var description: String {
75+
borrow { // expected-error{{a 'borrow' accessor is supported only on a struct}}
76+
switch self {
77+
case .processing(let trackingNumber):
78+
return trackingNumber
79+
case .cancelled(let reason):
80+
return reason
81+
}
82+
}
83+
}
84+
}
85+

0 commit comments

Comments
 (0)