Skip to content

Commit f642c3e

Browse files
committed
[PreCheck] Don't use value declared in closure as outer candidate if it's validated
With multi-statement closure inference enabled "outer candidates" hack needs to be careful with its use of `isInvalid()` because some of the declarations lookup finds might be coming from a multi-statement closure that being type-checked, such declarations have to be avoided as candidates, otherwise calling `isInvalid` on them results in a circular type-checking. Resolves: rdar://85843677
1 parent 7d09b30 commit f642c3e

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

lib/Sema/PreCheckExpr.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -749,10 +749,27 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
749749
/*Implicit=*/true);
750750
}
751751

752+
auto isInClosureContext = [&](ValueDecl *decl) -> bool {
753+
auto *DC = decl->getDeclContext();
754+
do {
755+
if (dyn_cast<ClosureExpr>(DC))
756+
return true;
757+
} while ((DC = DC->getParent()));
758+
759+
return false;
760+
};
761+
752762
llvm::SmallVector<ValueDecl *, 4> outerAlternatives;
753763
(void)findNonMembers(Lookup.outerResults(), UDRE->getRefKind(),
754764
/*breakOnMember=*/false, outerAlternatives,
755-
/*isValid=*/[](ValueDecl *choice) -> bool {
765+
/*isValid=*/[&](ValueDecl *choice) -> bool {
766+
// Values that are defined in a closure
767+
// that hasn't been type-checked yet,
768+
// cannot be outer candidates.
769+
if (isInClosureContext(choice)) {
770+
return choice->hasInterfaceType() &&
771+
!choice->isInvalid();
772+
}
756773
return !choice->isInvalid();
757774
});
758775

validation-test/Sema/type_checker_crashers_fixed/rdar85843677.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift
1+
// RUN: %target-typecheck-verify-swift -swift-version 5 -experimental-multi-statement-closures
22

33
func callClosure(closure: () -> ()) {
44
closure()

0 commit comments

Comments
 (0)