@@ -2670,25 +2670,42 @@ RequiresOpaqueAccessorsRequest::evaluate(Evaluator &evaluator,
26702670// /
26712671// / The underscored accessor could, however, still be required for ABI
26722672// / 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 ();
26762677 assert (ctx.LangOpts .hasFeature (Feature::CoroutineAccessors));
26772678 assert (kind == AccessorKind::Modify2 || kind == AccessorKind::Read2);
26782679
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+
26792697 // Non-stable modules have no ABI to keep stable.
2680- if (getModuleContext ()->getResilienceStrategy () !=
2698+ if (storage-> getModuleContext ()->getResilienceStrategy () !=
26812699 ResilienceStrategy::Resilient)
26822700 return false ;
26832701
26842702 // Non-exported storage has no ABI to keep stable.
2685- if (!isExported (this ))
2703+ if (!isExported (storage ))
26862704 return false ;
26872705
26882706 // The non-underscored accessor is not present, the underscored accessor
26892707 // 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);
26922709 if (!accessor)
26932710 return false ;
26942711
@@ -2699,17 +2716,43 @@ bool AbstractStorageDecl::requiresCorrespondingUnderscoredCoroutineAccessor(
26992716 if (!ctx.supportsVersionedAvailability ())
27002717 return true ;
27012718
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+ }();
27032738 auto featureAvailability = ctx.getCoroutineAccessorsAvailability ();
27042739 // If accessor was introduced only after the feature was, there's no old ABI
27052740 // to maintain.
2706- if (modifyAvailability.getPlatformRange ().isContainedIn (featureAvailability))
2741+ if (accessorAvailability.getPlatformRange ().isContainedIn (
2742+ featureAvailability))
27072743 return false ;
27082744
27092745 // The underscored accessor is required for ABI stability.
27102746 return true ;
27112747}
27122748
2749+ bool AbstractStorageDecl::requiresCorrespondingUnderscoredCoroutineAccessor (
2750+ AccessorKind kind, AccessorDecl const *decl) const {
2751+ return requiresCorrespondingUnderscoredCoroutineAccessorImpl (
2752+ this , kind, decl,
2753+ /* derived=*/ this );
2754+ }
2755+
27132756bool RequiresOpaqueModifyCoroutineRequest::evaluate (
27142757 Evaluator &evaluator, AbstractStorageDecl *storage,
27152758 bool isUnderscored) const {
0 commit comments