@@ -2446,16 +2446,53 @@ static bool usesFeatureAsyncAwait(Decl *decl) {
2446
2446
}
2447
2447
2448
2448
static bool usesFeatureMarkerProtocol (Decl *decl) {
2449
+ // Check an inheritance clause for a marker protocol.
2450
+ auto checkInherited = [&](ArrayRef<TypeLoc> inherited) -> bool {
2451
+ for (const auto &inheritedEntry : inherited) {
2452
+ if (auto inheritedType = inheritedEntry.getType ()) {
2453
+ if (inheritedType->isExistentialType ()) {
2454
+ auto layout = inheritedType->getExistentialLayout ();
2455
+ for (ProtocolType *protoTy : layout.getProtocols ()) {
2456
+ if (protoTy->getDecl ()->isMarkerProtocol ())
2457
+ return true ;
2458
+ }
2459
+ }
2460
+ }
2461
+ }
2462
+
2463
+ return false ;
2464
+ };
2465
+
2466
+ // Check generic requirements for a marker protocol.
2467
+ auto checkRequirements = [&](ArrayRef<Requirement> requirements) -> bool {
2468
+ for (const auto &req: requirements) {
2469
+ if (req.getKind () == RequirementKind::Conformance &&
2470
+ req.getSecondType ()->castTo <ProtocolType>()->getDecl ()
2471
+ ->isMarkerProtocol ())
2472
+ return true ;
2473
+ }
2474
+
2475
+ return false ;
2476
+ };
2477
+
2449
2478
if (auto proto = dyn_cast<ProtocolDecl>(decl)) {
2450
2479
if (proto->isMarkerProtocol ())
2451
2480
return true ;
2481
+
2482
+ if (checkInherited (proto->getInherited ()))
2483
+ return true ;
2484
+
2485
+ if (checkRequirements (proto->getRequirementSignature ()))
2486
+ return true ;
2452
2487
}
2453
2488
2454
2489
if (auto ext = dyn_cast<ExtensionDecl>(decl)) {
2455
- if (auto proto = ext->getSelfProtocolDecl ())
2456
- if (proto->isMarkerProtocol ())
2457
- return true ;
2458
- }
2490
+ if (checkRequirements (ext->getGenericRequirements ()))
2491
+ return true ;
2492
+
2493
+ if (checkInherited (ext->getInherited ()))
2494
+ return true ;
2495
+ }
2459
2496
2460
2497
return false ;
2461
2498
}
@@ -2524,15 +2561,40 @@ static bool usesFeatureRethrowsProtocol(
2524
2561
if (!checked.insert (decl).second )
2525
2562
return false ;
2526
2563
2564
+ // Check an inheritance clause for a marker protocol.
2565
+ auto checkInherited = [&](ArrayRef<TypeLoc> inherited) -> bool {
2566
+ for (const auto &inheritedEntry : inherited) {
2567
+ if (auto inheritedType = inheritedEntry.getType ()) {
2568
+ if (inheritedType->isExistentialType ()) {
2569
+ auto layout = inheritedType->getExistentialLayout ();
2570
+ for (ProtocolType *protoTy : layout.getProtocols ()) {
2571
+ if (usesFeatureRethrowsProtocol (protoTy->getDecl (), checked))
2572
+ return true ;
2573
+ }
2574
+ }
2575
+ }
2576
+ }
2577
+
2578
+ return false ;
2579
+ };
2580
+
2581
+ if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
2582
+ if (checkInherited (nominal->getInherited ()))
2583
+ return true ;
2584
+ }
2585
+
2527
2586
if (auto proto = dyn_cast<ProtocolDecl>(decl)) {
2528
2587
if (proto->getAttrs ().hasAttribute <AtRethrowsAttr>())
2529
2588
return true ;
2530
2589
}
2531
2590
2532
2591
if (auto ext = dyn_cast<ExtensionDecl>(decl)) {
2533
- if (auto proto = ext->getSelfProtocolDecl ())
2534
- if (usesFeatureRethrowsProtocol (proto , checked))
2592
+ if (auto nominal = ext->getSelfNominalTypeDecl ())
2593
+ if (usesFeatureRethrowsProtocol (nominal , checked))
2535
2594
return true ;
2595
+
2596
+ if (checkInherited (ext->getInherited ()))
2597
+ return true ;
2536
2598
}
2537
2599
2538
2600
if (auto genericSig = decl->getInnermostDeclContext ()
@@ -2635,15 +2697,30 @@ static std::vector<Feature> getUniqueFeaturesUsed(Decl *decl) {
2635
2697
if (features.empty ())
2636
2698
return features;
2637
2699
2638
- Decl *enclosingDecl;
2639
- if (auto accessor = dyn_cast<AccessorDecl>(decl))
2640
- enclosingDecl = accessor->getStorage ();
2641
- else
2642
- enclosingDecl = decl->getDeclContext ()->getAsDecl ();
2643
- if (!enclosingDecl)
2644
- return features;
2700
+ // Gather the features used by all enclosing declarations.
2701
+ Decl *enclosingDecl = decl;
2702
+ std::vector<Feature> enclosingFeatures;
2703
+ while (true ) {
2704
+ // Find the next outermost enclosing declaration.
2705
+ if (auto accessor = dyn_cast<AccessorDecl>(enclosingDecl))
2706
+ enclosingDecl = accessor->getStorage ();
2707
+ else
2708
+ enclosingDecl = enclosingDecl->getDeclContext ()->getAsDecl ();
2709
+ if (!enclosingDecl)
2710
+ break ;
2711
+
2712
+ auto outerEnclosingFeatures = getFeaturesUsed (enclosingDecl);
2713
+ if (outerEnclosingFeatures.empty ())
2714
+ continue ;
2715
+
2716
+ auto currentEnclosingFeatures = std::move (enclosingFeatures);
2717
+ enclosingFeatures.clear ();
2718
+ std::merge (outerEnclosingFeatures.begin (), outerEnclosingFeatures.end (),
2719
+ currentEnclosingFeatures.begin (), currentEnclosingFeatures.end (),
2720
+ std::back_inserter (enclosingFeatures));
2721
+ }
2645
2722
2646
- auto enclosingFeatures = getFeaturesUsed (enclosingDecl);
2723
+ // If there were no enclosing features, we're done.
2647
2724
if (enclosingFeatures.empty ())
2648
2725
return features;
2649
2726
0 commit comments