Skip to content

Commit 359f898

Browse files
Merge pull request #77546 from nate-chandler/general-coro/20241110/1
[CoroutineAccessors] Ban read+_read and modify+_modify.
2 parents d2d830f + 0089d4d commit 359f898

File tree

9 files changed

+141
-81
lines changed

9 files changed

+141
-81
lines changed

include/swift/AST/Decl.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9705,8 +9705,11 @@ const ParamDecl *getParameterAt(const ValueDecl *source, unsigned index);
97059705
/// nullptr if the source does not have a parameter list.
97069706
const ParamDecl *getParameterAt(const DeclContext *source, unsigned index);
97079707

9708-
StringRef getAccessorNameForDiagnostic(AccessorDecl *accessor, bool article);
9709-
StringRef getAccessorNameForDiagnostic(AccessorKind accessorKind, bool article);
9708+
StringRef
9709+
getAccessorNameForDiagnostic(AccessorDecl *accessor, bool article,
9710+
std::optional<bool> underscored = std::nullopt);
9711+
StringRef getAccessorNameForDiagnostic(AccessorKind accessorKind, bool article,
9712+
bool underscored);
97109713

97119714
void simple_display(llvm::raw_ostream &out,
97129715
OptionSet<NominalTypeDecl::LookupDirectFlags> options);

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2381,12 +2381,6 @@ void PrintAST::printSelfAccessKindModifiersIfNeeded(const FuncDecl *FD) {
23812381
}
23822382
}
23832383

2384-
static bool
2385-
shouldPrintUnderscoredCoroutineAccessors(const AbstractStorageDecl *ASD) {
2386-
// TODO: CoroutineAccessors: Print only when necessary.
2387-
return true;
2388-
}
2389-
23902384
void PrintAST::printAccessors(const AbstractStorageDecl *ASD) {
23912385
if (isa<VarDecl>(ASD) && !Options.PrintPropertyAccessors)
23922386
return;
@@ -2563,7 +2557,7 @@ void PrintAST::printAccessors(const AbstractStorageDecl *ASD) {
25632557
break;
25642558
case ReadImplKind::Read2:
25652559
if (ASD->getAccessor(AccessorKind::Read) &&
2566-
shouldPrintUnderscoredCoroutineAccessors(ASD)) {
2560+
Options.SuppressCoroutineAccessors) {
25672561
AddAccessorToPrint(AccessorKind::Read);
25682562
}
25692563
AddAccessorToPrint(AccessorKind::Read2);
@@ -2597,7 +2591,7 @@ void PrintAST::printAccessors(const AbstractStorageDecl *ASD) {
25972591
break;
25982592
case WriteImplKind::Modify2:
25992593
if (ASD->getAccessor(AccessorKind::Modify) &&
2600-
shouldPrintUnderscoredCoroutineAccessors(ASD)) {
2594+
Options.SuppressCoroutineAccessors) {
26012595
AddAccessorToPrint(AccessorKind::Modify);
26022596
}
26032597
AddAccessorToPrint(AccessorKind::Modify2);

lib/AST/Decl.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6863,7 +6863,7 @@ bool ProtocolDecl::hasCircularInheritedProtocols() const {
68636863

68646864
/// Returns a descriptive name for the given accessor/addressor kind.
68656865
StringRef swift::getAccessorNameForDiagnostic(AccessorKind accessorKind,
6866-
bool article) {
6866+
bool article, bool underscored) {
68676867
switch (accessorKind) {
68686868
case AccessorKind::Get:
68696869
return article ? "a getter" : "getter";
@@ -6876,9 +6876,17 @@ StringRef swift::getAccessorNameForDiagnostic(AccessorKind accessorKind,
68766876
case AccessorKind::MutableAddress:
68776877
return article ? "a mutable addressor" : "mutable addressor";
68786878
case AccessorKind::Read:
6879+
if (underscored)
6880+
return article ? "a '_read' accessor" : "'_read' accessor";
6881+
// Fall through to the non-underscored spelling.
6882+
LLVM_FALLTHROUGH;
68796883
case AccessorKind::Read2:
68806884
return article ? "a 'read' accessor" : "'read' accessor";
68816885
case AccessorKind::Modify:
6886+
if (underscored)
6887+
return article ? "a '_modify' accessor" : "'_modify' accessor";
6888+
// Fall through to the non-underscored spelling.
6889+
LLVM_FALLTHROUGH;
68826890
case AccessorKind::Modify2:
68836891
return article ? "a 'modify' accessor" : "'modify' accessor";
68846892
case AccessorKind::WillSet:
@@ -6892,9 +6900,12 @@ StringRef swift::getAccessorNameForDiagnostic(AccessorKind accessorKind,
68926900
}
68936901

68946902
StringRef swift::getAccessorNameForDiagnostic(AccessorDecl *accessor,
6895-
bool article) {
6896-
return getAccessorNameForDiagnostic(accessor->getAccessorKind(),
6897-
article);
6903+
bool article,
6904+
std::optional<bool> underscored) {
6905+
return getAccessorNameForDiagnostic(
6906+
accessor->getAccessorKind(), article,
6907+
underscored.value_or(accessor->getASTContext().LangOpts.hasFeature(
6908+
Feature::CoroutineAccessors)));
68986909
}
68996910

69006911
bool AbstractStorageDecl::hasStorage() const {

lib/Parse/ParseDecl.cpp

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7932,15 +7932,17 @@ bool Parser::parseAccessorAfterIntroducer(
79327932
if (requiresFeatureCoroutineAccessors(Kind) &&
79337933
!Context.LangOpts.hasFeature(Feature::CoroutineAccessors)) {
79347934
diagnose(Tok, diag::accessor_requires_coroutine_accessors,
7935-
getAccessorNameForDiagnostic(Kind, /*article*/ false));
7935+
getAccessorNameForDiagnostic(Kind, /*article*/ false,
7936+
/*underscored*/ false));
79367937
}
79377938

79387939
// There should be no body in the limited syntax; diagnose unexpected
79397940
// accessor implementations.
79407941
if (parsingLimitedSyntax) {
79417942
if (Tok.is(tok::l_brace))
79427943
diagnose(Tok, diag::unexpected_getset_implementation_in_protocol,
7943-
getAccessorNameForDiagnostic(Kind, /*article*/ false));
7944+
getAccessorNameForDiagnostic(Kind, /*article*/ false,
7945+
/*underscored*/ false));
79447946
return false;
79457947
}
79467948

@@ -8352,16 +8354,45 @@ void Parser::ParsedAccessors::record(Parser &P, AbstractStorageDecl *storage,
83528354
storage->setAccessors(LBLoc, Accessors, RBLoc);
83538355
}
83548356

8357+
static std::optional<AccessorKind>
8358+
getCorrespondingUnderscoredAccessorKind(AccessorKind kind) {
8359+
switch (kind) {
8360+
case AccessorKind::Read2:
8361+
return {AccessorKind::Read};
8362+
case AccessorKind::Modify2:
8363+
return {AccessorKind::Modify};
8364+
case AccessorKind::Get:
8365+
case AccessorKind::DistributedGet:
8366+
case AccessorKind::Set:
8367+
case AccessorKind::Read:
8368+
case AccessorKind::Modify:
8369+
case AccessorKind::WillSet:
8370+
case AccessorKind::DidSet:
8371+
case AccessorKind::Address:
8372+
case AccessorKind::MutableAddress:
8373+
case AccessorKind::Init:
8374+
return std::nullopt;
8375+
}
8376+
}
8377+
83558378
static void diagnoseConflictingAccessors(Parser &P, AccessorDecl *first,
83568379
AccessorDecl *&second) {
83578380
if (!second) return;
8358-
P.diagnose(second->getLoc(), diag::conflicting_accessor,
8359-
isa<SubscriptDecl>(first->getStorage()),
8360-
getAccessorNameForDiagnostic(second, /*article*/ true),
8361-
getAccessorNameForDiagnostic(first, /*article*/ true));
8362-
P.diagnose(first->getLoc(), diag::previous_accessor,
8363-
getAccessorNameForDiagnostic(first, /*article*/ false),
8364-
/*already*/ false);
8381+
bool underscored =
8382+
(getCorrespondingUnderscoredAccessorKind(first->getAccessorKind()) ==
8383+
second->getAccessorKind()) ||
8384+
(getCorrespondingUnderscoredAccessorKind(second->getAccessorKind()) ==
8385+
first->getAccessorKind()) ||
8386+
first->getASTContext().LangOpts.hasFeature(Feature::CoroutineAccessors);
8387+
P.diagnose(
8388+
second->getLoc(), diag::conflicting_accessor,
8389+
isa<SubscriptDecl>(first->getStorage()),
8390+
getAccessorNameForDiagnostic(second, /*article*/ true, underscored),
8391+
getAccessorNameForDiagnostic(first, /*article*/ true, underscored));
8392+
P.diagnose(
8393+
first->getLoc(), diag::previous_accessor,
8394+
getAccessorNameForDiagnostic(first, /*article*/ false, underscored),
8395+
/*already*/ false);
83658396
second->setInvalid();
83668397
}
83678398

@@ -8404,12 +8435,13 @@ void Parser::ParsedAccessors::classify(Parser &P, AbstractStorageDecl *storage,
84048435

84058436
// Okay, observers are out of the way.
84068437

8407-
// 'get', 'read', and a non-mutable addressor are all exclusive.
8438+
// 'get', '_read', 'read' and a non-mutable addressor are all exclusive.
84088439
if (Get) {
84098440
diagnoseConflictingAccessors(P, Get, Read);
84108441
diagnoseConflictingAccessors(P, Get, Read2);
84118442
diagnoseConflictingAccessors(P, Get, Address);
84128443
} else if (Read) {
8444+
diagnoseConflictingAccessors(P, Read, Read2);
84138445
diagnoseConflictingAccessors(P, Read, Address);
84148446
} else if (Read2) {
84158447
diagnoseConflictingAccessors(P, Read2, Address);
@@ -8438,11 +8470,13 @@ void Parser::ParsedAccessors::classify(Parser &P, AbstractStorageDecl *storage,
84388470
}
84398471
}
84408472

8441-
// A mutable addressor is exclusive with 'set' and 'modify', but
8442-
// 'set' and 'modify' can appear together.
8473+
// '_modify', 'modify' and 'unsafeMutableAddress' are all mutually exclusive.
8474+
// 'unsafeMutableAddress' and 'set' are mutually exclusive, but 'set' and
8475+
// 'modify' can appear together.
84438476
if (Set) {
84448477
diagnoseConflictingAccessors(P, Set, MutableAddress);
84458478
} else if (Modify) {
8479+
diagnoseConflictingAccessors(P, Modify, Modify2);
84468480
diagnoseConflictingAccessors(P, Modify, MutableAddress);
84478481
}
84488482

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3644,7 +3644,7 @@ static FuncDecl *findSimilarAccessor(DeclNameRef replacedVarName,
36443644
origStorage->getWriteImpl() == WriteImplKind::Stored)) {
36453645
Diags.diagnose(attr->getLocation(),
36463646
diag::dynamic_replacement_accessor_not_explicit,
3647-
getAccessorNameForDiagnostic(origAccessor->getAccessorKind(),
3647+
getAccessorNameForDiagnostic(origAccessor,
36483648
/*article=*/false),
36493649
origStorage->getName());
36503650
attr->setInvalid();

lib/Sema/TypeCheckStorage.cpp

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -717,13 +717,19 @@ static void diagnoseReadWriteMutatingnessMismatch(
717717
auto disagreesWithWriter = (isWriterMutating != isModifierMutating);
718718
auto disagreesWithBoth = disagreesWithReader && disagreesWithWriter;
719719

720+
bool hasCoroutineAccessorFeature =
721+
storage->getASTContext().LangOpts.hasFeature(Feature::CoroutineAccessors);
722+
720723
auto readerAccessor = directAccessorKindForReadImpl(storage->getReadImpl());
721724
StringRef readerAccessorName =
722725
readerAccessor.has_value()
723-
? getAccessorNameForDiagnostic(*readerAccessor, /*article=*/false)
726+
? getAccessorNameForDiagnostic(
727+
*readerAccessor, /*article=*/false,
728+
/*underscored=*/hasCoroutineAccessorFeature)
724729
: "the inherited accessor";
725730
StringRef writerAccessorName =
726-
getAccessorNameForDiagnostic(writerAccesor, /*article=*/false);
731+
getAccessorNameForDiagnostic(writerAccesor, /*article=*/false,
732+
/*underscored=*/hasCoroutineAccessorFeature);
727733
unsigned diagnosticForm;
728734
if (isModifierMutating) {
729735
// modifier can't be mutating when both the setter is nonmutating and the
@@ -745,16 +751,20 @@ static void diagnoseReadWriteMutatingnessMismatch(
745751

746752
modifyAccessor->diagnose(
747753
diag::readwriter_mutatingness_differs_from_reader_or_writer_mutatingness,
748-
getAccessorNameForDiagnostic(readWriterAccessor, /*article=*/false),
754+
getAccessorNameForDiagnostic(readWriterAccessor, /*article=*/false,
755+
/*underscored=*/hasCoroutineAccessorFeature),
749756
isModifierMutating ? SelfAccessKind::Mutating
750757
: SelfAccessKind::NonMutating,
751758
diagnosticForm, writerAccessorName, SelfAccessKind::NonMutating,
752759
readerAccessorName, SelfAccessKind::Mutating);
753760
auto *writer = storage->getParsedAccessor(writerAccesor);
754761
if (disagreesWithWriter && writer) {
755-
writer->diagnose(
756-
diag::previous_accessor,
757-
getAccessorNameForDiagnostic(writerAccesor, /*article=*/false), 0);
762+
writer->diagnose(diag::previous_accessor,
763+
getAccessorNameForDiagnostic(
764+
writerAccesor,
765+
/*article=*/false,
766+
/*underscored=*/hasCoroutineAccessorFeature),
767+
0);
758768
}
759769
AccessorDecl *reader = nullptr;
760770
if (disagreesWithReader && readerAccessor.has_value() &&
@@ -3960,6 +3970,8 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
39603970

39613971
bool hasWillSet = storage->getParsedAccessor(AccessorKind::WillSet);
39623972
bool hasDidSet = storage->getParsedAccessor(AccessorKind::DidSet);
3973+
bool hasCoroutineAccessorFeature =
3974+
storage->getASTContext().LangOpts.hasFeature(Feature::CoroutineAccessors);
39633975
if ((hasWillSet || hasDidSet) && !isa<SubscriptDecl>(storage)) {
39643976
// Observers conflict with non-observers.
39653977
AccessorDecl *firstNonObserver = nullptr;
@@ -3972,19 +3984,21 @@ StorageImplInfoRequest::evaluate(Evaluator &evaluator,
39723984

39733985
if (firstNonObserver) {
39743986
if (auto willSet = storage->getParsedAccessor(AccessorKind::WillSet)) {
3975-
willSet->diagnose(
3976-
diag::observing_accessor_conflicts_with_accessor, 0,
3977-
getAccessorNameForDiagnostic(
3978-
firstNonObserver->getAccessorKind(), /*article=*/ true));
3987+
willSet->diagnose(diag::observing_accessor_conflicts_with_accessor, 0,
3988+
getAccessorNameForDiagnostic(
3989+
firstNonObserver->getAccessorKind(),
3990+
/*article=*/true,
3991+
/*underscored=*/hasCoroutineAccessorFeature));
39793992
willSet->setInvalid();
39803993
hasWillSet = false;
39813994
}
39823995

39833996
if (auto didSet = storage->getParsedAccessor(AccessorKind::DidSet)) {
3984-
didSet->diagnose(
3985-
diag::observing_accessor_conflicts_with_accessor, 1,
3986-
getAccessorNameForDiagnostic(
3987-
firstNonObserver->getAccessorKind(), /*article=*/ true));
3997+
didSet->diagnose(diag::observing_accessor_conflicts_with_accessor, 1,
3998+
getAccessorNameForDiagnostic(
3999+
firstNonObserver->getAccessorKind(),
4000+
/*article=*/true,
4001+
/*underscored=*/hasCoroutineAccessorFeature));
39884002
didSet->setInvalid();
39894003
hasDidSet = false;
39904004
}

test/ModuleInterface/coroutine_accessors.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ var _i: Int = 0
1212

1313
// CHECK: #if compiler(>=5.3) && $CoroutineAccessors
1414
// CHECK-NEXT: public var i: Swift.Int {
15-
// CHECK-NEXT: _read
1615
// CHECK-NEXT: read
17-
// CHECK-NEXT: _modify
1816
// CHECK-NEXT: modify
1917
// CHECK-NEXT: }
2018
// CHECK-NEXT: #else
@@ -24,15 +22,9 @@ var _i: Int = 0
2422
// CHECK-NEXT: }
2523
// CHECK-NEXT: #endif
2624
public var i: Int {
27-
_read {
28-
yield _i
29-
}
3025
read {
3126
yield _i
3227
}
33-
_modify {
34-
yield &_i
35-
}
3628
modify {
3729
yield &_i
3830
}

0 commit comments

Comments
 (0)