Skip to content

Commit 111b236

Browse files
authored
Merge pull request #6917 from DougGregor/compare-dependent-types
2 parents 615800b + 9addec3 commit 111b236

File tree

5 files changed

+58
-30
lines changed

5 files changed

+58
-30
lines changed

include/swift/AST/ArchetypeBuilder.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,9 @@ class ArchetypeBuilder::PotentialArchetype {
574574
PotentialArchetype *getNestedType(Identifier Name,
575575
ArchetypeBuilder &builder);
576576

577+
/// \brief Retrieve (or create) a nested type with a known associated type.
578+
PotentialArchetype *getNestedType(AssociatedTypeDecl *assocType,
579+
ArchetypeBuilder &builder);
577580

578581
/// \brief Retrieve (or build) the type corresponding to the potential
579582
/// archetype within the given generic environment.

lib/AST/ArchetypeBuilder.cpp

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -402,35 +402,46 @@ static int compareDependentTypes(
402402
if (int compareProtocols
403403
= ProtocolType::compareProtocols(&protoa, &protob))
404404
return compareProtocols;
405+
406+
// Error case: if we have two associated types with the same name in the
407+
// same protocol, just tie-break based on address.
408+
if (aa != ab)
409+
return aa < ab ? -1 : +1;
405410
} else {
406411
// A resolved archetype is always ordered before an unresolved one.
407412
return -1;
408413
}
414+
} else {
415+
// A resolved archetype is always ordered before an unresolved one.
416+
if (b->getResolvedAssociatedType())
417+
return +1;
409418
}
410419

411-
// A resolved archetype is always ordered before an unresolved one.
412-
if (b->getResolvedAssociatedType())
413-
return +1;
414-
415420
// Make sure typealiases are properly ordered, to avoid crashers.
416421
// FIXME: Ideally we would eliminate typealiases earlier.
417422
if (auto *aa = a->getTypeAliasDecl()) {
418423
if (auto *ab = b->getTypeAliasDecl()) {
419424
// - by protocol, so t_n_m.`P.T` < t_n_m.`Q.T` (given P < Q)
420-
auto protoa = aa->getDeclContext()->getAsProtocolOrProtocolExtensionContext();
421-
auto protob = ab->getDeclContext()->getAsProtocolOrProtocolExtensionContext();
425+
auto protoa =
426+
aa->getDeclContext()->getAsProtocolOrProtocolExtensionContext();
427+
auto protob =
428+
ab->getDeclContext()->getAsProtocolOrProtocolExtensionContext();
429+
422430
if (int compareProtocols
423431
= ProtocolType::compareProtocols(&protoa, &protob))
424432
return compareProtocols;
425-
}
426433

434+
// FIXME: Arbitrarily break the result here.
435+
if (aa != ab)
436+
return aa < ab ? -1 : +1;
437+
} else {
438+
// A resolved archetype is always ordered before an unresolved one.
439+
return -1;
440+
}
441+
} else if (b->getTypeAliasDecl()) {
427442
// A resolved archetype is always ordered before an unresolved one.
428-
return -1;
429-
}
430-
431-
// A resolved archetype is always ordered before an unresolved one.
432-
if (b->getTypeAliasDecl())
433443
return +1;
444+
}
434445

435446
// Along the error path where one or both of the potential archetypes was
436447
// renamed due to typo correction,
@@ -569,6 +580,12 @@ auto ArchetypeBuilder::PotentialArchetype::getNestedType(
569580
return nested.front();
570581
}
571582

583+
auto ArchetypeBuilder::PotentialArchetype::getNestedType(
584+
AssociatedTypeDecl *assocType,
585+
ArchetypeBuilder &builder) -> PotentialArchetype * {
586+
return getNestedType(assocType->getName(), builder);
587+
}
588+
572589
Type ArchetypeBuilder::PotentialArchetype::getTypeInContext(
573590
ArchetypeBuilder &builder,
574591
GenericEnvironment *genericEnv) {
@@ -913,6 +930,9 @@ auto ArchetypeBuilder::resolveArchetype(Type type) -> PotentialArchetype * {
913930
if (!base)
914931
return nullptr;
915932

933+
if (auto assocType = dependentMember->getAssocType())
934+
return base->getNestedType(assocType, *this);
935+
916936
return base->getNestedType(dependentMember->getName(), *this);
917937
}
918938

@@ -1003,7 +1023,7 @@ bool ArchetypeBuilder::addConformanceRequirement(PotentialArchetype *PAT,
10031023
for (auto Member : Proto->getMembers()) {
10041024
if (auto AssocType = dyn_cast<AssociatedTypeDecl>(Member)) {
10051025
// Add requirements placed directly on this associated type.
1006-
auto AssocPA = T->getNestedType(AssocType->getName(), *this);
1026+
auto AssocPA = T->getNestedType(AssocType, *this);
10071027
if (AssocPA != T) {
10081028
if (addAbstractTypeParamRequirements(AssocType, AssocPA,
10091029
RequirementSource::Protocol,

lib/AST/GenericSignature.cpp

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -389,10 +389,16 @@ getSubstitutions(TypeSubstitutionFn subs,
389389
for (auto req: reqs) {
390390
assert(req.getKind() == RequirementKind::Conformance);
391391
auto protoType = req.getSecondType()->castTo<ProtocolType>();
392-
// TODO: Error handling for failed conformance lookup.
393-
currentConformances.push_back(
394-
*lookupConformance(depTy->getCanonicalType(), currentReplacement,
395-
protoType));
392+
if (auto conformance = lookupConformance(depTy->getCanonicalType(),
393+
currentReplacement,
394+
protoType)) {
395+
currentConformances.push_back(*conformance);
396+
} else {
397+
if (!currentReplacement->hasError())
398+
currentReplacement = ErrorType::get(currentReplacement);
399+
currentConformances.push_back(
400+
ProtocolConformanceRef(protoType->getDecl()));
401+
}
396402
}
397403

398404
// Add it to the final substitution list.
@@ -605,21 +611,22 @@ CanType GenericSignature::getCanonicalTypeInContext(Type type,
605611
return CanType(type);
606612

607613
// Replace non-canonical type parameters.
608-
type = type.transform([&](Type component) -> Type {
609-
if (!component->isTypeParameter()) return component;
614+
type = type.transformRec([&](TypeBase *component) -> Optional<Type> {
615+
if (!isa<GenericTypeParamType>(component) &&
616+
!isa<DependentMemberType>(component))
617+
return None;
610618

611619
// Resolve the potential archetype. This can be null in nested generic
612620
// types, which we can't immediately canonicalize.
613-
auto pa = builder.resolveArchetype(component);
614-
if (!pa) return component;
621+
auto pa = builder.resolveArchetype(Type(component));
622+
if (!pa) return None;
615623

616624
auto rep = pa->getArchetypeAnchor();
617625
if (rep->isConcreteType()) {
618626
return getCanonicalTypeInContext(rep->getConcreteType(), builder);
619-
} else {
620-
return rep->getDependentType(getGenericParams(),
621-
/*allowUnresolved*/ false);
622627
}
628+
629+
return rep->getDependentType(getGenericParams(), /*allowUnresolved*/ false);
623630
});
624631

625632
auto result = type->getCanonicalType();

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Type DependentGenericTypeResolver::resolveSelfAssociatedType(
5555
assert(archetype && "Bad generic context nesting?");
5656

5757
return archetype
58-
->getNestedType(assocType->getName(), Builder)
58+
->getNestedType(assocType, Builder)
5959
->getDependentType(/*FIXME: */{ }, /*allowUnresolved=*/true);
6060
}
6161

@@ -214,7 +214,7 @@ Type CompleteGenericTypeResolver::resolveDependentMemberType(
214214
Type CompleteGenericTypeResolver::resolveSelfAssociatedType(
215215
Type selfTy, AssociatedTypeDecl *assocType) {
216216
return Builder.resolveArchetype(selfTy)
217-
->getNestedType(assocType->getName(), Builder)
217+
->getNestedType(assocType, Builder)
218218
->getDependentType(/*FIXME: */{ }, /*allowUnresolved=*/false);
219219
}
220220

test/Generics/associated_type_typo.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,10 @@ func typoAssoc4<T : P2>(_: T) where T.Assocp2.assoc : P3 {}
3939
// CHECK-GENERIC-LABEL: .typoAssoc4@
4040
// CHECK-GENERIC-NEXT: Requirements:
4141
// CHECK-GENERIC-NEXT: T : P2 [explicit
42-
// CHECK-GENERIC-NEXT: T[.P2].AssocP2 == T[.P2].AssocP2 [redundant]
4342
// CHECK-GENERIC-NEXT: T[.P2].AssocP2 : P1 [protocol
44-
// CHECK-GENERIC-NEXT: T[.P2].AssocP2[.P1].Assoc == T[.P2].AssocP2[.P1].Assoc [redundant
43+
// CHECK-GENERIC-NEXT: T[.P2].AssocP2 == T[.P2].AssocP2 [redundant]
4544
// CHECK-GENERIC-NEXT: T[.P2].AssocP2[.P1].Assoc : P3 [explicit
46-
// CHECK-GENERIC-NEXT: T[.P2].AssocP2[.P1].Assoc == T[.P2].AssocP2[.P1].Assoc [redundant]
45+
// CHECK-GENERIC-NEXT: T[.P2].AssocP2[.P1].Assoc == T[.P2].AssocP2[.P1].Assoc [redundant
4746
// CHECK-GENERIC-NEXT: Generic signature
4847

4948
// <rdar://problem/19620340>
@@ -73,7 +72,6 @@ protocol Pattern {
7372
associatedtype Element : Equatable
7473

7574
// FIXME: Diagnostics here are very poor
76-
// expected-error@+4{{'C.Slice' does not have a member type named 'Iterator'; did you mean 'Slice'?}}
7775
// expected-error@+3{{'C' does not have a member type named 'Iterator'; did you mean 'Slice'?}}
7876
// expected-error@+2{{'C.Slice' does not have a member type named 'Element'; did you mean 'Slice'?}}
7977
// expected-error@+1{{'C.Slice' does not have a member type named 'Iterator'; did you mean 'Slice'?}}

0 commit comments

Comments
 (0)