Skip to content

Commit 66cacf7

Browse files
committed
RequirementMachine: Fix another bug in getTypeFromSubstitutionSchema()
protocol Q { associatedtype T where T == Self? } func foo<X, Y : Q>(_: X, _: Y) {} This generates the rewrite system [Q:T].[concrete: Optional<τ_0_0> with <[Q]>] τ_0_1.[Q] => τ_0_1 With this property map: [Q:T] => { [concrete: Optional<τ_0_0> with <[Q]>] } τ_0_1 => { [Q] } Suppose we're resolving the concrete type τ_0_1.[Q:T]. The property map entry is keyed by [Q:T], so the prefix τ_0_1 must be prepended to the concrete substitutions of [concrete: Optional<τ_0_0> with <[Q]>]. However, [Q] is just the protocol Self type, and τ_0_0.[Q] is not a valid type-like term. We could simplify the term before building the Swift type which would apply the second rewrite rule, but it's easier to just drop the protocol symbol in this case.
1 parent 51b08b6 commit 66cacf7

File tree

2 files changed

+27
-6
lines changed

2 files changed

+27
-6
lines changed

lib/AST/RequirementMachine/PropertyMap.cpp

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,24 @@ static Type getTypeFromSubstitutionSchema(Type schema,
155155
return schema.transformRec([&](Type t) -> Optional<Type> {
156156
if (t->is<GenericTypeParamType>()) {
157157
auto index = getGenericParamIndex(t);
158+
auto substitution = substitutions[index];
158159

159-
// Prepend the prefix of the lookup key to the substitution, skipping
160-
// creation of a new MutableTerm in the case where the prefix is empty.
160+
// Prepend the prefix of the lookup key to the substitution.
161161
if (prefix.empty()) {
162-
return ctx.getTypeForTerm(substitutions[index], genericParams, protos);
163-
} else {
164-
MutableTerm substitution(prefix);
165-
substitution.append(substitutions[index]);
162+
// Skip creation of a new MutableTerm in the case where the
163+
// prefix is empty.
166164
return ctx.getTypeForTerm(substitution, genericParams, protos);
165+
} else if (substitution.size() == 1 &&
166+
substitution[0].getKind() == Symbol::Kind::Protocol) {
167+
// If the prefix is non-empty and the substitution is the
168+
// protocol 'Self' type for some protocol, just use the prefix.
169+
return ctx.getTypeForTerm(prefix, genericParams, protos);
170+
} else {
171+
// Otherwise build a new term by appending the substitution
172+
// to the prefix.
173+
MutableTerm result(prefix);
174+
result.append(substitution);
175+
return ctx.getTypeForTerm(result, genericParams, protos);
167176
}
168177
}
169178

test/Generics/concrete_type_property_of_suffix.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,15 @@ func foo<X : P, Y : P>(_: X, _: Y) {
1414
// Y.T is Optional<Y.U>.
1515
sameType(Y.T.self, Y.U?.self)
1616
}
17+
18+
protocol Q {
19+
associatedtype T where T == Self?
20+
}
21+
22+
func foo<X : Q, Y : Q>(_: X, _: Y) {
23+
// X.T is Optional<X>.
24+
sameType(X.T.self, X?.self)
25+
26+
// Y.T is Optional<Y>.
27+
sameType(Y.T.self, Y?.self)
28+
}

0 commit comments

Comments
 (0)