SILGen: Fix verifier error when forming keypath to subscript with resilient index type

emitKeyPathSubscriptOperands() uses the ArgEmitter to collect
index arguments, which uses ResilienceExpansion::Minimal when
lowering parameter types.

For this reason, lowerKeyPathSubscriptIndexTypes() should also
use ResilienceExpansion::Minimal when lowering parameter types.

Otherwise, we crash in the SIL verifier due to a loadable vs
address-only mismatch, if the index type is resilient.

Fixes rdar://problem/144654366.
Fixes https://github.com/swiftlang/swift/issues/79304.
This commit is contained in:
Slava Pestov
2025-02-11 22:08:21 -05:00
parent 5a3327c829
commit 68bdfa81e3
2 changed files with 21 additions and 3 deletions

View File

@@ -4098,7 +4098,6 @@ lowerKeyPathSubscriptIndexTypes(
SmallVectorImpl<IndexTypePair> &indexPatterns,
SubscriptDecl *subscript,
SubstitutionMap subscriptSubs,
ResilienceExpansion expansion,
bool &needsGenericContext) {
// Capturing an index value dependent on the generic context means we
// need the generic context captured in the key path.
@@ -4118,7 +4117,8 @@ lowerKeyPathSubscriptIndexTypes(
auto indexLoweredTy = SGM.Types.getLoweredType(
AbstractionPattern::getOpaque(), indexTy,
TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(expansion));
TypeExpansionContext::noOpaqueTypeArchetypesSubstitution(
ResilienceExpansion::Minimal));
indexLoweredTy = indexLoweredTy.mapTypeOutOfContext();
indexPatterns.push_back({indexTy->mapTypeOutOfContext()
->getCanonicalType(),
@@ -4347,7 +4347,6 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
SmallVector<IndexTypePair, 4> indexTypes;
lowerKeyPathSubscriptIndexTypes(*this, indexTypes,
decl, subs,
expansion,
needsGenericContext);
SmallVector<KeyPathPatternComponent::Index, 4> indexPatterns;

View File

@@ -0,0 +1,19 @@
// RUN: %target-swift-emit-silgen %s -enable-library-evolution | %FileCheck %s
public enum E: Hashable {
case e
}
public struct S {
public var dict: [E: Int] = [:]
}
public func f() {
let _ = \S.dict[.e]
}
// CHECK-LABEL: sil [ossa] @$s18keypaths_resilient1fyyF : $@convention(thin) () -> () {
// CHECK: [[ARG:%.*]] = alloc_stack $E
// CHECK: store %1 to [trivial] [[ARG]]
// CHECK: {{%.*}} = keypath $WritableKeyPath<S, Optional<Int>>, (root $S; stored_property #S.dict : $Dictionary<E, Int>; settable_property $Optional<Int>, id @$sSDyq_Sgxcig : $@convention(method) <τ_0_0, τ_0_1 where τ_0_0 : Hashable> (@in_guaranteed τ_0_0, @guaranteed Dictionary<τ_0_0, τ_0_1>) -> @out Optional<τ_0_1>, getter @$sSDyq_SgxcipSDy18keypaths_resilient1EOSiGADSiTK : $@convention(keypath_accessor_getter) (@in_guaranteed Dictionary<E, Int>, @in_guaranteed E) -> @out Optional<Int>, setter @$sSDyq_SgxcipSDy18keypaths_resilient1EOSiGADSiTk : $@convention(keypath_accessor_setter) (@in_guaranteed Optional<Int>, @inout Dictionary<E, Int>, @in_guaranteed E) -> (), indices [%$0 : $E : $*E], indices_equals @$s18keypaths_resilient1EOTH : $@convention(keypath_accessor_equals) (@in_guaranteed E, @in_guaranteed E) -> Bool, indices_hash @$s18keypaths_resilient1EOTh : $@convention(keypath_accessor_hash) (@in_guaranteed E) -> Int, external #Dictionary.subscript<E, Int>) ([[ARG]])
// CHECK: return