Skip to content

Commit 2ee7464

Browse files
authored
Merge pull request #21267 from DougGregor/keypath-hashable-subscript-indices-5.0
[5.0] [Key paths] Map Hashable conformances for subscript indexes out of context
2 parents bdcc2ec + 45f6014 commit 2ee7464

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
@@ -3322,6 +3322,48 @@ lowerKeyPathSubscriptIndexTypes(
33223322
}
33233323
};
33243324

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

33403381
indexPatterns.push_back({baseOperand++, formalTy, loweredTy, hashable});
33413382
}

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)