Skip to content

Commit d9e4184

Browse files
committed
Make Error and CodingKey conform to ConcurrentValue.
Make both Error and CodingKey conform to ConcurrentValue, so that thrown errors always conform to ConcurrentValue. Downgrade (to warnings) and ConcurrentValue-related diagnostics that are triggered by this change in existing Error and CodingKey-conforming types to reduce the impact on source compatibility.
1 parent 87ac6ce commit d9e4184

File tree

12 files changed

+79
-24
lines changed

12 files changed

+79
-24
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 23 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 "
@@ -5624,6 +5642,10 @@ ERROR(marker_protocol_inherit_nonmarker, none,
56245642
(DeclName, DeclName))
56255643
ERROR(marker_protocol_cast,none,
56265644
"marker protocol %0 cannot be used in a conditional cast", (DeclName))
5645+
ERROR(marker_protocol_conditional_conformance,none,
5646+
"conditional conformance to non-marker protocol %0 cannot depend on "
5647+
"conformance of %1 to non-marker protocol %2",
5648+
(Identifier, Type, Identifier))
56275649

56285650
//------------------------------------------------------------------------------
56295651
// MARK: differentiable programming diagnostics

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)