@@ -83,6 +83,33 @@ struct TypeWrapperAttrInfo {
83
83
NominalTypeDecl *AttachedTo;
84
84
};
85
85
86
+ static void
87
+ getDeclaredProtocolConformances (NominalTypeDecl *decl,
88
+ SmallVectorImpl<ProtocolDecl *> &protocols) {
89
+ for (unsigned i : indices (decl->getInherited ())) {
90
+ auto inheritedType = evaluateOrDefault (
91
+ decl->getASTContext ().evaluator ,
92
+ InheritedTypeRequest{decl, i, TypeResolutionStage::Interface}, Type ());
93
+
94
+ if (!(inheritedType && inheritedType->isConstraintType ()))
95
+ continue ;
96
+
97
+ if (auto *protocol =
98
+ dyn_cast_or_null<ProtocolDecl>(inheritedType->getAnyNominal ())) {
99
+ protocols.push_back (protocol);
100
+ }
101
+
102
+ if (auto composition = inheritedType->getAs <ProtocolCompositionType>()) {
103
+ for (auto member : composition->getMembers ()) {
104
+ if (auto *protocol =
105
+ dyn_cast_or_null<ProtocolDecl>(member->getAnyNominal ())) {
106
+ protocols.push_back (protocol);
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+
86
113
static void
87
114
getTypeWrappers (NominalTypeDecl *decl,
88
115
SmallVectorImpl<TypeWrapperAttrInfo> &typeWrappers) {
@@ -108,18 +135,10 @@ getTypeWrappers(NominalTypeDecl *decl,
108
135
109
136
// Attributes inferred from (explicit) protocol conformances
110
137
// associated with the declaration of the type.
111
- for (unsigned i : indices (decl->getInherited ())) {
112
- auto inheritedType = evaluateOrDefault (
113
- ctx.evaluator ,
114
- InheritedTypeRequest{decl, i, TypeResolutionStage::Interface}, Type ());
115
-
116
- if (!(inheritedType && inheritedType->isConstraintType ()))
117
- continue ;
118
-
119
- auto *protocol = inheritedType->getAnyNominal ();
120
- if (!protocol)
121
- continue ;
138
+ SmallVector<ProtocolDecl *, 4 > protocols;
139
+ getDeclaredProtocolConformances (decl, protocols);
122
140
141
+ for (auto *protocol : protocols) {
123
142
SmallVector<TypeWrapperAttrInfo, 2 > inferredAttrs;
124
143
getTypeWrappers (protocol, inferredAttrs);
125
144
@@ -219,6 +238,54 @@ TypeDecl *NominalTypeDecl::getTypeWrapperStorageDecl() const {
219
238
GetTypeWrapperStorage{mutableSelf}, nullptr );
220
239
}
221
240
241
+ static AccessLevel
242
+ getAccessLevelForTypeWrapperStorage (NominalTypeDecl *attachedTo) {
243
+ auto &ctx = attachedTo->getASTContext ();
244
+
245
+ if (isa<ProtocolDecl>(attachedTo))
246
+ return attachedTo->getFormalAccess ();
247
+
248
+ llvm::SmallDenseMap<ProtocolDecl *, bool , 4 > visitedProtocols;
249
+ std::function<bool (ProtocolDecl *)> hasPublicStorageAssociatedType =
250
+ [&](ProtocolDecl *protocol) {
251
+ if (visitedProtocols.count (protocol))
252
+ return visitedProtocols[protocol];
253
+
254
+ auto recordResult = [&](ProtocolDecl *P, bool hasWrapper) {
255
+ visitedProtocols[P] = hasWrapper;
256
+ return hasWrapper;
257
+ };
258
+
259
+ if (auto *storage =
260
+ protocol->getAssociatedType (ctx.Id_TypeWrapperStorage )) {
261
+ if (storage->getFormalAccess () == AccessLevel::Public)
262
+ return recordResult (protocol, true );
263
+ }
264
+
265
+ // Recursively check whether any of the parents have that
266
+ // requirement.
267
+ for (auto *parent : protocol->getProtocolDependencies ()) {
268
+ bool hasPublicStorage = hasPublicStorageAssociatedType (parent);
269
+ (void )recordResult (parent, hasPublicStorage);
270
+
271
+ if (hasPublicStorage)
272
+ return recordResult (protocol, true );
273
+ }
274
+
275
+ return recordResult (protocol, false );
276
+ };
277
+
278
+ SmallVector<ProtocolDecl *, 4 > protocols;
279
+ getDeclaredProtocolConformances (attachedTo, protocols);
280
+
281
+ for (auto *protocol : protocols) {
282
+ if (hasPublicStorageAssociatedType (protocol))
283
+ return AccessLevel::Public;
284
+ }
285
+
286
+ return AccessLevel::Internal;
287
+ }
288
+
222
289
TypeDecl *GetTypeWrapperStorage::evaluate (Evaluator &evaluator,
223
290
NominalTypeDecl *parent) const {
224
291
if (!parent->hasTypeWrapper ())
@@ -246,7 +313,7 @@ TypeDecl *GetTypeWrapperStorage::evaluate(Evaluator &evaluator,
246
313
247
314
storage->setImplicit ();
248
315
storage->setSynthesized ();
249
- storage->setAccess (AccessLevel::Internal );
316
+ storage->setAccess (getAccessLevelForTypeWrapperStorage (parent) );
250
317
251
318
parent->addMember (storage);
252
319
@@ -278,7 +345,8 @@ GetTypeWrapperProperty::evaluate(Evaluator &evaluator,
278
345
storage->getDeclaredInterfaceType ()});
279
346
280
347
return injectProperty (parent, ctx.Id_TypeWrapperProperty , propertyTy,
281
- VarDecl::Introducer::Var, AccessLevel::Internal);
348
+ VarDecl::Introducer::Var,
349
+ getAccessLevelForTypeWrapperStorage (parent));
282
350
}
283
351
284
352
VarDecl *GetTypeWrapperStorageForProperty::evaluate (Evaluator &evaluator,
0 commit comments