@@ -83,6 +83,33 @@ struct TypeWrapperAttrInfo {
8383 NominalTypeDecl *AttachedTo;
8484};
8585
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+
86113static void
87114getTypeWrappers (NominalTypeDecl *decl,
88115 SmallVectorImpl<TypeWrapperAttrInfo> &typeWrappers) {
@@ -108,18 +135,10 @@ getTypeWrappers(NominalTypeDecl *decl,
108135
109136 // Attributes inferred from (explicit) protocol conformances
110137 // 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);
122140
141+ for (auto *protocol : protocols) {
123142 SmallVector<TypeWrapperAttrInfo, 2 > inferredAttrs;
124143 getTypeWrappers (protocol, inferredAttrs);
125144
@@ -219,6 +238,54 @@ TypeDecl *NominalTypeDecl::getTypeWrapperStorageDecl() const {
219238 GetTypeWrapperStorage{mutableSelf}, nullptr );
220239}
221240
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+
222289TypeDecl *GetTypeWrapperStorage::evaluate (Evaluator &evaluator,
223290 NominalTypeDecl *parent) const {
224291 if (!parent->hasTypeWrapper ())
@@ -246,7 +313,7 @@ TypeDecl *GetTypeWrapperStorage::evaluate(Evaluator &evaluator,
246313
247314 storage->setImplicit ();
248315 storage->setSynthesized ();
249- storage->setAccess (AccessLevel::Internal );
316+ storage->setAccess (getAccessLevelForTypeWrapperStorage (parent) );
250317
251318 parent->addMember (storage);
252319
@@ -278,7 +345,8 @@ GetTypeWrapperProperty::evaluate(Evaluator &evaluator,
278345 storage->getDeclaredInterfaceType ()});
279346
280347 return injectProperty (parent, ctx.Id_TypeWrapperProperty , propertyTy,
281- VarDecl::Introducer::Var, AccessLevel::Internal);
348+ VarDecl::Introducer::Var,
349+ getAccessLevelForTypeWrapperStorage (parent));
282350}
283351
284352VarDecl *GetTypeWrapperStorageForProperty::evaluate (Evaluator &evaluator,
0 commit comments