Skip to content

Commit a86d942

Browse files
committed
Migrate "@unchecked Sendable" strict safety diagnostic to become a note associated with its type
1 parent 192bb33 commit a86d942

File tree

5 files changed

+43
-26
lines changed

5 files changed

+43
-26
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8093,6 +8093,9 @@ NOTE(note_reference_to_nonisolated_unsafe,none,
80938093
(const ValueDecl *))
80948094
NOTE(note_reference_unowned_unsafe,none,
80958095
"reference to unowned(unsafe) %kind0 is unsafe", (const ValueDecl *))
8096+
NOTE(note_use_of_unchecked_conformance_is_unsafe,none,
8097+
"@unchecked conformance of %0 to %kind1 involves unsafe code",
8098+
(Type, const ValueDecl *))
80968099

80978100
GROUPED_WARNING(override_safe_withunsafe,Unsafe,none,
80988101
"override of safe %0 with unsafe %0", (DescriptiveDeclKind))
@@ -8102,8 +8105,9 @@ GROUPED_WARNING(witness_unsafe,Unsafe,none,
81028105
GROUPED_WARNING(type_witness_unsafe,Unsafe,none,
81038106
"unsafe type %0 cannot satisfy safe associated type %1",
81048107
(Type, DeclName))
8105-
GROUPED_WARNING(unchecked_conformance_is_unsafe,Unsafe,none,
8106-
"@unchecked conformance involves unsafe code", ())
8108+
GROUPED_WARNING(use_of_unchecked_conformance_is_unsafe,Unsafe,none,
8109+
"@unchecked conformance of %0 to %kind1 involves unsafe code",
8110+
(Type, const ValueDecl *))
81078111
GROUPED_WARNING(reference_unowned_unsafe,Unsafe,none,
81088112
"reference to unowned(unsafe) %kind0 is unsafe", (const ValueDecl *))
81098113
GROUPED_WARNING(reference_to_nonisolated_unsafe,Unsafe,none,

include/swift/AST/UnsafeUse.h

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,13 @@
1515

1616
#include "swift/AST/Decl.h"
1717
#include "swift/AST/ProtocolConformance.h"
18+
#include "swift/AST/ProtocolConformanceRef.h"
1819
#include "swift/AST/Type.h"
1920
#include "swift/Basic/SourceLoc.h"
2021
#include "swift/Basic/Unreachable.h"
2122

2223
namespace swift {
2324

24-
class NormalProtocolConformance;
25-
2625
/// Describes a use of an unsafe construct.
2726
///
2827
/// Every use of an unsafe construct that should be diagnosed will be captured
@@ -66,7 +65,8 @@ class UnsafeUse {
6665
} typeWitness;
6766

6867
struct {
69-
NormalProtocolConformance *conformance;
68+
TypeBase *type;
69+
void *conformanceRef;
7070
DeclContext *declContext;
7171
const void *location;
7272
} conformance;
@@ -139,11 +139,13 @@ class UnsafeUse {
139139
return result;
140140
}
141141

142-
static UnsafeUse forConformance(NormalProtocolConformance *conformance,
142+
static UnsafeUse forConformance(Type subjectType,
143+
ProtocolConformanceRef conformance,
143144
SourceLoc location,
144145
DeclContext *dc) {
145146
UnsafeUse result(UnsafeConformance);
146-
result.storage.conformance.conformance = conformance;
147+
result.storage.conformance.type = subjectType.getPointer();
148+
result.storage.conformance.conformanceRef = conformance.getOpaqueValue();
147149
result.storage.conformance.declContext = dc;
148150
result.storage.conformance.location = location.getOpaquePointerValue();
149151
return result;
@@ -180,7 +182,9 @@ class UnsafeUse {
180182
return getDecl()->getLoc();
181183

182184
case UnsafeConformance:
183-
return getConformance()->getLoc();
185+
return SourceLoc(
186+
llvm::SMLoc::getFromPointer(
187+
(const char *)storage.conformance.location));
184188

185189
case TypeWitness:
186190
return SourceLoc(
@@ -237,7 +241,7 @@ class UnsafeUse {
237241

238242
case Witness:
239243
case TypeWitness:
240-
return getConformance()->getDeclContext();
244+
return getConformance().getConcrete()->getDeclContext();
241245

242246
case UnsafeConformance:
243247
return storage.conformance.declContext;
@@ -268,9 +272,11 @@ class UnsafeUse {
268272
switch (getKind()) {
269273
case Override:
270274
case Witness:
271-
case UnsafeConformance:
272275
return nullptr;
273276

277+
case UnsafeConformance:
278+
return storage.conformance.type;
279+
274280
case TypeWitness:
275281
return storage.typeWitness.type;
276282

@@ -283,23 +289,24 @@ class UnsafeUse {
283289
}
284290

285291
/// Get the protocol conformance, if there is one.
286-
NormalProtocolConformance *getConformance() const {
292+
ProtocolConformanceRef getConformance() const {
287293
switch (getKind()) {
288294
case UnsafeConformance:
289-
return storage.conformance.conformance;
295+
return ProtocolConformanceRef::getFromOpaqueValue(
296+
storage.conformance.conformanceRef);
290297

291298
case Witness:
292-
return storage.polymorphic.conformance;
299+
return ProtocolConformanceRef(storage.polymorphic.conformance);
293300

294301
case TypeWitness:
295-
return storage.typeWitness.conformance;
302+
return ProtocolConformanceRef(storage.typeWitness.conformance);
296303

297304
case Override:
298305
case UnownedUnsafe:
299306
case NonisolatedUnsafe:
300307
case ReferenceToUnsafe:
301308
case CallToUnsafe:
302-
return nullptr;
309+
return ProtocolConformanceRef::forInvalid();
303310
}
304311
}
305312
};

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2469,7 +2469,9 @@ checkIndividualConformance(NormalProtocolConformance *conformance) {
24692469

24702470
if (!conformance->getDeclContext()->allowsUnsafe()) {
24712471
diagnoseUnsafeUse(
2472-
UnsafeUse::forConformance(conformance, ComplainLoc,
2472+
UnsafeUse::forConformance(conformance->getType(),
2473+
ProtocolConformanceRef(conformance),
2474+
ComplainLoc,
24732475
conformance->getDeclContext()));
24742476
}
24752477
}

lib/Sema/TypeCheckUnsafe.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ static bool isUnsafeUseInDefinition(const UnsafeUse &use) {
3838
case UnsafeUse::Override:
3939
case UnsafeUse::Witness:
4040
case UnsafeUse::TypeWitness:
41-
case UnsafeUse::UnsafeConformance:
4241
// Never part of the definition. These are always part of the interface.
4342
return false;
4443

4544
case UnsafeUse::ReferenceToUnsafe:
4645
case UnsafeUse::CallToUnsafe:
4746
case UnsafeUse::NonisolatedUnsafe:
4847
case UnsafeUse::UnownedUnsafe:
48+
case UnsafeUse::UnsafeConformance:
4949
return enclosingContextForUnsafe(use).second;
5050
}
5151
}
@@ -74,7 +74,7 @@ static void suggestUnsafeOnEnclosingDecl(
7474
}
7575

7676
static void suggestUnsafeMarkerOnConformance(
77-
NormalProtocolConformance *conformance) {
77+
ProtocolConformance *conformance) {
7878
auto dc = conformance->getDeclContext();
7979
auto decl = dc->getAsDecl();
8080
if (!decl)
@@ -105,7 +105,8 @@ void swift::diagnoseUnsafeUse(const UnsafeUse &use, bool asNote) {
105105
if (use.getKind() == UnsafeUse::ReferenceToUnsafe ||
106106
use.getKind() == UnsafeUse::CallToUnsafe ||
107107
use.getKind() == UnsafeUse::NonisolatedUnsafe ||
108-
use.getKind() == UnsafeUse::UnownedUnsafe) {
108+
use.getKind() == UnsafeUse::UnownedUnsafe ||
109+
use.getKind() == UnsafeUse::UnsafeConformance) {
109110
auto [enclosingDecl, _] = enclosingContextForUnsafe(
110111
use.getLocation(), use.getDeclContext());
111112
if (enclosingDecl) {
@@ -137,15 +138,15 @@ void swift::diagnoseUnsafeUse(const UnsafeUse &use, bool asNote) {
137138
witness->diagnose(diag::witness_unsafe,
138139
witness->getDescriptiveKind(),
139140
witness->getName());
140-
suggestUnsafeMarkerOnConformance(use.getConformance());
141+
suggestUnsafeMarkerOnConformance(use.getConformance().getConcrete());
141142
return;
142143
}
143144

144145
case UnsafeUse::TypeWitness: {
145146
auto assocType = use.getAssociatedType();
146147
auto loc = use.getLocation();
147148
auto type = use.getType();
148-
auto conformance = use.getConformance();
149+
auto conformance = use.getConformance().getConcrete();
149150
ASTContext &ctx = assocType->getASTContext();
150151

151152
diagnoseUnsafeType(ctx, loc, type, conformance->getDeclContext(),
@@ -161,10 +162,13 @@ void swift::diagnoseUnsafeUse(const UnsafeUse &use, bool asNote) {
161162

162163
case UnsafeUse::UnsafeConformance: {
163164
auto conformance = use.getConformance();
164-
ASTContext &ctx = conformance->getProtocol()->getASTContext();
165+
ASTContext &ctx = conformance.getRequirement()->getASTContext();
165166
ctx.Diags.diagnose(
166-
use.getLocation(), diag::unchecked_conformance_is_unsafe);
167-
suggestUnsafeMarkerOnConformance(conformance);
167+
use.getLocation(),
168+
asNote ? diag::note_use_of_unchecked_conformance_is_unsafe
169+
: diag::use_of_unchecked_conformance_is_unsafe,
170+
use.getType(),
171+
conformance.getRequirement());
168172
return;
169173
}
170174

test/Unsafe/unsafe_concurrency.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
// REQUIRES: swift_feature_StrictConcurrency
55
// REQUIRES: swift_feature_WarnUnsafe
66

7-
// expected-warning@+2{{@unchecked conformance involves unsafe code}}
8-
// expected-note@+1{{make the enclosing class @unsafe to allow unsafe conformance to protocol 'Sendable'}}{{1-1=@unsafe }}
7+
// expected-note@+2{{@unchecked conformance of 'C' to protocol 'Sendable' involves unsafe code}}
8+
// expected-warning@+1{{class 'C' involves unsafe code; use '@unsafe' to indicate that its use is not memory-safe}}{{1-1=@unsafe }}
99
class C: @unchecked Sendable {
1010
var counter: Int = 0
1111
}

0 commit comments

Comments
 (0)