Skip to content

Commit 64bca8a

Browse files
committed
[CSGen] Detect nested out-of-scope variables in recursive declarations
Follow-up to swiftlang#63505 Since, when the type is not stated, a variable assumes the type of its initializer that enables out-of-scope variables to be nested inside of some other concrete type i.e. Optional. Resolves: swiftlang#63455
1 parent fad0f90 commit 64bca8a

File tree

2 files changed

+30
-8
lines changed

2 files changed

+30
-8
lines changed

lib/Sema/CSGen.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,13 +1368,19 @@ namespace {
13681368
knownType = CS.getVarType(VD);
13691369

13701370
if (knownType) {
1371-
// An out-of-scope type variable could be a type of a declaration
1372-
// only in diagnostic mode when invalid variable declaration is
1373-
// recursively referenced inside of a multi-statement closure
1374-
// located somewhere within its initializer e.g.:
1375-
// `let x = [<call>] { ... print(x) }`
1376-
if (auto *typeVar = knownType->getAs<TypeVariableType>()) {
1377-
if (!CS.isActiveTypeVariable(typeVar))
1371+
// An out-of-scope type variable(s) could appear the type of
1372+
// a declaration only in diagnostic mode when invalid variable
1373+
// declaration is recursively referenced inside of a multi-statement
1374+
// closure located somewhere within its initializer e.g.:
1375+
// `let x = [<call>] { ... print(x) }`. It happens because the
1376+
// variable assumes the result type of its initializer unless
1377+
// its specified explicitly.
1378+
if (knownType->hasTypeVariable()) {
1379+
llvm::SmallPtrSet<TypeVariableType *, 2> typeVars;
1380+
knownType->getTypeVariables(typeVars);
1381+
if (llvm::any_of(typeVars, [&](auto *typeVar) {
1382+
return !CS.isActiveTypeVariable(typeVar);
1383+
}))
13781384
return invalidateReference();
13791385
}
13801386

test/expr/closure/multi_statement.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,13 +653,29 @@ func test_that_closures_are_attempted_in_order() {
653653

654654
// https://github.com/apple/swift/issues/63455
655655
func test_recursive_var_reference_in_multistatement_closure() {
656+
struct MyStruct {
657+
func someMethod() {}
658+
}
659+
656660
func takeClosure(_ x: () -> Void) {}
657661

658-
func test(optionalInt: Int?) {
662+
func test(optionalInt: Int?, themes: MyStruct?) {
659663
takeClosure {
660664
let int = optionalInt { // expected-error {{cannot call value of non-function type 'Int?'}}
661665
print(int)
662666
}
663667
}
668+
669+
takeClosure {
670+
let theme = themes?.someMethod() { // expected-error {{extra trailing closure passed in call}}
671+
_ = theme
672+
}
673+
}
674+
675+
takeClosure {
676+
let theme = themes?.filter({ $0 }) { // expected-error {{value of type 'MyStruct' has no member 'filter'}}
677+
_ = theme
678+
}
679+
}
664680
}
665681
}

0 commit comments

Comments
 (0)