diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 5a08ffa8f14d0..865b5a639678a 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -3564,9 +3564,14 @@ bool ArchetypeType::requiresClass() const { Type ArchetypeType::getNestedType(AssociatedTypeDecl *assocType) { Type interfaceType = getInterfaceType(); Type memberInterfaceType = - DependentMemberType::get(interfaceType, assocType->getName()); - return getGenericEnvironment()->getOrCreateArchetypeFromInterfaceType( - memberInterfaceType); + DependentMemberType::get(interfaceType, assocType); + auto genericSig = getGenericEnvironment()->getGenericSignature(); + if (genericSig->isValidTypeParameter(memberInterfaceType)) { + return getGenericEnvironment()->getOrCreateArchetypeFromInterfaceType( + memberInterfaceType); + } + + return Type(); } Type ArchetypeType::getNestedTypeByName(Identifier name) { @@ -4387,24 +4392,9 @@ static Type getMemberForBaseType(LookupConformanceFn lookupConformances, return DependentMemberType::get(baseType, name); }; - // If we don't have a substituted base type, fail. - if (!substBase) return failed(); - if (auto *selfType = substBase->getAs()) substBase = selfType->getSelfType(); - // If the parent is an archetype, extract the child archetype with the - // given name. - if (auto archetypeParent = substBase->getAs()) { - if (Type memberArchetypeByName = archetypeParent->getNestedTypeByName(name)) - return memberArchetypeByName; - - // If looking for an associated type and the archetype is constrained to a - // class, continue to the default associated type lookup - if (!assocType || !archetypeParent->getSuperclass()) - return failed(); - } - // If the parent is a type variable or a member rooted in a type variable, // or if the parent is a type parameter, we're done. Also handle // UnresolvedType here, which can come up in diagnostics. @@ -4413,53 +4403,63 @@ static Type getMemberForBaseType(LookupConformanceFn lookupConformances, substBase->is()) return getDependentMemberType(substBase); - // Retrieve the member type with the given name. + // All remaining cases require an associated type declaration and not just + // the name of a member type. + if (!assocType) + return failed(); - // If we know the associated type, look in the witness table. - if (assocType) { - auto proto = assocType->getProtocol(); - ProtocolConformanceRef conformance = - lookupConformances(origBase->getCanonicalType(), substBase, proto); + // If the parent is an archetype, extract the child archetype with the + // given name. + if (auto archetypeParent = substBase->getAs()) { + if (Type memberArchetypeByName = archetypeParent->getNestedType(assocType)) + return memberArchetypeByName; - if (conformance.isInvalid()) + // If looking for an associated type and the archetype is constrained to a + // class, continue to the default associated type lookup + if (!assocType || !archetypeParent->getSuperclass()) return failed(); + } - Type witnessTy; - - // Retrieve the type witness. - if (conformance.isPack()) { - auto *packConformance = conformance.getPack(); + auto proto = assocType->getProtocol(); + ProtocolConformanceRef conformance = + lookupConformances(origBase->getCanonicalType(), substBase, proto); - witnessTy = packConformance->getAssociatedType( - assocType->getDeclaredInterfaceType()); - } else if (conformance.isConcrete()) { - auto witness = - conformance.getConcrete()->getTypeWitnessAndDecl(assocType, options); + if (conformance.isInvalid()) + return failed(); - witnessTy = witness.getWitnessType(); - if (!witnessTy || witnessTy->hasError()) - return failed(); + Type witnessTy; - // This is a hacky feature allowing code completion to migrate to - // using Type::subst() without changing output. - if (options & SubstFlags::DesugarMemberTypes) { - if (auto *aliasType = dyn_cast(witnessTy.getPointer())) - witnessTy = aliasType->getSinglyDesugaredType(); + // Retrieve the type witness. + if (conformance.isPack()) { + auto *packConformance = conformance.getPack(); - // Another hack. If the type witness is a opaque result type. They can - // only be referred using the name of the associated type. - if (witnessTy->is()) - witnessTy = witness.getWitnessDecl()->getDeclaredInterfaceType(); - } - } + witnessTy = packConformance->getAssociatedType( + assocType->getDeclaredInterfaceType()); + } else if (conformance.isConcrete()) { + auto witness = + conformance.getConcrete()->getTypeWitnessAndDecl(assocType, options); - if (!witnessTy || witnessTy->is()) + witnessTy = witness.getWitnessType(); + if (!witnessTy || witnessTy->hasError()) return failed(); - return witnessTy; + // This is a hacky feature allowing code completion to migrate to + // using Type::subst() without changing output. + if (options & SubstFlags::DesugarMemberTypes) { + if (auto *aliasType = dyn_cast(witnessTy.getPointer())) + witnessTy = aliasType->getSinglyDesugaredType(); + + // Another hack. If the type witness is a opaque result type. They can + // only be referred using the name of the associated type. + if (witnessTy->is()) + witnessTy = witness.getWitnessDecl()->getDeclaredInterfaceType(); + } } - return failed(); + if (!witnessTy || witnessTy->is()) + return failed(); + + return witnessTy; } ProtocolConformanceRef LookUpConformanceInModule:: @@ -4690,9 +4690,6 @@ static Type substType(Type derivedType, if (auto depMemTy = dyn_cast(type)) { auto newBase = substType(depMemTy->getBase(), substitutions, lookupConformances, options); - if (!newBase) - return Type(); - return getMemberForBaseType(lookupConformances, depMemTy->getBase(), newBase, depMemTy->getAssocType(),