1
-
2
1
// ===--- Decl.cpp - Swift Language Decl ASTs ------------------------------===//
3
2
//
4
3
// This source file is part of the Swift.org open source project
15
14
//
16
15
// ===----------------------------------------------------------------------===//
17
16
18
- #include " swift/Strings.h"
19
17
#include " swift/AST/Decl.h"
20
18
#include " swift/AST/ASTContext.h"
21
19
#include " swift/AST/ASTMangler.h"
24
22
#include " swift/AST/AccessRequests.h"
25
23
#include " swift/AST/AccessScope.h"
26
24
#include " swift/AST/Attr.h"
25
+ #include " swift/AST/AvailabilityContext.h"
27
26
#include " swift/AST/AvailabilityInference.h"
28
27
#include " swift/AST/CaptureInfo.h"
29
28
#include " swift/AST/ConformanceLookup.h"
64
63
#include " swift/ClangImporter/ClangModule.h"
65
64
#include " swift/Demangling/ManglingMacros.h"
66
65
#include " swift/Parse/Lexer.h" // FIXME: Bad dependency
66
+ #include " swift/Strings.h"
67
67
#include " clang/Lex/MacroInfo.h"
68
68
#include " llvm/ADT/DenseMap.h"
69
69
#include " llvm/ADT/SmallPtrSet.h"
@@ -3026,9 +3026,11 @@ getDirectWriteAccessStrategy(const AbstractStorageDecl *storage) {
3026
3026
llvm_unreachable (" bad impl kind" );
3027
3027
}
3028
3028
3029
- static AccessStrategy
3030
- getOpaqueReadAccessStrategy (const AbstractStorageDecl *storage, bool dispatch,
3031
- bool useOldABI);
3029
+ static AccessStrategy getOpaqueReadAccessStrategy (
3030
+ const AbstractStorageDecl *storage, bool dispatch, ModuleDecl *module ,
3031
+ ResilienceExpansion expansion,
3032
+ std::optional<std::pair<SourceRange, const DeclContext *>> location,
3033
+ bool useOldABI);
3032
3034
static AccessStrategy
3033
3035
getOpaqueWriteAccessStrategy (const AbstractStorageDecl *storage, bool dispatch);
3034
3036
@@ -3043,7 +3045,9 @@ getDirectReadWriteAccessStrategy(const AbstractStorageDecl *storage) {
3043
3045
// If the storage isDynamic (and not @objc) use the accessors.
3044
3046
if (storage->shouldUseNativeDynamicDispatch ())
3045
3047
return AccessStrategy::getMaterializeToTemporary (
3046
- getOpaqueReadAccessStrategy (storage, false , false ),
3048
+ getOpaqueReadAccessStrategy (storage, false , nullptr ,
3049
+ ResilienceExpansion::Minimal,
3050
+ std::nullopt, false ),
3047
3051
getOpaqueWriteAccessStrategy (storage, false ));
3048
3052
return AccessStrategy::getStorage ();
3049
3053
}
@@ -3080,15 +3084,61 @@ getDirectReadWriteAccessStrategy(const AbstractStorageDecl *storage) {
3080
3084
llvm_unreachable (" bad impl kind" );
3081
3085
}
3082
3086
3083
- static AccessStrategy
3084
- getOpaqueReadAccessStrategy (const AbstractStorageDecl *storage, bool dispatch,
3085
- bool useOldABI) {
3087
+ static bool mayReferenceUseCoroutineAccessorOnStorage (
3088
+ ModuleDecl *module , ResilienceExpansion expansion,
3089
+ std::optional<std::pair<SourceRange, const DeclContext *>> reference,
3090
+ const AbstractStorageDecl *storage) {
3091
+ assert (storage);
3092
+ ASTContext &ctx = storage->getASTContext ();
3093
+ assert (ctx.LangOpts .hasFeature (Feature::CoroutineAccessors));
3094
+
3095
+ // For triples without platforms, coroutine accessors are always available.
3096
+ auto domain = ctx.getTargetAvailabilityDomain ();
3097
+ if (domain.isUniversal ())
3098
+ return true ;
3099
+
3100
+ // A non-resilient access to storage can always use the coroutine accessor,
3101
+ // provided it exists. Such an access is compiled with the version of the
3102
+ // module that includes the accessor.
3103
+ bool resilient = [&] {
3104
+ if (module )
3105
+ return storage->isResilient (module , expansion);
3106
+ else
3107
+ return storage->isResilient ();
3108
+ }();
3109
+ if (!resilient)
3110
+ return true ;
3111
+
3112
+ // Without knowing where the storage is referenced, it can't be known that
3113
+ // a coroutine accessor is available.
3114
+ if (!reference) {
3115
+ return false ;
3116
+ }
3117
+
3118
+ // A resilient access to storage may only use a coroutine accessor if the
3119
+ // storage became available no earlier than the feature.
3120
+ auto referenceAvailability = AvailabilityContext::forLocation (
3121
+ reference->first .Start , reference->second )
3122
+ .getPlatformRange ();
3123
+ auto featureAvailability =
3124
+ storage->getASTContext ().getCoroutineAccessorsAvailability ();
3125
+
3126
+ return referenceAvailability.isContainedIn (featureAvailability);
3127
+ }
3128
+
3129
+ static AccessStrategy getOpaqueReadAccessStrategy (
3130
+ const AbstractStorageDecl *storage, bool dispatch, ModuleDecl *module ,
3131
+ ResilienceExpansion expansion,
3132
+ std::optional<std::pair<SourceRange, const DeclContext *>> location,
3133
+ bool useOldABI) {
3086
3134
if (useOldABI) {
3087
3135
assert (storage->requiresOpaqueRead2Coroutine ());
3088
3136
assert (storage->requiresOpaqueReadCoroutine ());
3089
3137
return AccessStrategy::getAccessor (AccessorKind::Read, dispatch);
3090
3138
}
3091
- if (storage->requiresOpaqueRead2Coroutine ())
3139
+ if (storage->requiresOpaqueRead2Coroutine () &&
3140
+ mayReferenceUseCoroutineAccessorOnStorage (module , expansion, location,
3141
+ storage))
3092
3142
return AccessStrategy::getAccessor (AccessorKind::Read2, dispatch);
3093
3143
if (storage->requiresOpaqueReadCoroutine ())
3094
3144
return AccessStrategy::getAccessor (AccessorKind::Read, dispatch);
@@ -3102,41 +3152,53 @@ getOpaqueWriteAccessStrategy(const AbstractStorageDecl *storage, bool dispatch)
3102
3152
return AccessStrategy::getAccessor (AccessorKind::Set, dispatch);
3103
3153
}
3104
3154
3105
- static AccessStrategy
3106
- getOpaqueReadWriteAccessStrategy (const AbstractStorageDecl *storage,
3107
- bool dispatch, bool useOldABI) {
3155
+ static AccessStrategy getOpaqueReadWriteAccessStrategy (
3156
+ const AbstractStorageDecl *storage, bool dispatch, ModuleDecl *module ,
3157
+ ResilienceExpansion expansion,
3158
+ std::optional<std::pair<SourceRange, const DeclContext *>> location,
3159
+ bool useOldABI) {
3108
3160
if (useOldABI) {
3109
3161
assert (storage->requiresOpaqueModify2Coroutine ());
3110
3162
assert (storage->requiresOpaqueModifyCoroutine ());
3111
3163
return AccessStrategy::getAccessor (AccessorKind::Modify, dispatch);
3112
3164
}
3113
- if (storage->requiresOpaqueModify2Coroutine ())
3165
+ if (storage->requiresOpaqueModify2Coroutine () &&
3166
+ mayReferenceUseCoroutineAccessorOnStorage (module , expansion, location,
3167
+ storage))
3114
3168
return AccessStrategy::getAccessor (AccessorKind::Modify2, dispatch);
3115
3169
if (storage->requiresOpaqueModifyCoroutine ())
3116
3170
return AccessStrategy::getAccessor (AccessorKind::Modify, dispatch);
3117
3171
return AccessStrategy::getMaterializeToTemporary (
3118
- getOpaqueReadAccessStrategy (storage, dispatch, false ),
3172
+ getOpaqueReadAccessStrategy (storage, dispatch, nullptr ,
3173
+ ResilienceExpansion::Minimal, location,
3174
+ false ),
3119
3175
getOpaqueWriteAccessStrategy (storage, dispatch));
3120
3176
}
3121
3177
3122
- static AccessStrategy
3123
- getOpaqueAccessStrategy (const AbstractStorageDecl *storage,
3124
- AccessKind accessKind, bool dispatch, bool useOldABI) {
3178
+ static AccessStrategy getOpaqueAccessStrategy (
3179
+ const AbstractStorageDecl *storage, AccessKind accessKind, bool dispatch,
3180
+ ModuleDecl *module , ResilienceExpansion expansion,
3181
+ std::optional<std::pair<SourceRange, const DeclContext *>> location,
3182
+ bool useOldABI) {
3125
3183
switch (accessKind) {
3126
3184
case AccessKind::Read:
3127
- return getOpaqueReadAccessStrategy (storage, dispatch, useOldABI);
3185
+ return getOpaqueReadAccessStrategy (storage, dispatch, module , expansion,
3186
+ location, useOldABI);
3128
3187
case AccessKind::Write:
3129
3188
assert (!useOldABI);
3130
3189
return getOpaqueWriteAccessStrategy (storage, dispatch);
3131
3190
case AccessKind::ReadWrite:
3132
- return getOpaqueReadWriteAccessStrategy (storage, dispatch, useOldABI);
3191
+ return getOpaqueReadWriteAccessStrategy (storage, dispatch, module ,
3192
+ expansion, location, useOldABI);
3133
3193
}
3134
3194
llvm_unreachable (" bad access kind" );
3135
3195
}
3136
3196
3137
3197
AccessStrategy AbstractStorageDecl::getAccessStrategy (
3138
3198
AccessSemantics semantics, AccessKind accessKind, ModuleDecl *module ,
3139
- ResilienceExpansion expansion, bool useOldABI) const {
3199
+ ResilienceExpansion expansion,
3200
+ std::optional<std::pair<SourceRange, const DeclContext *>> location,
3201
+ bool useOldABI) const {
3140
3202
switch (semantics) {
3141
3203
case AccessSemantics::DirectToStorage:
3142
3204
assert (hasStorage () || getASTContext ().Diags .hadAnyError ());
@@ -3153,11 +3215,11 @@ AccessStrategy AbstractStorageDecl::getAccessStrategy(
3153
3215
// accessors are dynamically dispatched, and we cannot do direct access.
3154
3216
if (isPolymorphic (this ))
3155
3217
return getOpaqueAccessStrategy (this , accessKind, /* dispatch*/ true ,
3156
- useOldABI);
3218
+ module , expansion, location, useOldABI);
3157
3219
3158
3220
if (shouldUseNativeDynamicDispatch ())
3159
3221
return getOpaqueAccessStrategy (this , accessKind, /* dispatch*/ false ,
3160
- useOldABI);
3222
+ module , expansion, location, useOldABI);
3161
3223
3162
3224
// If the storage is resilient from the given module and resilience
3163
3225
// expansion, we cannot use direct access.
@@ -3180,7 +3242,7 @@ AccessStrategy AbstractStorageDecl::getAccessStrategy(
3180
3242
3181
3243
if (resilient)
3182
3244
return getOpaqueAccessStrategy (this , accessKind, /* dispatch*/ false ,
3183
- useOldABI);
3245
+ module , expansion, location, useOldABI);
3184
3246
}
3185
3247
3186
3248
LLVM_FALLTHROUGH;
@@ -3204,6 +3266,7 @@ bool AbstractStorageDecl::isAccessedViaPhysicalStorage(
3204
3266
AccessSemantics semantics, AccessKind accessKind, ModuleDecl *module ,
3205
3267
ResilienceExpansion expansion) const {
3206
3268
return getAccessStrategy (semantics, accessKind, module , expansion,
3269
+ /* location=*/ std::nullopt,
3207
3270
/* useOldABI=*/ false )
3208
3271
.getKind () == AccessStrategy::Kind::Storage;
3209
3272
}
0 commit comments