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"
@@ -3022,9 +3022,11 @@ getDirectWriteAccessStrategy(const AbstractStorageDecl *storage) {
3022
3022
llvm_unreachable (" bad impl kind" );
3023
3023
}
3024
3024
3025
- static AccessStrategy
3026
- getOpaqueReadAccessStrategy (const AbstractStorageDecl *storage, bool dispatch,
3027
- bool useOldABI);
3025
+ static AccessStrategy getOpaqueReadAccessStrategy (
3026
+ const AbstractStorageDecl *storage, bool dispatch, ModuleDecl *module ,
3027
+ ResilienceExpansion expansion,
3028
+ std::optional<std::pair<SourceRange, const DeclContext *>> location,
3029
+ bool useOldABI);
3028
3030
static AccessStrategy
3029
3031
getOpaqueWriteAccessStrategy (const AbstractStorageDecl *storage, bool dispatch);
3030
3032
@@ -3039,7 +3041,9 @@ getDirectReadWriteAccessStrategy(const AbstractStorageDecl *storage) {
3039
3041
// If the storage isDynamic (and not @objc) use the accessors.
3040
3042
if (storage->shouldUseNativeDynamicDispatch ())
3041
3043
return AccessStrategy::getMaterializeToTemporary (
3042
- getOpaqueReadAccessStrategy (storage, false , false ),
3044
+ getOpaqueReadAccessStrategy (storage, false , nullptr ,
3045
+ ResilienceExpansion::Minimal,
3046
+ std::nullopt, false ),
3043
3047
getOpaqueWriteAccessStrategy (storage, false ));
3044
3048
return AccessStrategy::getStorage ();
3045
3049
}
@@ -3076,15 +3080,61 @@ getDirectReadWriteAccessStrategy(const AbstractStorageDecl *storage) {
3076
3080
llvm_unreachable (" bad impl kind" );
3077
3081
}
3078
3082
3079
- static AccessStrategy
3080
- getOpaqueReadAccessStrategy (const AbstractStorageDecl *storage, bool dispatch,
3081
- bool useOldABI) {
3083
+ static bool mayReferenceUseCoroutineAccessorOnStorage (
3084
+ ModuleDecl *module , ResilienceExpansion expansion,
3085
+ std::optional<std::pair<SourceRange, const DeclContext *>> reference,
3086
+ const AbstractStorageDecl *storage) {
3087
+ assert (storage);
3088
+ ASTContext &ctx = storage->getASTContext ();
3089
+ assert (ctx.LangOpts .hasFeature (Feature::CoroutineAccessors));
3090
+
3091
+ // For triples without platforms, coroutine accessors are always available.
3092
+ auto domain = ctx.getTargetAvailabilityDomain ();
3093
+ if (domain.isUniversal ())
3094
+ return true ;
3095
+
3096
+ // A non-resilient access to storage can always use the coroutine accessor,
3097
+ // provided it exists. Such an access is compiled with the version of the
3098
+ // module that includes the accessor.
3099
+ bool resilient = [&] {
3100
+ if (module )
3101
+ return storage->isResilient (module , expansion);
3102
+ else
3103
+ return storage->isResilient ();
3104
+ }();
3105
+ if (!resilient)
3106
+ return true ;
3107
+
3108
+ // Without knowing where the storage is referenced, it can't be known that
3109
+ // a coroutine accessor is available.
3110
+ if (!reference) {
3111
+ return false ;
3112
+ }
3113
+
3114
+ // A resilient access to storage may only use a coroutine accessor if the
3115
+ // storage became available no earlier than the feature.
3116
+ auto referenceAvailability = AvailabilityContext::forLocation (
3117
+ reference->first .Start , reference->second )
3118
+ .getPlatformRange ();
3119
+ auto featureAvailability =
3120
+ storage->getASTContext ().getCoroutineAccessorsAvailability ();
3121
+
3122
+ return referenceAvailability.isContainedIn (featureAvailability);
3123
+ }
3124
+
3125
+ static AccessStrategy getOpaqueReadAccessStrategy (
3126
+ const AbstractStorageDecl *storage, bool dispatch, ModuleDecl *module ,
3127
+ ResilienceExpansion expansion,
3128
+ std::optional<std::pair<SourceRange, const DeclContext *>> location,
3129
+ bool useOldABI) {
3082
3130
if (useOldABI) {
3083
3131
assert (storage->requiresOpaqueRead2Coroutine ());
3084
3132
assert (storage->requiresOpaqueReadCoroutine ());
3085
3133
return AccessStrategy::getAccessor (AccessorKind::Read, dispatch);
3086
3134
}
3087
- if (storage->requiresOpaqueRead2Coroutine ())
3135
+ if (storage->requiresOpaqueRead2Coroutine () &&
3136
+ mayReferenceUseCoroutineAccessorOnStorage (module , expansion, location,
3137
+ storage))
3088
3138
return AccessStrategy::getAccessor (AccessorKind::Read2, dispatch);
3089
3139
if (storage->requiresOpaqueReadCoroutine ())
3090
3140
return AccessStrategy::getAccessor (AccessorKind::Read, dispatch);
@@ -3098,41 +3148,53 @@ getOpaqueWriteAccessStrategy(const AbstractStorageDecl *storage, bool dispatch)
3098
3148
return AccessStrategy::getAccessor (AccessorKind::Set, dispatch);
3099
3149
}
3100
3150
3101
- static AccessStrategy
3102
- getOpaqueReadWriteAccessStrategy (const AbstractStorageDecl *storage,
3103
- bool dispatch, bool useOldABI) {
3151
+ static AccessStrategy getOpaqueReadWriteAccessStrategy (
3152
+ const AbstractStorageDecl *storage, bool dispatch, ModuleDecl *module ,
3153
+ ResilienceExpansion expansion,
3154
+ std::optional<std::pair<SourceRange, const DeclContext *>> location,
3155
+ bool useOldABI) {
3104
3156
if (useOldABI) {
3105
3157
assert (storage->requiresOpaqueModify2Coroutine ());
3106
3158
assert (storage->requiresOpaqueModifyCoroutine ());
3107
3159
return AccessStrategy::getAccessor (AccessorKind::Modify, dispatch);
3108
3160
}
3109
- if (storage->requiresOpaqueModify2Coroutine ())
3161
+ if (storage->requiresOpaqueModify2Coroutine () &&
3162
+ mayReferenceUseCoroutineAccessorOnStorage (module , expansion, location,
3163
+ storage))
3110
3164
return AccessStrategy::getAccessor (AccessorKind::Modify2, dispatch);
3111
3165
if (storage->requiresOpaqueModifyCoroutine ())
3112
3166
return AccessStrategy::getAccessor (AccessorKind::Modify, dispatch);
3113
3167
return AccessStrategy::getMaterializeToTemporary (
3114
- getOpaqueReadAccessStrategy (storage, dispatch, false ),
3168
+ getOpaqueReadAccessStrategy (storage, dispatch, nullptr ,
3169
+ ResilienceExpansion::Minimal, location,
3170
+ false ),
3115
3171
getOpaqueWriteAccessStrategy (storage, dispatch));
3116
3172
}
3117
3173
3118
- static AccessStrategy
3119
- getOpaqueAccessStrategy (const AbstractStorageDecl *storage,
3120
- AccessKind accessKind, bool dispatch, bool useOldABI) {
3174
+ static AccessStrategy getOpaqueAccessStrategy (
3175
+ const AbstractStorageDecl *storage, AccessKind accessKind, bool dispatch,
3176
+ ModuleDecl *module , ResilienceExpansion expansion,
3177
+ std::optional<std::pair<SourceRange, const DeclContext *>> location,
3178
+ bool useOldABI) {
3121
3179
switch (accessKind) {
3122
3180
case AccessKind::Read:
3123
- return getOpaqueReadAccessStrategy (storage, dispatch, useOldABI);
3181
+ return getOpaqueReadAccessStrategy (storage, dispatch, module , expansion,
3182
+ location, useOldABI);
3124
3183
case AccessKind::Write:
3125
3184
assert (!useOldABI);
3126
3185
return getOpaqueWriteAccessStrategy (storage, dispatch);
3127
3186
case AccessKind::ReadWrite:
3128
- return getOpaqueReadWriteAccessStrategy (storage, dispatch, useOldABI);
3187
+ return getOpaqueReadWriteAccessStrategy (storage, dispatch, module ,
3188
+ expansion, location, useOldABI);
3129
3189
}
3130
3190
llvm_unreachable (" bad access kind" );
3131
3191
}
3132
3192
3133
3193
AccessStrategy AbstractStorageDecl::getAccessStrategy (
3134
3194
AccessSemantics semantics, AccessKind accessKind, ModuleDecl *module ,
3135
- ResilienceExpansion expansion, bool useOldABI) const {
3195
+ ResilienceExpansion expansion,
3196
+ std::optional<std::pair<SourceRange, const DeclContext *>> location,
3197
+ bool useOldABI) const {
3136
3198
switch (semantics) {
3137
3199
case AccessSemantics::DirectToStorage:
3138
3200
assert (hasStorage () || getASTContext ().Diags .hadAnyError ());
@@ -3149,11 +3211,11 @@ AccessStrategy AbstractStorageDecl::getAccessStrategy(
3149
3211
// accessors are dynamically dispatched, and we cannot do direct access.
3150
3212
if (isPolymorphic (this ))
3151
3213
return getOpaqueAccessStrategy (this , accessKind, /* dispatch*/ true ,
3152
- useOldABI);
3214
+ module , expansion, location, useOldABI);
3153
3215
3154
3216
if (shouldUseNativeDynamicDispatch ())
3155
3217
return getOpaqueAccessStrategy (this , accessKind, /* dispatch*/ false ,
3156
- useOldABI);
3218
+ module , expansion, location, useOldABI);
3157
3219
3158
3220
// If the storage is resilient from the given module and resilience
3159
3221
// expansion, we cannot use direct access.
@@ -3176,7 +3238,7 @@ AccessStrategy AbstractStorageDecl::getAccessStrategy(
3176
3238
3177
3239
if (resilient)
3178
3240
return getOpaqueAccessStrategy (this , accessKind, /* dispatch*/ false ,
3179
- useOldABI);
3241
+ module , expansion, location, useOldABI);
3180
3242
}
3181
3243
3182
3244
LLVM_FALLTHROUGH;
@@ -3196,6 +3258,15 @@ AccessStrategy AbstractStorageDecl::getAccessStrategy(
3196
3258
llvm_unreachable (" bad access semantics" );
3197
3259
}
3198
3260
3261
+ bool AbstractStorageDecl::isAccessedViaPhysicalStorage (
3262
+ AccessSemantics semantics, AccessKind accessKind, ModuleDecl *module ,
3263
+ ResilienceExpansion expansion) const {
3264
+ return getAccessStrategy (semantics, accessKind, module , expansion,
3265
+ /* location=*/ std::nullopt,
3266
+ /* useOldABI=*/ false )
3267
+ .getKind () == AccessStrategy::Kind::Storage;
3268
+ }
3269
+
3199
3270
bool AbstractStorageDecl::requiresOpaqueAccessors () const {
3200
3271
// Subscripts always require opaque accessors, so don't even kick off
3201
3272
// a request.
0 commit comments