Skip to content

Commit 56c67f9

Browse files
committed
Sema: Visit types of captures to determine if a closure captures the generic signature
Otherwise, we can miss that 'self' has a generic type when accessed via a 'super' call if the type of 'super' is concrete. This is a regression from a patch series to allow C function pointers to be formed from closures in generic contexts -- basically, the check was not conservative enough, and in this case, it would conclude the closure did not capture the generic signature when in reality it did: 533f42d Fixes <rdar://problem/25439564>.
1 parent cd8254f commit 56c67f9

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

lib/Sema/TypeCheckExpr.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,13 @@ namespace {
812812
captureList[entryNumber-1] = capture;
813813
}
814814

815+
// Visit the type of the capture. If we capture 'self' via a 'super' call,
816+
// and the superclass is not generic, there might not be any generic
817+
// parameter types in the closure body, so we have to account for them
818+
// here.
819+
if (VD->hasType())
820+
checkType(VD->getType());
821+
815822
// If VD is a noescape decl, then the closure we're computing this for
816823
// must also be noescape.
817824
if (VD->getAttrs().hasAttribute<NoEscapeAttr>() &&

test/SILGen/closures.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,3 +564,25 @@ class UnownedSelfNestedCapture {
564564
{[unowned self] in { self } }()()
565565
}
566566
}
567+
568+
// Check that capturing 'self' via a 'super' call also captures the generic
569+
// signature if the base class is concrete and the derived class is generic
570+
571+
class ConcreteBase {
572+
func swim() {}
573+
}
574+
575+
// CHECK-LABEL: sil shared @_TFFC8closures14GenericDerived4swimFT_T_U_FT_T_ : $@convention(thin) <Ocean> (@owned GenericDerived<Ocean>) -> ()
576+
// CHECK: [[SUPER:%.*]] = upcast %0 : $GenericDerived<Ocean> to $ConcreteBase
577+
// CHECK: [[METHOD:%.*]] = function_ref @_TFC8closures12ConcreteBase4swimfT_T_
578+
// CHECK: apply [[METHOD]]([[SUPER]]) : $@convention(method) (@guaranteed ConcreteBase) -> ()
579+
580+
class GenericDerived<Ocean> : ConcreteBase {
581+
override func swim() {
582+
withFlotationAid {
583+
super.swim()
584+
}
585+
}
586+
587+
func withFlotationAid(fn: () -> ()) {}
588+
}

0 commit comments

Comments
 (0)