diff --git a/lib/AST/GenericSignatureBuilder.cpp b/lib/AST/GenericSignatureBuilder.cpp index 4b08216270f95..136106b9c69c2 100644 --- a/lib/AST/GenericSignatureBuilder.cpp +++ b/lib/AST/GenericSignatureBuilder.cpp @@ -48,6 +48,8 @@ #include "llvm/Support/SaveAndRestore.h" #include +#include + using namespace swift; using llvm::DenseMap; @@ -3625,6 +3627,8 @@ ResolvedType GenericSignatureBuilder::maybeResolveEquivalenceClass( Type type, ArchetypeResolutionKind resolutionKind, bool wantExactPotentialArchetype) { + type->dump(); + // An error type is best modeled as an unresolved potential archetype, since // there's no way to be sure what it is actually meant to be. if (type->is()) { @@ -3633,12 +3637,16 @@ ResolvedType GenericSignatureBuilder::maybeResolveEquivalenceClass( // The equivalence class of a generic type is known directly. if (auto genericParam = type->getAs()) { + std::cout << "0" << std::endl; unsigned index = GenericParamKey(genericParam).findIndexIn( getGenericParams()); + std::cout << "1" << std::endl; if (index < Impl->GenericParams.size()) { + std::cout << "2" << std::endl; return ResolvedType(Impl->PotentialArchetypes[index]); } + std::cout << "3" << std::endl; return ResolvedType::forUnresolved(nullptr); } @@ -3646,6 +3654,7 @@ ResolvedType GenericSignatureBuilder::maybeResolveEquivalenceClass( // base equivalence class, if there is one. if (auto depMemTy = type->getAs()) { // Find the equivalence class of the base. + std::cout << "4" << std::endl; auto resolvedBase = maybeResolveEquivalenceClass(depMemTy->getBase(), resolutionKind, @@ -4850,6 +4859,16 @@ ConstraintResult GenericSignatureBuilder::addSameTypeRequirement( FloatingRequirementSource source, UnresolvedHandlingKind unresolvedHandling, llvm::function_ref diagnoseMismatch) { + + if (paOrT1.is()) + paOrT1.get()->dump(); + if (paOrT1.is()) + paOrT1.get()->dump(); + + if (paOrT2.is()) + paOrT2.get()->dump(); + if (paOrT2.is()) + paOrT2.get()->dump(); auto resolved1 = resolve(paOrT1, source); if (!resolved1) { diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index a5ed86edb2b5b..23272fe63c7cf 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -47,6 +47,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/SaveAndRestore.h" +#include using namespace swift; @@ -566,8 +567,7 @@ Type TypeChecker::resolveTypeInContext(TypeDecl *typeDecl, DeclContext *foundDC, if (selfType->is()) { if (typeDecl->getDeclContext()->getSelfProtocolDecl()) { if (isa(typeDecl) || - (isa(typeDecl) && - !cast(typeDecl)->isGeneric())) { + typeDecl->getAsGenericContext()) { // FIXME: We should use this lookup method for the Interface // stage too, but right now that causes problems with // Sequence.SubSequence vs Collection.SubSequence; the former @@ -576,10 +576,16 @@ Type TypeChecker::resolveTypeInContext(TypeDecl *typeDecl, DeclContext *foundDC, // because we use the Sequence.SubSequence default instead of // the Collection.SubSequence default, even when the conforming // type wants to conform to Collection. +// selfType->dump(); +// typeDecl->dump(); +// std::cout << typeDecl->getName().get() << std::endl; + if (resolution.getStage() == TypeResolutionStage::Structural) { return resolution.resolveSelfAssociatedType(selfType, foundDC, typeDecl->getName()); - } else if (auto assocType = dyn_cast(typeDecl)) { + } + + if (auto assocType = dyn_cast(typeDecl)) { typeDecl = assocType->getAssociatedTypeAnchor(); } } @@ -1295,10 +1301,23 @@ resolveTopLevelIdentTypeComponent(TypeResolution resolution, // Otherwise, check for an ambiguity. if (!resolution.areSameType(current, type)) { isAmbiguous = true; - break; + // If a typealias collides with an associatedtype in generic requirement + // position, prefer the associated type. + if (options.getContext() == TypeResolverContext::GenericRequirement) { + if (isa(currentDecl) && isa(typeDecl)) { + current = type; + currentDecl = typeDecl; + currentDC = foundDC; + isAmbiguous = false; + } else if (isa(currentDecl) && + isa(typeDecl)) { + isAmbiguous = false; + } + } + if (isAmbiguous) break; } - // We have a found multiple type aliases that refer to the same thing. + // We have found multiple type aliases that refer to the same thing. // Ignore the duplicate. } diff --git a/validation-test/compiler_crashers_2_fixed/sr11639.swift b/validation-test/compiler_crashers_2_fixed/sr11639.swift new file mode 100644 index 0000000000000..4d0cca842c837 --- /dev/null +++ b/validation-test/compiler_crashers_2_fixed/sr11639.swift @@ -0,0 +1,16 @@ +// RUN: %target-typecheck-verify-swift + +protocol ProtocolA { + associatedtype T1 +} + +struct S : ProtocolA { + typealias T1 = T +} + +protocol ProtocolB: ProtocolA { + associatedtype T2: ProtocolB where T2.T1 == T3.T1 + associatedtype X + typealias T3 = S +} +