[CoroutineAccessors] Ban _read+read.

This commit is contained in:
Nate Chandler
2024-11-10 14:58:36 -08:00
parent de86cc037c
commit 0089d4d54e
4 changed files with 58 additions and 29 deletions

View File

@@ -2391,12 +2391,6 @@ void PrintAST::printSelfAccessKindModifiersIfNeeded(const FuncDecl *FD) {
}
}
static bool
shouldPrintUnderscoredCoroutineAccessors(const AbstractStorageDecl *ASD) {
// TODO: CoroutineAccessors: Print only when necessary.
return true;
}
void PrintAST::printAccessors(const AbstractStorageDecl *ASD) {
if (isa<VarDecl>(ASD) && !Options.PrintPropertyAccessors)
return;
@@ -2573,7 +2567,7 @@ void PrintAST::printAccessors(const AbstractStorageDecl *ASD) {
break;
case ReadImplKind::Read2:
if (ASD->getAccessor(AccessorKind::Read) &&
shouldPrintUnderscoredCoroutineAccessors(ASD)) {
Options.SuppressCoroutineAccessors) {
AddAccessorToPrint(AccessorKind::Read);
}
AddAccessorToPrint(AccessorKind::Read2);
@@ -2607,7 +2601,7 @@ void PrintAST::printAccessors(const AbstractStorageDecl *ASD) {
break;
case WriteImplKind::Modify2:
if (ASD->getAccessor(AccessorKind::Modify) &&
shouldPrintUnderscoredCoroutineAccessors(ASD)) {
Options.SuppressCoroutineAccessors) {
AddAccessorToPrint(AccessorKind::Modify);
}
AddAccessorToPrint(AccessorKind::Modify2);

View File

@@ -8336,16 +8336,45 @@ void Parser::ParsedAccessors::record(Parser &P, AbstractStorageDecl *storage,
storage->setAccessors(LBLoc, Accessors, RBLoc);
}
static std::optional<AccessorKind>
getCorrespondingUnderscoredAccessorKind(AccessorKind kind) {
switch (kind) {
case AccessorKind::Read2:
return {AccessorKind::Read};
case AccessorKind::Modify2:
return {AccessorKind::Modify};
case AccessorKind::Get:
case AccessorKind::DistributedGet:
case AccessorKind::Set:
case AccessorKind::Read:
case AccessorKind::Modify:
case AccessorKind::WillSet:
case AccessorKind::DidSet:
case AccessorKind::Address:
case AccessorKind::MutableAddress:
case AccessorKind::Init:
return std::nullopt;
}
}
static void diagnoseConflictingAccessors(Parser &P, AccessorDecl *first,
AccessorDecl *&second) {
if (!second) return;
P.diagnose(second->getLoc(), diag::conflicting_accessor,
isa<SubscriptDecl>(first->getStorage()),
getAccessorNameForDiagnostic(second, /*article*/ true),
getAccessorNameForDiagnostic(first, /*article*/ true));
P.diagnose(first->getLoc(), diag::previous_accessor,
getAccessorNameForDiagnostic(first, /*article*/ false),
/*already*/ false);
bool underscored =
(getCorrespondingUnderscoredAccessorKind(first->getAccessorKind()) ==
second->getAccessorKind()) ||
(getCorrespondingUnderscoredAccessorKind(second->getAccessorKind()) ==
first->getAccessorKind()) ||
first->getASTContext().LangOpts.hasFeature(Feature::CoroutineAccessors);
P.diagnose(
second->getLoc(), diag::conflicting_accessor,
isa<SubscriptDecl>(first->getStorage()),
getAccessorNameForDiagnostic(second, /*article*/ true, underscored),
getAccessorNameForDiagnostic(first, /*article*/ true, underscored));
P.diagnose(
first->getLoc(), diag::previous_accessor,
getAccessorNameForDiagnostic(first, /*article*/ false, underscored),
/*already*/ false);
second->setInvalid();
}
@@ -8388,12 +8417,13 @@ void Parser::ParsedAccessors::classify(Parser &P, AbstractStorageDecl *storage,
// Okay, observers are out of the way.
// 'get', 'read', and a non-mutable addressor are all exclusive.
// 'get', '_read', 'read' and a non-mutable addressor are all exclusive.
if (Get) {
diagnoseConflictingAccessors(P, Get, Read);
diagnoseConflictingAccessors(P, Get, Read2);
diagnoseConflictingAccessors(P, Get, Address);
} else if (Read) {
diagnoseConflictingAccessors(P, Read, Read2);
diagnoseConflictingAccessors(P, Read, Address);
} else if (Read2) {
diagnoseConflictingAccessors(P, Read2, Address);
@@ -8422,11 +8452,13 @@ void Parser::ParsedAccessors::classify(Parser &P, AbstractStorageDecl *storage,
}
}
// A mutable addressor is exclusive with 'set' and 'modify', but
// 'set' and 'modify' can appear together.
// '_modify', 'modify' and 'unsafeMutableAddress' are all mutually exclusive.
// 'unsafeMutableAddress' and 'set' are mutually exclusive, but 'set' and
// 'modify' can appear together.
if (Set) {
diagnoseConflictingAccessors(P, Set, MutableAddress);
} else if (Modify) {
diagnoseConflictingAccessors(P, Modify, Modify2);
diagnoseConflictingAccessors(P, Modify, MutableAddress);
}

View File

@@ -12,9 +12,7 @@ var _i: Int = 0
// CHECK: #if compiler(>=5.3) && $CoroutineAccessors
// CHECK-NEXT: public var i: Swift.Int {
// CHECK-NEXT: _read
// CHECK-NEXT: read
// CHECK-NEXT: _modify
// CHECK-NEXT: modify
// CHECK-NEXT: }
// CHECK-NEXT: #else
@@ -24,15 +22,9 @@ var _i: Int = 0
// CHECK-NEXT: }
// CHECK-NEXT: #endif
public var i: Int {
_read {
yield _i
}
read {
yield _i
}
_modify {
yield &_i
}
modify {
yield &_i
}

View File

@@ -30,14 +30,16 @@ var _i: Int = 0
// disabled: implicit getter.
var ir_r: Int {
read { // expected-disabled-error{{cannot_find_in_scope}}
// expected-enabled-error@-1{{variable cannot provide both a 'read' accessor and a '_read' accessor}}
fatalError()
}
_read { // expected-disabled-error{{cannot_find_in_scope}}
// expected-enabled-note@-1{{previous_accessor}}
fatalError()
}
}
// enabled: ok
// enabled: conflicting accessors
var igr: Int {
get {
1
@@ -255,14 +257,16 @@ var iumam: Int {
}
}
// enabled: need a reader.
// enabled: conflicting accessors. need a reader.
// disabled: implicit getter.
var im_m: Int {
modify { // expected-disabled-error{{cannot_find_in_scope}}
// expected-enabled-error@-1{{variable cannot provide both a 'modify' accessor and a '_modify' accessor}}
fatalError()
}
_modify { // expected-enabled-error{{variable with a '_modify' accessor must also have a getter, addressor, or 'read' accessor}}
// expected-disabled-error@-1{{cannot_find_in_scope}}
// expected-enabled-note@-2{{previous_accessor}}
fatalError()
}
}
@@ -272,9 +276,11 @@ var im_m: Int {
var i_mm: Int {
_modify { // expected-enabled-error{{variable with a '_modify' accessor must also have a getter, addressor, or 'read' accessor}}
// expected-disabled-error@-1{{variable with a 'modify' accessor must also have a getter, addressor, or 'read' accessor}}
// expected-note@-2{{previous_accessor}}
fatalError()
}
modify { // expected-disabled-error{{'modify' accessor is only valid when experimental feature coroutine accessors is enabled}}
// expected-error@-1{{variable cannot provide both a 'modify' accessor and a '_modify' accessor}}
fatalError()
}
}
@@ -304,9 +310,10 @@ var i_rm_m: Int {
yield _i
}
modify { // expected-disabled-error{{'modify' accessor is only valid when experimental feature coroutine accessors is enabled}}
// expected-error@-1{{variable cannot provide both a 'modify' accessor and a '_modify' accessor}}
yield &_i
}
_modify {
_modify { // expected-note{{previous_accessor}}
yield &_i
}
}
@@ -315,15 +322,19 @@ var i_rm_m: Int {
// disabled: implicit getter
var ir_rm_m: Int {
read { // expected-disabled-error{{cannot_find_in_scope}}
// expected-enabled-error@-1{{variable cannot provide both a 'read' accessor and a '_read' accessor}}
fatalError()
}
_read { // expected-disabled-error{{cannot_find_in_scope}}
// expected-enabled-note@-1{{previous_accessor}}
fatalError()
}
modify { // expected-disabled-error{{cannot_find_in_scope}}
// expected-enabled-error@-1{{variable cannot provide both a 'modify' accessor and a '_modify' accessor}}
fatalError()
}
_modify { // expected-disabled-error{{cannot_find_in_scope}}
// expected-enabled-note@-1{{previous_accessor}}
fatalError()
}
}