@@ -2670,25 +2670,42 @@ RequiresOpaqueAccessorsRequest::evaluate(Evaluator &evaluator,
2670
2670
// /
2671
2671
// / The underscored accessor could, however, still be required for ABI
2672
2672
// / stability.
2673
- bool AbstractStorageDecl::requiresCorrespondingUnderscoredCoroutineAccessor (
2674
- AccessorKind kind, AccessorDecl const *decl) const {
2675
- auto &ctx = getASTContext ();
2673
+ static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl (
2674
+ AbstractStorageDecl const *storage, AccessorKind kind,
2675
+ AccessorDecl const *decl, AbstractStorageDecl const *derived) {
2676
+ auto &ctx = storage->getASTContext ();
2676
2677
assert (ctx.LangOpts .hasFeature (Feature::CoroutineAccessors));
2677
2678
assert (kind == AccessorKind::Modify2 || kind == AccessorKind::Read2);
2678
2679
2680
+ // If any overridden decl requires the underscored version, then this decl
2681
+ // does too. Otherwise dispatch to the underscored version on a value
2682
+ // statically the super but dynamically this subtype would not dispatch to an
2683
+ // override of the underscored version but rather (incorrectly) the
2684
+ // supertype's implementation.
2685
+ if (storage == derived) {
2686
+ auto *current = storage;
2687
+ while ((current = current->getOverriddenDecl ())) {
2688
+ auto *currentDecl = cast_or_null<AccessorDecl>(
2689
+ decl ? decl->getOverriddenDecl () : nullptr );
2690
+ if (requiresCorrespondingUnderscoredCoroutineAccessorImpl (
2691
+ current, kind, currentDecl, derived)) {
2692
+ return true ;
2693
+ }
2694
+ }
2695
+ }
2696
+
2679
2697
// Non-stable modules have no ABI to keep stable.
2680
- if (getModuleContext ()->getResilienceStrategy () !=
2698
+ if (storage-> getModuleContext ()->getResilienceStrategy () !=
2681
2699
ResilienceStrategy::Resilient)
2682
2700
return false ;
2683
2701
2684
2702
// Non-exported storage has no ABI to keep stable.
2685
- if (!isExported (this ))
2703
+ if (!isExported (storage ))
2686
2704
return false ;
2687
2705
2688
2706
// The non-underscored accessor is not present, the underscored accessor
2689
2707
// won't be either.
2690
- // TODO: CoroutineAccessors: What if only the underscored is written out?
2691
- auto *accessor = decl ? decl : getOpaqueAccessor (kind);
2708
+ auto *accessor = decl ? decl : storage->getOpaqueAccessor (kind);
2692
2709
if (!accessor)
2693
2710
return false ;
2694
2711
@@ -2699,17 +2716,43 @@ bool AbstractStorageDecl::requiresCorrespondingUnderscoredCoroutineAccessor(
2699
2716
if (!ctx.supportsVersionedAvailability ())
2700
2717
return true ;
2701
2718
2702
- auto modifyAvailability = AvailabilityContext::forLocation ({}, accessor);
2719
+ AvailabilityContext accessorAvailability = [&] {
2720
+ if (storage->getModuleContext ()->isMainModule ()) {
2721
+ return AvailabilityContext::forDeclSignature (accessor);
2722
+ }
2723
+ // Calculate the availability of the imported declaration ourselves starting
2724
+ // from always available and constraining by walking the enclosing decl
2725
+ // contexts.
2726
+ auto retval = AvailabilityContext::forAlwaysAvailable (ctx);
2727
+ auto declContext = storage->getInnermostDeclContext ();
2728
+ while (declContext) {
2729
+ const Decl *decl = declContext->getInnermostDeclarationDeclContext ();
2730
+ if (!decl)
2731
+ break ;
2732
+
2733
+ retval.constrainWithDecl (decl);
2734
+ declContext = decl->getDeclContext ();
2735
+ }
2736
+ return retval;
2737
+ }();
2703
2738
auto featureAvailability = ctx.getCoroutineAccessorsAvailability ();
2704
2739
// If accessor was introduced only after the feature was, there's no old ABI
2705
2740
// to maintain.
2706
- if (modifyAvailability.getPlatformRange ().isContainedIn (featureAvailability))
2741
+ if (accessorAvailability.getPlatformRange ().isContainedIn (
2742
+ featureAvailability))
2707
2743
return false ;
2708
2744
2709
2745
// The underscored accessor is required for ABI stability.
2710
2746
return true ;
2711
2747
}
2712
2748
2749
+ bool AbstractStorageDecl::requiresCorrespondingUnderscoredCoroutineAccessor (
2750
+ AccessorKind kind, AccessorDecl const *decl) const {
2751
+ return requiresCorrespondingUnderscoredCoroutineAccessorImpl (
2752
+ this , kind, decl,
2753
+ /* derived=*/ this );
2754
+ }
2755
+
2713
2756
bool RequiresOpaqueModifyCoroutineRequest::evaluate (
2714
2757
Evaluator &evaluator, AbstractStorageDecl *storage,
2715
2758
bool isUnderscored) const {
0 commit comments