@@ -2672,11 +2672,28 @@ RequiresOpaqueAccessorsRequest::evaluate(Evaluator &evaluator,
26722672// / stability.
26732673static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl (
26742674 AbstractStorageDecl const *storage, AccessorKind kind,
2675- AccessorDecl const *decl) {
2675+ AccessorDecl const *decl, AbstractStorageDecl const *derived ) {
26762676 auto &ctx = storage->getASTContext ();
26772677 assert (ctx.LangOpts .hasFeature (Feature::CoroutineAccessors));
26782678 assert (kind == AccessorKind::Modify2 || kind == AccessorKind::Read2);
26792679
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+
26802697 // Non-stable modules have no ABI to keep stable.
26812698 if (storage->getModuleContext ()->getResilienceStrategy () !=
26822699 ResilienceStrategy::Resilient)
@@ -2699,11 +2716,30 @@ static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl(
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.
@@ -2712,8 +2748,9 @@ static bool requiresCorrespondingUnderscoredCoroutineAccessorImpl(
27122748
27132749bool AbstractStorageDecl::requiresCorrespondingUnderscoredCoroutineAccessor (
27142750 AccessorKind kind, AccessorDecl const *decl) const {
2715- return requiresCorrespondingUnderscoredCoroutineAccessorImpl (this , kind,
2716- decl);
2751+ return requiresCorrespondingUnderscoredCoroutineAccessorImpl (
2752+ this , kind, decl,
2753+ /* derived=*/ this );
27172754}
27182755
27192756bool RequiresOpaqueModifyCoroutineRequest::evaluate (
0 commit comments