Skip to content

Commit d7601b6

Browse files
author
ematejska
authored
Merge pull request #7083 from slavapestov/protocol-typealiases-are-fun-3.1
AST: Fix compareDependentTypes() for protocol typealiases [3.1]
2 parents 42fa720 + 49fef82 commit d7601b6

File tree

4 files changed

+63
-15
lines changed

4 files changed

+63
-15
lines changed

lib/AST/ASTContext.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2926,6 +2926,8 @@ getGenericFunctionRecursiveProperties(Type Input, Type Result) {
29262926
RecursiveTypeProperties properties;
29272927
if (Result->getRecursiveProperties().hasDynamicSelf())
29282928
properties |= RecursiveTypeProperties::HasDynamicSelf;
2929+
if (Result->getRecursiveProperties().hasError())
2930+
properties |= RecursiveTypeProperties::HasError;
29292931
return properties;
29302932
}
29312933

@@ -3133,17 +3135,23 @@ SILFunctionType::SILFunctionType(GenericSignature *genericSig,
31333135

31343136
for (auto param : getParameters()) {
31353137
(void)param;
3138+
assert(!param.getType()->hasError()
3139+
&& "interface type of parameter should not contain error types");
31363140
assert(!param.getType()->hasArchetype()
3137-
&& "interface type of generic type should not contain context archetypes");
3141+
&& "interface type of parameter should not contain context archetypes");
31383142
}
31393143
for (auto result : getAllResults()) {
31403144
(void)result;
3145+
assert(!result.getType()->hasError()
3146+
&& "interface type of result should not contain error types");
31413147
assert(!result.getType()->hasArchetype()
3142-
&& "interface type of generic type should not contain context archetypes");
3148+
&& "interface type of result should not contain context archetypes");
31433149
}
31443150
if (hasErrorResult()) {
3151+
assert(!getErrorResult().getType()->hasError()
3152+
&& "interface type of result should not contain error types");
31453153
assert(!getErrorResult().getType()->hasArchetype()
3146-
&& "interface type of generic type should not contain context archetypes");
3154+
&& "interface type of result should not contain context archetypes");
31473155
}
31483156
}
31493157

lib/AST/ArchetypeBuilder.cpp

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,12 @@ static int compareDependentTypes(
382382
if (a->isGenericParam() != b->isGenericParam())
383383
return a->isGenericParam() ? -1 : +1;
384384

385+
// Typealiases must be ordered *after* everything else, to ensure they
386+
// don't become representatives in the case where a typealias is equated
387+
// with an associated type.
388+
if (!!a->getTypeAliasDecl() != !!b->getTypeAliasDecl())
389+
return a->getTypeAliasDecl() ? +1 : -1;
390+
385391
// - Dependent members
386392
auto ppa = a->getParent();
387393
auto ppb = b->getParent();
@@ -415,17 +421,22 @@ static int compareDependentTypes(
415421
// Make sure typealiases are properly ordered, to avoid crashers.
416422
// FIXME: Ideally we would eliminate typealiases earlier.
417423
if (auto *aa = a->getTypeAliasDecl()) {
418-
if (auto *ab = b->getTypeAliasDecl()) {
419-
// - 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();
422-
if (int compareProtocols
423-
= ProtocolType::compareProtocols(&protoa, &protob))
424-
return compareProtocols;
425-
}
424+
auto *ab = b->getTypeAliasDecl();
425+
assert(ab != nullptr && "Should have handled this case above");
426+
427+
// - by protocol, so t_n_m.`P.T` < t_n_m.`Q.T` (given P < Q)
428+
auto protoa =
429+
aa->getDeclContext()->getAsProtocolOrProtocolExtensionContext();
430+
auto protob =
431+
ab->getDeclContext()->getAsProtocolOrProtocolExtensionContext();
426432

427-
// A resolved archetype is always ordered before an unresolved one.
428-
return -1;
433+
if (int compareProtocols
434+
= ProtocolType::compareProtocols(&protoa, &protob))
435+
return compareProtocols;
436+
437+
// FIXME: Arbitrarily break the result here.
438+
if (aa != ab)
439+
return aa < ab ? -1 : +1;
429440
}
430441

431442
// A resolved archetype is always ordered before an unresolved one.
@@ -518,8 +529,6 @@ auto ArchetypeBuilder::PotentialArchetype::getNestedType(
518529
continue;
519530

520531
auto type = alias->getDeclaredInterfaceType();
521-
SmallVector<Identifier, 4> identifiers;
522-
523532
if (auto existingPA = builder.resolveArchetype(type)) {
524533
builder.addSameTypeRequirementBetweenArchetypes(pa, existingPA,
525534
redundantSource);

test/SILGen/same_type_abstraction.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,20 @@ extension MyProtocol where Data == (ReadData, ReadData) {
3838
return (readData(), readData())
3939
}
4040
}
41+
42+
// Problem with protocol typealiases, which are modeled as same-type
43+
// constraints
44+
45+
protocol Refined : Associated {
46+
associatedtype Key
47+
typealias Assoc = Key
48+
49+
init()
50+
}
51+
52+
extension Refined {
53+
// CHECK-LABEL: sil hidden @_TFE21same_type_abstractionPS_7RefinedCfT12withElementswx3Key_x : $@convention(method) <Self where Self : Refined> (@in Self.Key, @thick Self.Type) -> @out Self
54+
init(withElements newElements: Key) {
55+
self.init()
56+
}
57+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-frontend %s -emit-ir
2+
3+
public protocol QHash : Collection, ExpressibleByArrayLiteral {
4+
associatedtype Key
5+
typealias Element = Key
6+
7+
init()
8+
}
9+
10+
extension QHash {
11+
init(withElements newElements: Key...) {
12+
self.init()
13+
}
14+
}

0 commit comments

Comments
 (0)