@@ -193,23 +193,6 @@ void TypeChecker::forceExternalDeclMembers(NominalTypeDecl *nominalDecl) {
193193 }
194194}
195195
196- static Optional<Type>
197- resolveAssociatedTypeInContext (TypeChecker &TC, AssociatedTypeDecl *assocType,
198- DeclContext *DC, GenericTypeResolver *resolver) {
199- auto protoSelf = DC->getProtocolSelf ();
200- auto selfTy = protoSelf->getDeclaredType ()->castTo <GenericTypeParamType>();
201- auto baseTy = resolver->resolveGenericTypeParamType (selfTy);
202-
203- if (baseTy->isTypeParameter ())
204- return resolver->resolveSelfAssociatedType (baseTy, DC, assocType);
205-
206- if (assocType->getDeclContext () != DC)
207- return TC.substMemberTypeWithBase (DC->getParentModule (), assocType,
208- protoSelf->getArchetype (),
209- /* isTypeReference=*/ true );
210- return None;
211- }
212-
213196Type TypeChecker::resolveTypeInContext (
214197 TypeDecl *typeDecl,
215198 DeclContext *fromDC,
@@ -239,15 +222,12 @@ Type TypeChecker::resolveTypeInContext(
239222 nominalType = nullptr ;
240223 }
241224
242- // Walk up through the type scopes to find the context where the type
243- // declaration was found. When we find it, substitute the appropriate base
244- // type.
225+ // Walk up through the type scopes to find the context containing the type
226+ // being resolved.
245227 auto ownerDC = typeDecl->getDeclContext ();
246228 bool nonTypeOwner = !ownerDC->isTypeContext ();
247229 auto ownerNominal = ownerDC->getAsNominalTypeOrNominalTypeExtensionContext ();
248230 auto assocType = dyn_cast<AssociatedTypeDecl>(typeDecl);
249- auto alias = dyn_cast<TypeAliasDecl>(typeDecl);
250- DeclContext *typeParent = nullptr ;
251231 assert ((ownerNominal || nonTypeOwner) &&
252232 " Owner must be a nominal type or a non type context" );
253233
@@ -273,140 +253,126 @@ Type TypeChecker::resolveTypeInContext(
273253 return typeDecl->getDeclaredType ();
274254
275255 // For the next steps we need our parentDC to be a type context
276- if (!parentDC->isTypeContext ()) {
256+ if (!parentDC->isTypeContext ())
277257 continue ;
278- } else if (!typeParent) {
279- // Remember the first type decl context in the hierarchy for later use
280- typeParent = parentDC;
281- }
282-
283- // If we found an associated type in an inherited protocol, the base for our
284- // reference to this associated type is our own `Self`. If we can't resolve
285- // the associated type during this iteration, try again on the next.
286- if (assocType) {
287- if ( auto proto = parentDC-> getAsProtocolOrProtocolExtensionContext ()) {
288- auto assocProto = assocType-> getProtocol ();
289- if (proto == assocProto || proto-> inheritsFrom (assocProto)) {
290- // If the associated type is from our own protocol or we inherit from
291- // the associated type's protocol, resolve it
292- if ( auto resolved = resolveAssociatedTypeInContext (
293- * this , assocType, parentDC, resolver))
294- return *resolved ;
295-
296- } else if (auto ED = dyn_cast<ExtensionDecl>(parentDC )) {
297- // Otherwise, if we are in an extension there might be other
298- // associated types brought into the context through
299- // `extension ... where Self : SomeProtocol`
300- for ( auto req : ED-> getGenericParams ()-> getTrailingRequirements ()) {
301- // Reject requirements other than constraints with an subject other
302- // than `Self`
303- if ( req.getKind () != RequirementReprKind::TypeConstraint ||
304- !req.getSubject ()->castTo <ArchetypeType>()->isSelfDerived ())
258+
259+ // Search the type of this context and its supertypes (if its a
260+ // class) or refined protocols (if its a protocol).
261+ llvm::SmallPtrSet< const NominalTypeDecl *, 8 > visited;
262+ llvm::SmallVector<Type, 8 > stack;
263+
264+ // Start with the type of the current context.
265+ if ( auto fromType = resolver-> resolveTypeOfContext (parentDC))
266+ stack. push_back (fromType);
267+
268+ // If we are in a protocol extension there might be other type aliases and
269+ // nominal types brought into the context through requirements on Self,
270+ // for example:
271+ //
272+ // extension MyProtocol where Self : YourProtocol { ... }
273+ if ( parentDC-> getAsProtocolExtensionContext ()) {
274+ auto ED = cast<ExtensionDecl>(parentDC) ;
275+ if ( auto genericParams = ED-> getGenericParams ()) {
276+ for (auto req : genericParams-> getTrailingRequirements ( )) {
277+ // We might be resolving 'req.getSubject()' itself.
278+ // This whole case feels like a hack -- there should be a
279+ // more principled way to represent extensions of protocol
280+ // compositions.
281+ if (req. getKind () == RequirementReprKind::TypeConstraint) {
282+ if (!req. getSubject () ||
283+ ! req.getSubject ()-> is <ArchetypeType>() ||
284+ !req.getSubject ()->castTo <ArchetypeType>()->getSelfProtocol ())
305285 continue ;
306286
307- // If the associated type is defined in the same protocol which is
308- // required for this extension, or if the required protocol inherits
309- // from the protocol the associated type is declared in, we can
310- // resolve the associated type with our `Self` as the reference
311- // point.
312- auto reqProto =
313- req.getConstraint ()->castTo <ProtocolType>()->getDecl ();
314- if (reqProto == assocProto || reqProto->inheritsFrom (assocProto)) {
315- if (auto resolved = resolveAssociatedTypeInContext (
316- *this , assocType, parentDC, resolver))
317- return *resolved;
318- break ;
319- }
287+ stack.push_back (req.getConstraint ());
320288 }
321289 }
322290 }
323291 }
324-
325- // If we found an alias type in an inherited protocol, resolve it based on our
326- // own `Self`.
327- if (alias && alias->hasInterfaceType ()) {
328- auto metaType = alias->getInterfaceType ()->getAs <MetatypeType>();
329- auto memberType = metaType ? metaType->getInstanceType ()->getAs <DependentMemberType>() :
330- nullptr ;
331-
332- if (memberType && parentDC->getAsProtocolOrProtocolExtensionContext ()) {
333- auto protoSelf = parentDC->getProtocolSelf ();
334- auto selfTy = protoSelf->getDeclaredType ()->castTo <GenericTypeParamType>();
335- auto baseTy = resolver->resolveGenericTypeParamType (selfTy);
336-
337- SmallVector<DependentMemberType *, 4 > memberTypes;
338- do {
339- memberTypes.push_back (memberType);
340- memberType = memberType->getBase ()->getAs <DependentMemberType>();
341- } while (memberType);
342-
343- auto module = parentDC->getParentModule ();
344- while (memberTypes.size ()) {
345- baseTy = memberTypes.back ()->substBaseType (module , baseTy, nullptr );
346- memberTypes.pop_back ();
347- }
348- return baseTy;
349- }
350- }
351292
352- // Search the type of this context and its supertypes.
353- llvm::SmallPtrSet<const NominalTypeDecl *, 8 > visited;
354- for (auto fromType = resolver->resolveTypeOfContext (parentDC);
355- fromType;
356- fromType = getSuperClassOf (fromType)) {
293+ while (!stack.empty ()) {
294+ auto fromType = stack.back ();
295+ auto *fromProto = parentDC->getAsProtocolOrProtocolExtensionContext ();
296+
297+ stack.pop_back ();
298+
357299 // If we hit circularity, we will diagnose at some point in typeCheckDecl().
358300 // However we have to explicitly guard against that here because we get
359301 // called as part of validateDecl().
360302 if (!visited.insert (fromType->getAnyNominal ()).second )
361- break ;
303+ continue ;
304+
305+ // Handle this case:
306+ // - Current context: concrete type
307+ // - Nested type: associated type
308+ // - Nested type's context: protocol or protocol extension
309+ //
310+ if (assocType && fromProto == nullptr ) {
311+ ProtocolConformance *conformance = nullptr ;
312+
313+ // If the conformance check failed, the associated type is for a
314+ // conformance of an outer context.
315+ if (!options.contains (TR_InheritanceClause) &&
316+ conformsToProtocol (fromType,
317+ cast<ProtocolDecl>(ownerNominal),
318+ parentDC, ConformanceCheckFlags::Used,
319+ &conformance) &&
320+ conformance) {
321+ return conformance->getTypeWitness (assocType, this ).getReplacement ();
322+ }
323+ }
362324
363- // If the nominal type declaration of the context type we're looking at
364- // matches the owner's nominal type declaration, this is how we found
365- // the member type declaration. Substitute the type we're coming from as
366- // the base of the member type to produce the projected type result.
325+ // Handle these cases:
326+ // - Current context: concrete type
327+ // - Nested type: concrete type or type alias
328+ // - Nested type's context: concrete type
329+ //
330+ // - Current context: protocol or protocol extension
331+ // - Nested type: type alias
332+ // - Nested type's context: protocol or protocol extension
333+ //
334+ // Note: this is not supported yet, FIXME:
335+ // - Current context: concrete type
336+ // - Nested type: type alias
337+ // - Nested type's context: protocol or protocol extension
338+ //
367339 if (fromType->getAnyNominal () == ownerNominal) {
368- // If we are referring into a protocol or extension thereof,
369- // the base type is the 'Self'.
370- if (ownerDC->getAsProtocolOrProtocolExtensionContext ()) {
371- auto selfTy = ownerDC->getProtocolSelf ()->getDeclaredType ()
372- ->castTo <GenericTypeParamType>();
373- fromType = resolver->resolveGenericTypeParamType (selfTy);
340+ if (fromProto &&
341+ ownerNominal->getAsProtocolOrProtocolExtensionContext ()) {
342+ // If we are looking up an associated type or a protocol's type alias
343+ // from a protocol or protocol extension, use the archetype for 'Self'
344+ // instead of the existential type.
345+ assert (fromType->is <ProtocolType>());
346+
347+ auto protoSelf = parentDC->getProtocolSelf ();
348+ auto selfType = protoSelf
349+ ->getDeclaredType ()
350+ ->castTo <GenericTypeParamType>();
351+ fromType = resolver->resolveGenericTypeParamType (selfType);
352+
353+ if (assocType) {
354+ // Odd special case, ask Doug to explain it over pizza one day
355+ if (fromType->isTypeParameter ())
356+ return resolver->resolveSelfAssociatedType (
357+ fromType, parentDC, assocType);
358+ }
374359 }
375360
376- // Perform the substitution.
377361 return substMemberTypeWithBase (parentDC->getParentModule (), typeDecl,
378362 fromType, /* isTypeReference=*/ true );
379363 }
380364
381- ProtocolConformance *conformance = nullptr ;
382- if (assocType &&
383- !options.contains (TR_InheritanceClause) &&
384- conformsToProtocol (fromType,
385- cast<ProtocolDecl>(assocType->getDeclContext ()),
386- parentDC, ConformanceCheckFlags::Used,
387- &conformance) &&
388- conformance) {
389- return conformance->getTypeWitness (assocType, this ).getReplacement ();
365+ if (auto superclassTy = getSuperClassOf (fromType))
366+ stack.push_back (superclassTy);
367+ else if (auto protoTy = fromType->getAs <ProtocolType>()) {
368+ for (auto *proto : protoTy->getDecl ()->getInheritedProtocols (this ))
369+ if (auto refinedTy = proto->getDeclaredTypeInContext ())
370+ stack.push_back (refinedTy);
390371 }
391372 }
392373 }
393374
394- // At this point by iterating through the decl context hierarchy we should
395- // have encountered the first type context in the stack.
396- assert (typeParent && " incomplete iteration" );
397- assert (!typeParent->isModuleContext ());
398-
399- // Substitute in the appropriate type for 'Self'.
400- // FIXME: We shouldn't have to guess here; the caller should tell us.
401- Type fromType;
402- if (typeParent->getAsProtocolOrProtocolExtensionContext ())
403- fromType = typeParent->getProtocolSelf ()->getArchetype ();
404- else
405- fromType = resolver->resolveTypeOfContext (typeParent);
406-
407- // Perform the substitution.
408- return substMemberTypeWithBase (typeParent->getParentModule (), typeDecl,
409- fromType, /* isTypeReference=*/ true );
375+ llvm_unreachable (" Cannot resolve type" );
410376}
411377
412378Type TypeChecker::applyGenericArguments (Type type, SourceLoc loc,
@@ -537,7 +503,8 @@ Type TypeChecker::applyUnboundGenericArguments(
537503
538504 // Check the generic arguments against the generic signature.
539505 auto genericSig = unbound->getDecl ()->getGenericSignature ();
540- if (unbound->getDecl ()->isValidatingGenericSignature ()) {
506+ if (!unbound->getDecl ()->hasType () ||
507+ unbound->getDecl ()->isValidatingGenericSignature ()) {
541508 diagnose (loc, diag::recursive_requirement_reference);
542509 return nullptr ;
543510 }
@@ -2474,7 +2441,6 @@ Type TypeChecker::substMemberTypeWithBase(Module *module,
24742441 Type memberType = isTypeReference
24752442 ? cast<TypeDecl>(member)->getDeclaredInterfaceType ()
24762443 : member->getInterfaceType ();
2477-
24782444 if (isTypeReference) {
24792445 // The declared interface type for a generic type will have the type
24802446 // arguments; strip them off.
0 commit comments