@@ -116,6 +116,31 @@ class ContainsSpecializableArchetype : public TypeWalker {
116
116
}
117
117
};
118
118
119
+ // / Returns `true` if `ED` is an extension of `PD` that binds `Self` to a
120
+ // / concrete type, like `extension MyProto where Self == MyStruct {}`.
121
+ // /
122
+ // / In these cases, it is possible to access static members defined in the
123
+ // / extension when perfoming unresolved member lookup in a type context of
124
+ // / `PD`.
125
+ static bool isExtensionWithSelfBound (const ExtensionDecl *ED,
126
+ ProtocolDecl *PD) {
127
+ if (!ED || !PD) {
128
+ return false ;
129
+ }
130
+ if (ED->getExtendedNominal () != PD) {
131
+ return false ;
132
+ }
133
+ GenericSignature genericSig = ED->getGenericSignature ();
134
+ Type selfType = genericSig->getConcreteType (ED->getSelfInterfaceType ());
135
+ if (!selfType) {
136
+ return false ;
137
+ }
138
+ if (selfType->is <ExistentialType>()) {
139
+ return false ;
140
+ }
141
+ return true ;
142
+ }
143
+
119
144
static bool isExtensionAppliedInternal (const DeclContext *DC, Type BaseTy,
120
145
const ExtensionDecl *ED) {
121
146
// We can't do anything if the base type has unbound generic parameters.
@@ -130,8 +155,20 @@ static bool isExtensionAppliedInternal(const DeclContext *DC, Type BaseTy,
130
155
if (!ED->isConstrainedExtension ())
131
156
return true ;
132
157
133
- GenericSignature genericSig = ED->getGenericSignature ();
158
+ ProtocolDecl *BaseTypeProtocolDecl = nullptr ;
159
+ if (auto opaqueType = dyn_cast<OpaqueTypeArchetypeType>(BaseTy)) {
160
+ if (opaqueType->getConformsTo ().size () == 1 ) {
161
+ BaseTypeProtocolDecl = opaqueType->getConformsTo ().front ();
162
+ }
163
+ } else {
164
+ BaseTypeProtocolDecl = dyn_cast_or_null<ProtocolDecl>(BaseTy->getAnyNominal ());
165
+ }
166
+
167
+ if (isExtensionWithSelfBound (ED, BaseTypeProtocolDecl)) {
168
+ return true ;
169
+ }
134
170
auto *module = DC->getParentModule ();
171
+ GenericSignature genericSig = ED->getGenericSignature ();
135
172
SubstitutionMap substMap = BaseTy->getContextSubstitutionMap (
136
173
module , ED->getExtendedNominal ());
137
174
return checkRequirements (module ,
@@ -142,7 +179,10 @@ static bool isExtensionAppliedInternal(const DeclContext *DC, Type BaseTy,
142
179
143
180
static bool isMemberDeclAppliedInternal (const DeclContext *DC, Type BaseTy,
144
181
const ValueDecl *VD) {
145
- if (BaseTy->isExistentialType () && VD->isStatic ())
182
+ if (BaseTy->isExistentialType () && VD->isStatic () &&
183
+ !isExtensionWithSelfBound (
184
+ dyn_cast<ExtensionDecl>(VD->getDeclContext ()),
185
+ dyn_cast_or_null<ProtocolDecl>(BaseTy->getAnyNominal ())))
146
186
return false ;
147
187
148
188
// We can't leak type variables into another constraint system.
0 commit comments