Skip to content

Commit 5f6a074

Browse files
authored
Merge pull request #36070 from DougGregor/concurrentvalue-error-codingkey
Make Error and CodingKey conform to ConcurrentValue.
2 parents a3671e6 + d9e4184 commit 5f6a074

File tree

12 files changed

+75
-24
lines changed

12 files changed

+75
-24
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4320,20 +4320,38 @@ ERROR(non_concurrent_type_member,none,
43204320
"%select{stored property %1|associated value %1}0 of "
43214321
"'ConcurrentValue'-conforming %2 %3 has non-concurrent-value type %4",
43224322
(bool, DeclName, DescriptiveDeclKind, DeclName, Type))
4323+
WARNING(non_concurrent_type_member_warn,none,
4324+
"%select{stored property %1|associated value %1}0 of "
4325+
"'ConcurrentValue'-conforming %2 %3 has non-concurrent-value type %4",
4326+
(bool, DeclName, DescriptiveDeclKind, DeclName, Type))
43234327
ERROR(concurrent_value_class_mutable_property,none,
43244328
"stored property %0 of 'ConcurrentValue'-conforming %1 %2 is mutable",
43254329
(DeclName, DescriptiveDeclKind, DeclName))
4330+
WARNING(concurrent_value_class_mutable_property_warn,none,
4331+
"stored property %0 of 'ConcurrentValue'-conforming %1 %2 is mutable",
4332+
(DeclName, DescriptiveDeclKind, DeclName))
43264333
ERROR(concurrent_value_outside_source_file,none,
4327-
"conformance 'ConcurrentValue' must occur in the same source file as "
4334+
"conformance to 'ConcurrentValue' must occur in the same source file as "
4335+
"%0 %1; use 'UnsafeConcurrentValue' for retroactive conformance",
4336+
(DescriptiveDeclKind, DeclName))
4337+
WARNING(concurrent_value_outside_source_file_warn,none,
4338+
"conformance to 'ConcurrentValue' must occur in the same source file as "
43284339
"%0 %1; use 'UnsafeConcurrentValue' for retroactive conformance",
43294340
(DescriptiveDeclKind, DeclName))
43304341
ERROR(concurrent_value_open_class,none,
43314342
"open class %0 cannot conform to `ConcurrentValue`; "
43324343
"use `UnsafeConcurrentValue`", (DeclName))
4344+
WARNING(concurrent_value_open_class_warn,none,
4345+
"open class %0 cannot conform to `ConcurrentValue`; "
4346+
"use `UnsafeConcurrentValue`", (DeclName))
43334347
ERROR(concurrent_value_inherit,none,
43344348
"`ConcurrentValue` class %1 cannot inherit from another class"
43354349
"%select{| other than 'NSObject'}0",
43364350
(bool, DeclName))
4351+
WARNING(concurrent_value_inherit_warn,none,
4352+
"`ConcurrentValue` class %1 cannot inherit from another class"
4353+
"%select{| other than 'NSObject'}0",
4354+
(bool, DeclName))
43374355

43384356
ERROR(actorindependent_let,none,
43394357
"'@actorIndependent' is meaningless on 'let' declarations because "

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2308,7 +2308,8 @@ static bool shouldDiagnoseExistingDataRaces(const DeclContext *dc) {
23082308
return false;
23092309
}
23102310

2311-
void swift::checkConcurrentValueConformance(ProtocolConformance *conformance) {
2311+
void swift::checkConcurrentValueConformance(
2312+
ProtocolConformance *conformance, bool asWarning) {
23122313
auto conformanceDC = conformance->getDeclContext();
23132314
auto nominal = conformance->getType()->getAnyNominal();
23142315
if (!nominal)
@@ -2326,7 +2327,9 @@ void swift::checkConcurrentValueConformance(ProtocolConformance *conformance) {
23262327
if (!conformanceDC->getParentSourceFile() ||
23272328
conformanceDC->getParentSourceFile() != nominal->getParentSourceFile()) {
23282329
conformanceDecl->diagnose(
2329-
diag::concurrent_value_outside_source_file,
2330+
asWarning
2331+
? diag::concurrent_value_outside_source_file_warn
2332+
: diag::concurrent_value_outside_source_file,
23302333
nominal->getDescriptiveKind(), nominal->getName());
23312334
return;
23322335
}
@@ -2335,8 +2338,11 @@ void swift::checkConcurrentValueConformance(ProtocolConformance *conformance) {
23352338
// An open class cannot conform to `ConcurrentValue`.
23362339
if (classDecl->getFormalAccess() == AccessLevel::Open) {
23372340
classDecl->diagnose(
2338-
diag::concurrent_value_open_class, classDecl->getName());
2339-
return;
2341+
asWarning ? diag::concurrent_value_open_class_warn
2342+
: diag::concurrent_value_open_class,
2343+
classDecl->getName());
2344+
if (!asWarning)
2345+
return;
23402346
}
23412347

23422348
// A 'ConcurrentValue' class cannot inherit from another class, although
@@ -2345,10 +2351,12 @@ void swift::checkConcurrentValueConformance(ProtocolConformance *conformance) {
23452351
if (auto superclassDecl = classDecl->getSuperclassDecl()) {
23462352
if (!superclassDecl->isNSObject()) {
23472353
classDecl->diagnose(
2348-
diag::concurrent_value_inherit,
2354+
asWarning ? diag::concurrent_value_inherit_warn
2355+
: diag::concurrent_value_inherit,
23492356
nominal->getASTContext().LangOpts.EnableObjCInterop,
23502357
classDecl->getName());
2351-
return;
2358+
if (!asWarning)
2359+
return;
23522360
}
23532361
}
23542362
}
@@ -2359,7 +2367,10 @@ void swift::checkConcurrentValueConformance(ProtocolConformance *conformance) {
23592367
if (isa<StructDecl>(nominal) || classDecl) {
23602368
for (auto property : nominal->getStoredProperties()) {
23612369
if (classDecl && property->supportsMutation()) {
2362-
property->diagnose(diag::concurrent_value_class_mutable_property, property->getName(), nominal->getDescriptiveKind(),
2370+
property->diagnose(
2371+
asWarning ? diag::concurrent_value_class_mutable_property_warn
2372+
: diag::concurrent_value_class_mutable_property,
2373+
property->getName(), nominal->getDescriptiveKind(),
23632374
nominal->getName());
23642375
continue;
23652376
}
@@ -2368,7 +2379,9 @@ void swift::checkConcurrentValueConformance(ProtocolConformance *conformance) {
23682379
conformanceDC->mapTypeIntoContext(property->getInterfaceType());
23692380
if (!isConcurrentValueType(conformanceDC, propertyType)) {
23702381
property->diagnose(
2371-
diag::non_concurrent_type_member, false, property->getName(),
2382+
asWarning ? diag::non_concurrent_type_member_warn
2383+
: diag::non_concurrent_type_member,
2384+
false, property->getName(),
23722385
nominal->getDescriptiveKind(), nominal->getName(), propertyType);
23732386
continue;
23742387
}
@@ -2389,7 +2402,9 @@ void swift::checkConcurrentValueConformance(ProtocolConformance *conformance) {
23892402
element->getArgumentInterfaceType());
23902403
if (!isConcurrentValueType(conformanceDC, elementType)) {
23912404
element->diagnose(
2392-
diag::non_concurrent_type_member, true, element->getName(),
2405+
asWarning ? diag::non_concurrent_type_member_warn
2406+
: diag::non_concurrent_type_member,
2407+
true, element->getName(),
23932408
nominal->getDescriptiveKind(), nominal->getName(), elementType);
23942409
continue;
23952410
}

lib/Sema/TypeCheckConcurrency.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ bool diagnoseNonConcurrentTypesInReference(
238238
ConcurrentReferenceKind refKind);
239239

240240
/// Check the correctness of the given ConcurrentValue conformance.
241-
void checkConcurrentValueConformance(ProtocolConformance *conformance);
241+
void checkConcurrentValueConformance(
242+
ProtocolConformance *conformance, bool asWarning);
242243

243244
} // end namespace swift
244245

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5660,6 +5660,8 @@ void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) {
56605660

56615661
ProtocolConformance *concurrentValueConformance = nullptr;
56625662
ProtocolConformance *unsafeConcurrentValueConformance = nullptr;
5663+
ProtocolConformance *errorConformance = nullptr;
5664+
ProtocolConformance *codingKeyConformance = nullptr;
56635665
bool anyInvalid = false;
56645666
for (auto conformance : conformances) {
56655667
// Check and record normal conformances.
@@ -5691,12 +5693,18 @@ void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) {
56915693
} else if (proto->isSpecificProtocol(
56925694
KnownProtocolKind::UnsafeConcurrentValue)) {
56935695
unsafeConcurrentValueConformance = conformance;
5696+
} else if (proto->isSpecificProtocol(KnownProtocolKind::Error)) {
5697+
errorConformance = conformance;
5698+
} else if (proto->isSpecificProtocol(KnownProtocolKind::CodingKey)) {
5699+
codingKeyConformance = conformance;
56945700
}
56955701
}
56965702

56975703
// Check constraints of ConcurrentValue.
5698-
if (concurrentValueConformance && !unsafeConcurrentValueConformance)
5699-
checkConcurrentValueConformance(concurrentValueConformance);
5704+
if (concurrentValueConformance && !unsafeConcurrentValueConformance) {
5705+
bool asWarning = errorConformance || codingKeyConformance;
5706+
checkConcurrentValueConformance(concurrentValueConformance, asWarning);
5707+
}
57005708

57015709
// Check all conformances.
57025710
groupChecker.checkAllConformances();

stdlib/public/core/Codable.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ public typealias Codable = Encodable & Decodable
5151
//===----------------------------------------------------------------------===//
5252

5353
/// A type that can be used as a key for encoding and decoding.
54-
public protocol CodingKey: CustomStringConvertible,
54+
public protocol CodingKey: ConcurrentValue,
55+
CustomStringConvertible,
5556
CustomDebugStringConvertible {
5657
/// The string to use in a named collection (e.g. a string-keyed dictionary).
5758
var stringValue: String { get }
@@ -3179,7 +3180,7 @@ public struct CodingUserInfoKey: RawRepresentable, Equatable, Hashable, Concurre
31793180
/// An error that occurs during the encoding of a value.
31803181
public enum EncodingError: Error {
31813182
/// The context in which the error occurred.
3182-
public struct Context {
3183+
public struct Context: ConcurrentValue {
31833184
/// The path of coding keys taken to get to the point of the failing encode
31843185
/// call.
31853186
public let codingPath: [CodingKey]
@@ -3262,7 +3263,7 @@ public enum EncodingError: Error {
32623263
/// An error that occurs during the decoding of a value.
32633264
public enum DecodingError: Error {
32643265
/// The context in which the error occurred.
3265-
public struct Context {
3266+
public struct Context: ConcurrentValue {
32663267
/// The path of coding keys taken to get to the point of the failing decode
32673268
/// call.
32683269
public let codingPath: [CodingKey]

stdlib/public/core/ErrorType.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ import SwiftShims
110110
/// print("Other error: \(error)")
111111
/// }
112112
/// // Prints "Parsing error: mismatchedTag [19:5]"
113-
public protocol Error {
113+
public protocol Error: ConcurrentValue {
114114
var _domain: String { get }
115115
var _code: Int { get }
116116

test/Inputs/clang-importer-sdk/swift-modules/Foundation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ public struct URL : _ObjectiveCBridgeable {
221221
}
222222
}
223223

224-
extension NSError : Error {
224+
extension NSError : Error, UnsafeConcurrentValue {
225225
public var _domain: String { return domain }
226226
public var _code: Int { return code }
227227
}

test/SILGen/errors.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ class Cat {}
77
enum HomeworkError : Error {
88
case TooHard
99
case TooMuch
10-
case CatAteIt(Cat)
11-
case CatHidIt(Cat)
10+
case CatAteIt(Cat) // expected-warning{{associated value 'CatAteIt' of 'ConcurrentValue'-conforming enum 'HomeworkError' has non-concurrent-value type 'Cat'}}
11+
case CatHidIt(Cat) // expected-warning{{associated value 'CatHidIt' of 'ConcurrentValue'-conforming enum 'HomeworkError' has non-concurrent-value type 'Cat'}}
1212
}
1313

1414
func someValidPointer<T>() -> UnsafePointer<T> { fatalError() }

test/Sema/existential_nested_type.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ protocol HasAssoc {
1010
}
1111

1212
enum MyError : Error {
13-
case bad(Any)
13+
case bad(Any) // expected-warning{{associated value 'bad' of 'ConcurrentValue'-conforming enum 'MyError' has non-concurrent-value type 'Any'}}
1414
}
1515

1616
func checkIt(_ js: Any) throws {
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Protocol CodingKey has added inherited protocol ConcurrentValue
2+
Protocol CodingKey has generic signature change from <Self : Swift.CustomDebugStringConvertible, Self : Swift.CustomStringConvertible> to <Self : Swift.ConcurrentValue, Self : Swift.CustomDebugStringConvertible, Self : Swift.CustomStringConvertible>
3+
Protocol Error has added inherited protocol ConcurrentValue
4+
Protocol Error has generic signature change from to <Self : Swift.ConcurrentValue>

test/api-digester/stability-stdlib-abi-with-asserts.test

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,8 @@ Func _measureRuntimeFunctionCountersDiffs(objects:_:) is a new API without @avai
4343
Protocol _RuntimeFunctionCountersStats is a new API without @available attribute
4444
Struct _GlobalRuntimeFunctionCountersState is a new API without @available attribute
4545
Struct _ObjectRuntimeFunctionCountersState is a new API without @available attribute
46+
Protocol CodingKey has added inherited protocol ConcurrentValue
47+
Protocol CodingKey has generic signature change from <Self : Swift.CustomDebugStringConvertible, Self : Swift.CustomStringConvertible> to <Self : Swift.ConcurrentValue, Self : Swift.CustomDebugStringConvertible, Self : Swift.CustomStringConvertible>
48+
Protocol Error has added inherited protocol ConcurrentValue
49+
Protocol Error has generic signature change from to <Self : Swift.ConcurrentValue>
4650
Struct _RuntimeFunctionCounters is a new API without @available attribute
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
extension NoRawTypeKey : CodingKey {}
2-
extension StringKey : CodingKey {}
3-
extension IntKey : CodingKey {}
1+
extension NoRawTypeKey : CodingKey, UnsafeConcurrentValue {}
2+
extension StringKey : CodingKey, UnsafeConcurrentValue {}
3+
extension IntKey : CodingKey, UnsafeConcurrentValue {}

0 commit comments

Comments
 (0)