@@ -1950,7 +1950,7 @@ SourceRange IfConfigDecl::getSourceRange() const {
1950
1950
}
1951
1951
1952
1952
static bool isPolymorphic(const AbstractStorageDecl *storage) {
1953
- if (storage->isObjCDynamic ())
1953
+ if (storage->shouldUseObjCDispatch ())
1954
1954
return true;
1955
1955
1956
1956
@@ -2083,7 +2083,7 @@ getDirectReadWriteAccessStrategy(const AbstractStorageDecl *storage) {
2083
2083
return AccessStrategy::getStorage();
2084
2084
case ReadWriteImplKind::Stored: {
2085
2085
// If the storage isDynamic (and not @objc) use the accessors.
2086
- if (storage->isNativeDynamic ())
2086
+ if (storage->shouldUseNativeDynamicDispatch ())
2087
2087
return AccessStrategy::getMaterializeToTemporary(
2088
2088
getOpaqueReadAccessStrategy(storage, false),
2089
2089
getOpaqueWriteAccessStrategy(storage, false));
@@ -2168,7 +2168,7 @@ AbstractStorageDecl::getAccessStrategy(AccessSemantics semantics,
2168
2168
if (isPolymorphic(this))
2169
2169
return getOpaqueAccessStrategy(this, accessKind, /*dispatch*/ true);
2170
2170
2171
- if (isNativeDynamic ())
2171
+ if (shouldUseNativeDynamicDispatch ())
2172
2172
return getOpaqueAccessStrategy(this, accessKind, /*dispatch*/ false);
2173
2173
2174
2174
// If the storage is resilient from the given module and resilience
@@ -2926,6 +2926,59 @@ bool ValueDecl::isDynamic() const {
2926
2926
getAttrs().hasAttribute<DynamicAttr>());
2927
2927
}
2928
2928
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
+
2929
2982
void ValueDecl::setIsDynamic(bool value) {
2930
2983
assert(!LazySemanticInfo.isDynamicComputed ||
2931
2984
LazySemanticInfo.isDynamic == value);
@@ -5143,7 +5196,7 @@ bool AbstractStorageDecl::hasDidSetOrWillSetDynamicReplacement() const {
5143
5196
5144
5197
bool AbstractStorageDecl::hasAnyNativeDynamicAccessors() const {
5145
5198
for (auto accessor : getAllAccessors()) {
5146
- if (accessor->isNativeDynamic ())
5199
+ if (accessor->shouldUseNativeDynamicDispatch ())
5147
5200
return true;
5148
5201
}
5149
5202
return false;
0 commit comments