@@ -2672,11 +2672,28 @@ RequiresOpaqueAccessorsRequest::evaluate(Evaluator &evaluator,
2672
2672
// / stability.
2673
2673
static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl (
2674
2674
AbstractStorageDecl const *storage, AccessorKind kind,
2675
- AccessorDecl const *decl) {
2675
+ AccessorDecl const *decl, AbstractStorageDecl const *derived ) {
2676
2676
auto &ctx = storage->getASTContext ();
2677
2677
assert (ctx.LangOpts .hasFeature (Feature::CoroutineAccessors));
2678
2678
assert (kind == AccessorKind::Modify2 || kind == AccessorKind::Read2);
2679
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
+
2680
2697
// Non-stable modules have no ABI to keep stable.
2681
2698
if (storage->getModuleContext ()->getResilienceStrategy () !=
2682
2699
ResilienceStrategy::Resilient)
@@ -2699,11 +2716,30 @@ static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl(
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.
@@ -2712,8 +2748,9 @@ static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl(
2712
2748
2713
2749
bool AbstractStorageDecl::requiresCorrespondingUnderscoredCoroutineAccessor (
2714
2750
AccessorKind kind, AccessorDecl const *decl) const {
2715
- return requiresCorrespondingUnderscoredCoroutineAccessorImpl (this , kind,
2716
- decl);
2751
+ return requiresCorrespondingUnderscoredCoroutineAccessorImpl (
2752
+ this , kind, decl,
2753
+ /* derived=*/ this );
2717
2754
}
2718
2755
2719
2756
bool RequiresOpaqueModifyCoroutineRequest::evaluate (
0 commit comments