mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[CoroutineAccessors] Ban _read+read.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user