Skip to content

Commit e9220b4

Browse files
committed
Add a Fix-It to the warning about unnecessary @preconcurrency conformance
When we diagnose an unnecessary `@preconcurrency` on a conformance, also provide a Fix-It to remove the `@preconcurrency`.
1 parent c7c244e commit e9220b4

File tree

7 files changed

+30
-11
lines changed

7 files changed

+30
-11
lines changed

include/swift/AST/ASTContext.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,8 @@ class ASTContext final {
12381238
DeclContext *dc,
12391239
ProtocolConformanceState state,
12401240
bool isUnchecked,
1241-
bool isPreconcurrency);
1241+
bool isPreconcurrency,
1242+
SourceLoc preconcurrencyLoc = SourceLoc());
12421243

12431244
/// Produce a self-conformance for the given protocol.
12441245
SelfProtocolConformance *

include/swift/AST/ProtocolConformance.h

+12-3
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,9 @@ class NormalProtocolConformance : public RootProtocolConformance,
530530
/// The location of this protocol conformance in the source.
531531
SourceLoc Loc;
532532

533+
/// The location of the `@preconcurrency` attribute, if any.
534+
SourceLoc PreconcurrencyLoc;
535+
533536
/// The declaration context containing the ExtensionDecl or
534537
/// NominalTypeDecl that declared the conformance.
535538
DeclContext *Context;
@@ -562,10 +565,12 @@ class NormalProtocolConformance : public RootProtocolConformance,
562565
NormalProtocolConformance(Type conformingType, ProtocolDecl *protocol,
563566
SourceLoc loc, DeclContext *dc,
564567
ProtocolConformanceState state, bool isUnchecked,
565-
bool isPreconcurrency)
568+
bool isPreconcurrency,
569+
SourceLoc preconcurrencyLoc)
566570
: RootProtocolConformance(ProtocolConformanceKind::Normal,
567571
conformingType),
568-
Protocol(protocol), Loc(loc), Context(dc) {
572+
Protocol(protocol), Loc(loc), PreconcurrencyLoc(preconcurrencyLoc),
573+
Context(dc) {
569574
assert(!conformingType->hasArchetype() &&
570575
"ProtocolConformances should store interface types");
571576
setState(state);
@@ -580,7 +585,7 @@ class NormalProtocolConformance : public RootProtocolConformance,
580585
/// Get the protocol being conformed to.
581586
ProtocolDecl *getProtocol() const { return Protocol; }
582587

583-
/// Retrieve the location of this
588+
/// Retrieve the location of this conformance.
584589
SourceLoc getLoc() const { return Loc; }
585590

586591
/// Get the declaration context that contains the conforming extension or
@@ -629,6 +634,10 @@ class NormalProtocolConformance : public RootProtocolConformance,
629634
return Bits.NormalProtocolConformance.IsPreconcurrency;
630635
}
631636

637+
/// Retrieve the location of `@preconcurrency`, if there is one and it is
638+
/// known.
639+
SourceLoc getPreconcurrencyLoc() const { return PreconcurrencyLoc; }
640+
632641
/// Determine whether we've lazily computed the associated conformance array
633642
/// already.
634643
bool hasComputedAssociatedConformances() const {

lib/AST/ASTContext.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -2593,7 +2593,8 @@ ASTContext::getNormalConformance(Type conformingType,
25932593
DeclContext *dc,
25942594
ProtocolConformanceState state,
25952595
bool isUnchecked,
2596-
bool isPreconcurrency) {
2596+
bool isPreconcurrency,
2597+
SourceLoc preconcurrencyLoc) {
25972598
assert(dc->isTypeContext());
25982599

25992600
llvm::FoldingSetNodeID id;
@@ -2609,7 +2610,7 @@ ASTContext::getNormalConformance(Type conformingType,
26092610
// Build a new normal protocol conformance.
26102611
auto result = new (*this, AllocationArena::Permanent)
26112612
NormalProtocolConformance(conformingType, protocol, loc, dc, state,
2612-
isUnchecked, isPreconcurrency);
2613+
isUnchecked, isPreconcurrency, preconcurrencyLoc);
26132614
normalConformances.InsertNode(result, insertPos);
26142615

26152616
return result;

lib/AST/ConformanceLookupTable.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,8 @@ ConformanceLookupTable::getConformance(NominalTypeDecl *nominal,
989989
conformingType, protocol, conformanceLoc, conformingDC,
990990
ProtocolConformanceState::Incomplete,
991991
entry->Source.getUncheckedLoc().isValid(),
992-
entry->Source.getPreconcurrencyLoc().isValid());
992+
entry->Source.getPreconcurrencyLoc().isValid(),
993+
entry->Source.getPreconcurrencyLoc());
993994
// Invalid code may cause the getConformance call below to loop, so break
994995
// the infinite recursion by setting this eagerly to shortcircuit with the
995996
// early return at the start of this function.

lib/AST/TypeRepr.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ SourceLoc TypeRepr::findAttrLoc(TypeAttrKind kind) const {
147147
for (auto attr : attrTypeRepr->getAttrs()) {
148148
if (auto typeAttr = attr.dyn_cast<TypeAttribute*>())
149149
if (typeAttr->getKind() == kind)
150-
return typeAttr->getAttrLoc();
150+
return typeAttr->getStartLoc();
151151
}
152152

153153
typeRepr = attrTypeRepr->getTypeRepr();

lib/Sema/TypeCheckProtocol.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -5120,9 +5120,16 @@ void ConformanceChecker::resolveValueWitnesses() {
51205120
}
51215121

51225122
if (Conformance->isPreconcurrency() && !usesPreconcurrencyConformance) {
5123-
DC->getASTContext().Diags.diagnose(
5123+
auto diag = DC->getASTContext().Diags.diagnose(
51245124
Conformance->getLoc(), diag::preconcurrency_conformance_not_used,
51255125
Proto->getDeclaredInterfaceType());
5126+
5127+
SourceLoc preconcurrencyLoc = Conformance->getPreconcurrencyLoc();
5128+
if (preconcurrencyLoc.isValid()) {
5129+
SourceLoc endLoc =
5130+
preconcurrencyLoc.getAdvancedLoc(strlen("@preconcurrency "));
5131+
diag.fixItRemoveChars(preconcurrencyLoc, endLoc);
5132+
}
51265133
}
51275134

51285135
// Finally, check some ad-hoc protocol requirements.

test/Concurrency/preconcurrency_conformances.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ protocol WithNonIsolated {
152152

153153
do {
154154
class TestExplicitOtherIsolation : @preconcurrency WithNonIsolated {
155-
// expected-warning@-1 {{@preconcurrency attribute on conformance to 'WithNonIsolated' has no effect}}
155+
// expected-warning@-1 {{@preconcurrency attribute on conformance to 'WithNonIsolated' has no effect}}{{38-54=}}
156156

157157
@GlobalActor var prop: Int = 42
158158
// expected-warning@-1 {{global actor 'GlobalActor'-isolated property 'prop' cannot be used to satisfy main actor-isolated protocol requirement}}
@@ -164,7 +164,7 @@ do {
164164

165165
do {
166166
class InferredGlobalActorAttrs : @preconcurrency WithNonIsolated {
167-
// expected-warning@-1 {{@preconcurrency attribute on conformance to 'WithNonIsolated' has no effect}}
167+
// expected-warning@-1 {{@preconcurrency attribute on conformance to 'WithNonIsolated' has no effect}}{{36-52=}}
168168
var prop: Int = 42
169169
func test() {}
170170
}

0 commit comments

Comments
 (0)