Skip to content

Commit 8aaa553

Browse files
committed
Sema: Explicitly infer requirements from subscript element type for materializeForSet
The interface type for materializeForSet does not mention the element type of a subscript, so Sema was not inferring requirements that were implied by the element type but not explicitly stated in the generic signature. This led to assertion failures in SILGen because the materializeForSet calls the getter and setter, which does have these requirements. Fixes <rdar://problem/33219034>, <https://bugs.swift.org/browse/SR-5420>.
1 parent 2edf2b2 commit 8aaa553

File tree

2 files changed

+42
-0
lines changed

2 files changed

+42
-0
lines changed

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,26 @@ static bool checkGenericFuncSignature(TypeChecker &tc,
555555
source);
556556
}
557557
}
558+
559+
// If this is a materializeForSet, infer requirements from the
560+
// storage type instead, since it's not part of the accessor's
561+
// type signature.
562+
if (fn->getAccessorKind() == AccessorKind::IsMaterializeForSet) {
563+
if (builder) {
564+
auto *storage = fn->getAccessorStorageDecl();
565+
if (auto *subscriptDecl = dyn_cast<SubscriptDecl>(storage)) {
566+
auto source =
567+
GenericSignatureBuilder::FloatingRequirementSource::forInferred(
568+
subscriptDecl->getElementTypeLoc().getTypeRepr(),
569+
/*quietly=*/true);
570+
571+
TypeLoc type(nullptr, subscriptDecl->getElementInterfaceType());
572+
assert(type.getType());
573+
builder->inferRequirements(*func->getParentModule(),
574+
type, source);
575+
}
576+
}
577+
}
558578
}
559579

560580
return badType;

test/SILGen/materializeForSet.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,28 @@ extension GenericSubscriptProtocol {
466466

467467
struct GenericSubscriptDefaultWitness : GenericSubscriptProtocol { }
468468

469+
// Make sure we correctly infer the 'T : Magic' requirement on all the accessors
470+
// of the subscript.
471+
472+
struct GenericTypeWithRequirement<T : Magic> {}
473+
474+
protocol InferredRequirementOnSubscriptProtocol {
475+
subscript<T>(i: Int) -> GenericTypeWithRequirement<T> { get set }
476+
}
477+
478+
struct InferredRequirementOnSubscript : InferredRequirementOnSubscriptProtocol {
479+
subscript<T>(i: Int) -> GenericTypeWithRequirement<T> {
480+
get { }
481+
set { }
482+
}
483+
}
484+
485+
// CHECK-LABEL: sil hidden @_T017materializeForSet30InferredRequirementOnSubscriptV9subscriptAA015GenericTypeWithE0VyxGSicAA5MagicRzlufg : $@convention(method) <T where T : Magic> (Int, InferredRequirementOnSubscript) -> GenericTypeWithRequirement<T>
486+
487+
// CHECK-LABEL: sil hidden @_T017materializeForSet30InferredRequirementOnSubscriptV9subscriptAA015GenericTypeWithE0VyxGSicAA5MagicRzlufs : $@convention(method) <T where T : Magic> (GenericTypeWithRequirement<T>, Int, @inout InferredRequirementOnSubscript) -> ()
488+
489+
// CHECK-LABEL: sil hidden [transparent] @_T017materializeForSet30InferredRequirementOnSubscriptV9subscriptAA015GenericTypeWithE0VyxGSicAA5MagicRzlufm : $@convention(method) <T where T : Magic> (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, Int, @inout InferredRequirementOnSubscript) -> (Builtin.RawPointer, Optional<Builtin.RawPointer>)
490+
469491
// Test for materializeForSet vs static properties of structs.
470492

471493
protocol Beverage {

0 commit comments

Comments
 (0)