Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 52 additions & 55 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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<DynamicSelfType>())
substBase = selfType->getSelfType();

// If the parent is an archetype, extract the child archetype with the
// given name.
if (auto archetypeParent = substBase->getAs<ArchetypeType>()) {
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.
Expand All @@ -4413,53 +4403,63 @@ static Type getMemberForBaseType(LookupConformanceFn lookupConformances,
substBase->is<UnresolvedType>())
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<ArchetypeType>()) {
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<TypeAliasType>(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<OpaqueTypeArchetypeType>())
witnessTy = witness.getWitnessDecl()->getDeclaredInterfaceType();
}
}
witnessTy = packConformance->getAssociatedType(
assocType->getDeclaredInterfaceType());
} else if (conformance.isConcrete()) {
auto witness =
conformance.getConcrete()->getTypeWitnessAndDecl(assocType, options);

if (!witnessTy || witnessTy->is<ErrorType>())
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<TypeAliasType>(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<OpaqueTypeArchetypeType>())
witnessTy = witness.getWitnessDecl()->getDeclaredInterfaceType();
}
}

return failed();
if (!witnessTy || witnessTy->is<ErrorType>())
return failed();

return witnessTy;
}

ProtocolConformanceRef LookUpConformanceInModule::
Expand Down Expand Up @@ -4690,9 +4690,6 @@ static Type substType(Type derivedType,
if (auto depMemTy = dyn_cast<DependentMemberType>(type)) {
auto newBase = substType(depMemTy->getBase(),
substitutions, lookupConformances, options);
if (!newBase)
return Type();

return getMemberForBaseType(lookupConformances,
depMemTy->getBase(), newBase,
depMemTy->getAssocType(),
Expand Down