@@ -2356,6 +2356,68 @@ static bool shouldDiagnoseExistingDataRaces(const DeclContext *dc) {
2356
2356
return false ;
2357
2357
}
2358
2358
2359
+ // / Check the instance storage of the given nominal type to verify whether
2360
+ // / it is comprised only of ConcurrentValue instance storage.
2361
+ static bool checkConcurrentValueInstanceStorage (
2362
+ NominalTypeDecl *nominal, DeclContext *dc, ConcurrentValueCheck check) {
2363
+ // Stored properties of structs and classes must have
2364
+ // ConcurrentValue-conforming types.
2365
+ bool asWarning = (check == ConcurrentValueCheck::ImpliedByStandardProtocol);
2366
+ bool invalid = false ;
2367
+ if (isa<StructDecl>(nominal) || isa<ClassDecl>(nominal)) {
2368
+ auto classDecl = dyn_cast<ClassDecl>(nominal);
2369
+ for (auto property : nominal->getStoredProperties ()) {
2370
+ if (classDecl && property->supportsMutation ()) {
2371
+ property->diagnose (
2372
+ asWarning ? diag::concurrent_value_class_mutable_property_warn
2373
+ : diag::concurrent_value_class_mutable_property,
2374
+ property->getName (), nominal->getDescriptiveKind (),
2375
+ nominal->getName ());
2376
+ invalid = true ;
2377
+ continue ;
2378
+ }
2379
+
2380
+ auto propertyType = dc->mapTypeIntoContext (property->getInterfaceType ());
2381
+ if (!isConcurrentValueType (dc, propertyType)) {
2382
+ property->diagnose (
2383
+ asWarning ? diag::non_concurrent_type_member_warn
2384
+ : diag::non_concurrent_type_member,
2385
+ false , property->getName (),
2386
+ nominal->getDescriptiveKind (), nominal->getName (), propertyType);
2387
+ invalid = true ;
2388
+ continue ;
2389
+ }
2390
+ }
2391
+
2392
+ return invalid;
2393
+ }
2394
+
2395
+ // Associated values of enum cases must have ConcurrentValue-conforming
2396
+ // types.
2397
+ if (auto enumDecl = dyn_cast<EnumDecl>(nominal)) {
2398
+ for (auto caseDecl : enumDecl->getAllCases ()) {
2399
+ for (auto element : caseDecl->getElements ()) {
2400
+ if (!element->hasAssociatedValues ())
2401
+ continue ;
2402
+
2403
+ auto elementType = dc->mapTypeIntoContext (
2404
+ element->getArgumentInterfaceType ());
2405
+ if (!isConcurrentValueType (dc, elementType)) {
2406
+ element->diagnose (
2407
+ asWarning ? diag::non_concurrent_type_member_warn
2408
+ : diag::non_concurrent_type_member,
2409
+ true , element->getName (),
2410
+ nominal->getDescriptiveKind (), nominal->getName (), elementType);
2411
+ invalid = true ;
2412
+ continue ;
2413
+ }
2414
+ }
2415
+ }
2416
+ }
2417
+
2418
+ return invalid;
2419
+ }
2420
+
2359
2421
bool swift::checkConcurrentValueConformance (
2360
2422
ProtocolConformance *conformance, ConcurrentValueCheck check) {
2361
2423
auto conformanceDC = conformance->getDeclContext ();
@@ -2415,59 +2477,5 @@ bool swift::checkConcurrentValueConformance(
2415
2477
}
2416
2478
}
2417
2479
2418
- // Stored properties of structs and classes must have
2419
- // ConcurrentValue-conforming types.
2420
- bool invalid = false ;
2421
- if (isa<StructDecl>(nominal) || classDecl) {
2422
- for (auto property : nominal->getStoredProperties ()) {
2423
- if (classDecl && property->supportsMutation ()) {
2424
- property->diagnose (
2425
- asWarning ? diag::concurrent_value_class_mutable_property_warn
2426
- : diag::concurrent_value_class_mutable_property,
2427
- property->getName (), nominal->getDescriptiveKind (),
2428
- nominal->getName ());
2429
- invalid = true ;
2430
- continue ;
2431
- }
2432
-
2433
- auto propertyType =
2434
- conformanceDC->mapTypeIntoContext (property->getInterfaceType ());
2435
- if (!isConcurrentValueType (conformanceDC, propertyType)) {
2436
- property->diagnose (
2437
- asWarning ? diag::non_concurrent_type_member_warn
2438
- : diag::non_concurrent_type_member,
2439
- false , property->getName (),
2440
- nominal->getDescriptiveKind (), nominal->getName (), propertyType);
2441
- invalid = true ;
2442
- continue ;
2443
- }
2444
- }
2445
-
2446
- return invalid;
2447
- }
2448
-
2449
- // Associated values of enum cases must have ConcurrentValue-conforming
2450
- // types.
2451
- if (auto enumDecl = dyn_cast<EnumDecl>(nominal)) {
2452
- for (auto caseDecl : enumDecl->getAllCases ()) {
2453
- for (auto element : caseDecl->getElements ()) {
2454
- if (!element->hasAssociatedValues ())
2455
- continue ;
2456
-
2457
- auto elementType = conformanceDC->mapTypeIntoContext (
2458
- element->getArgumentInterfaceType ());
2459
- if (!isConcurrentValueType (conformanceDC, elementType)) {
2460
- element->diagnose (
2461
- asWarning ? diag::non_concurrent_type_member_warn
2462
- : diag::non_concurrent_type_member,
2463
- true , element->getName (),
2464
- nominal->getDescriptiveKind (), nominal->getName (), elementType);
2465
- invalid = true ;
2466
- continue ;
2467
- }
2468
- }
2469
- }
2470
- }
2471
-
2472
- return invalid;
2480
+ return checkConcurrentValueInstanceStorage (nominal, conformanceDC, check);
2473
2481
}
0 commit comments