@@ -1950,7 +1950,7 @@ SourceRange IfConfigDecl::getSourceRange() const {
19501950}
19511951
19521952static bool isPolymorphic (const AbstractStorageDecl *storage) {
1953- if (storage->isObjCDynamic ())
1953+ if (storage->shouldUseObjCDispatch ())
19541954 return true ;
19551955
19561956
@@ -2083,7 +2083,7 @@ getDirectReadWriteAccessStrategy(const AbstractStorageDecl *storage) {
20832083 return AccessStrategy::getStorage ();
20842084 case ReadWriteImplKind::Stored: {
20852085 // If the storage isDynamic (and not @objc) use the accessors.
2086- if (storage->isNativeDynamic ())
2086+ if (storage->shouldUseNativeDynamicDispatch ())
20872087 return AccessStrategy::getMaterializeToTemporary (
20882088 getOpaqueReadAccessStrategy (storage, false ),
20892089 getOpaqueWriteAccessStrategy (storage, false ));
@@ -2168,7 +2168,7 @@ AbstractStorageDecl::getAccessStrategy(AccessSemantics semantics,
21682168 if (isPolymorphic (this ))
21692169 return getOpaqueAccessStrategy (this , accessKind, /* dispatch*/ true );
21702170
2171- if (isNativeDynamic ())
2171+ if (shouldUseNativeDynamicDispatch ())
21722172 return getOpaqueAccessStrategy (this , accessKind, /* dispatch*/ false );
21732173
21742174 // If the storage is resilient from the given module and resilience
@@ -2926,6 +2926,59 @@ bool ValueDecl::isDynamic() const {
29262926 getAttrs ().hasAttribute <DynamicAttr>());
29272927}
29282928
2929+ bool ValueDecl::isObjCDynamicInGenericClass () const {
2930+ if (!isObjCDynamic ())
2931+ return false ;
2932+
2933+ auto *DC = this ->getDeclContext ();
2934+ auto *classDecl = DC->getSelfClassDecl ();
2935+ if (!classDecl)
2936+ return false ;
2937+
2938+ return classDecl->isGenericContext () && !classDecl->usesObjCGenericsModel ();
2939+ }
2940+
2941+ bool ValueDecl::shouldUseObjCMethodReplacement () const {
2942+ if (isNativeDynamic ())
2943+ return false ;
2944+
2945+ if (getModuleContext ()->isImplicitDynamicEnabled () &&
2946+ isObjCDynamicInGenericClass ())
2947+ return false ;
2948+
2949+ return isObjCDynamic ();
2950+ }
2951+
2952+ bool ValueDecl::shouldUseNativeMethodReplacement () const {
2953+ if (isNativeDynamic ())
2954+ return true ;
2955+
2956+ if (!isObjCDynamicInGenericClass ())
2957+ return false ;
2958+
2959+ auto *replacedDecl = getDynamicallyReplacedDecl ();
2960+ if (replacedDecl)
2961+ return false ;
2962+
2963+ return getModuleContext ()->isImplicitDynamicEnabled ();
2964+ }
2965+
2966+ bool ValueDecl::isNativeMethodReplacement () const {
2967+ // Is this a @_dynamicReplacement(for:) that use the native dynamic function
2968+ // replacement mechanism.
2969+ auto *replacedDecl = getDynamicallyReplacedDecl ();
2970+ if (!replacedDecl)
2971+ return false ;
2972+
2973+ if (isNativeDynamic ())
2974+ return true ;
2975+
2976+ if (isObjCDynamicInGenericClass ())
2977+ return replacedDecl->getModuleContext ()->isImplicitDynamicEnabled ();
2978+
2979+ return false ;
2980+ }
2981+
29292982void ValueDecl::setIsDynamic (bool value) {
29302983 assert (!LazySemanticInfo.isDynamicComputed ||
29312984 LazySemanticInfo.isDynamic == value);
@@ -5143,7 +5196,7 @@ bool AbstractStorageDecl::hasDidSetOrWillSetDynamicReplacement() const {
51435196
51445197bool AbstractStorageDecl::hasAnyNativeDynamicAccessors () const {
51455198 for (auto accessor : getAllAccessors ()) {
5146- if (accessor->isNativeDynamic ())
5199+ if (accessor->shouldUseNativeDynamicDispatch ())
51475200 return true ;
51485201 }
51495202 return false ;
0 commit comments