Skip to content

Commit 0a2e726

Browse files
committed
[Key paths] Map Hashable conformances for subscript indexes out of context.
When SILGen maps the subscript indices used in a keypath out of context, also map the conformance to Hashable. Fixes rdar://problem/46632723.
1 parent 83ccb23 commit 0a2e726

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3329,6 +3329,48 @@ lowerKeyPathSubscriptIndexTypes(
33293329
}
33303330
};
33313331

3332+
/// Map the given protocol conformance out of context, replacing archetypes
3333+
/// with their corresponding interface types.
3334+
static ProtocolConformance *mapConformanceOutOfContext(
3335+
ProtocolConformance *conformance) {
3336+
if (!conformance->getType()->hasArchetype())
3337+
return conformance;
3338+
3339+
ASTContext &ctx = conformance->getProtocol()->getASTContext();
3340+
switch (conformance->getKind()) {
3341+
case ProtocolConformanceKind::Normal:
3342+
case ProtocolConformanceKind::Self:
3343+
llvm_unreachable("Normal and self conformances never have archetypes");
3344+
3345+
case ProtocolConformanceKind::Inherited: {
3346+
auto inherited = cast<InheritedProtocolConformance>(conformance);
3347+
return ctx.getInheritedConformance(
3348+
inherited->getType()->mapTypeOutOfContext(),
3349+
mapConformanceOutOfContext(inherited->getInheritedConformance()));
3350+
}
3351+
3352+
case ProtocolConformanceKind::Specialized: {
3353+
auto specialized = cast<SpecializedProtocolConformance>(conformance);
3354+
return ctx.getSpecializedConformance(
3355+
specialized->getType()->mapTypeOutOfContext(),
3356+
mapConformanceOutOfContext(specialized->getGenericConformance()),
3357+
specialized->getSubstitutionMap()
3358+
.mapReplacementTypesOutOfContext());
3359+
}
3360+
}
3361+
}
3362+
3363+
/// Map the given protocol conformance out of context, replacing archetypes
3364+
/// with their corresponding interface types.
3365+
static ProtocolConformanceRef mapConformanceOutOfContext(
3366+
ProtocolConformanceRef conformance) {
3367+
if (conformance.isAbstract())
3368+
return conformance;
3369+
3370+
return ProtocolConformanceRef(
3371+
mapConformanceOutOfContext(conformance.getConcrete()));
3372+
}
3373+
33323374
static void
33333375
lowerKeyPathSubscriptIndexPatterns(
33343376
SmallVectorImpl<KeyPathPatternComponent::Index> &indexPatterns,
@@ -3339,10 +3381,9 @@ lowerKeyPathSubscriptIndexPatterns(
33393381
CanType formalTy;
33403382
SILType loweredTy;
33413383
std::tie(formalTy, loweredTy) = indexTypes[i];
3342-
auto hashable = indexHashables[i];
3384+
auto hashable = mapConformanceOutOfContext(indexHashables[i]);
33433385
assert(hashable.isAbstract() ||
3344-
hashable.getConcrete()->getType()->mapTypeOutOfContext()
3345-
->isEqual(formalTy));
3386+
hashable.getConcrete()->getType()->isEqual(formalTy));
33463387

33473388
indexPatterns.push_back({baseOperand++, formalTy, loweredTy, hashable});
33483389
}

test/IRGen/keypath_subscript.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s
2+
3+
// rdar://problem/46632723
4+
public struct Foo<T>: Hashable { }
5+
6+
public struct Bar<U, V> {
7+
public subscript<W> (foo: W) -> Int {
8+
return 0
9+
}
10+
11+
// CHECK-LABEL: define {{.*}} @"$s17keypath_subscript3FooVyqd__Gr0__lTh"
12+
// CHECK: call swiftcc %swift.metadata_response @"$s17keypath_subscript3FooVMa"
13+
public func blah<W>(_: W) -> AnyKeyPath {
14+
return \Bar<U, V>.[Foo<W>()] as AnyKeyPath
15+
}
16+
}
17+

0 commit comments

Comments
 (0)