Skip to content

Commit cab0cb5

Browse files
committed
[CSSyntaxElement] Detect type variables in sequence expressions of for-in loops
Invalid syntax could introduce type variables into sequence which have to be brought into scope otherwise solver is going to crash. Resolves: rdar://100753270
1 parent 1299d15 commit cab0cb5

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

lib/Sema/CSSyntacticElement.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2226,6 +2226,22 @@ void ConjunctionElement::findReferencedVariables(
22262226

22272227
TypeVariableRefFinder refFinder(cs, locator->getAnchor(), typeVars);
22282228

2229+
// If this is a pattern of `for-in` statement, let's walk into `for-in`
2230+
// sequence expression because both elements are type-checked together.
2231+
//
2232+
// Correct expressions wouldn't have any type variables in sequence but
2233+
// they could appear due to circular references or other incorrect syntax.
2234+
if (element.is<Pattern *>()) {
2235+
if (auto parent =
2236+
locator->getLastElementAs<LocatorPathElt::SyntacticElement>()) {
2237+
if (auto *forEach = getAsStmt<ForEachStmt>(parent->getElement())) {
2238+
if (auto *sequence = forEach->getParsedSequence())
2239+
sequence->walk(refFinder);
2240+
return;
2241+
}
2242+
}
2243+
}
2244+
22292245
if (auto *patternBinding =
22302246
dyn_cast_or_null<PatternBindingDecl>(element.dyn_cast<Decl *>())) {
22312247
// Let's not walk into placeholder variable initializers, since they
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
struct Location {
4+
var host: String?
5+
}
6+
7+
struct Data: Hashable {
8+
func location() -> Location {
9+
fatalError()
10+
}
11+
}
12+
13+
struct Test { // expected-note {{to match this opening '{'}}
14+
private struct Info {
15+
var data = Set<Data>()
16+
var desc: String
17+
}
18+
19+
static func print(data: [Data]) {
20+
var infos = [Info]()
21+
22+
for (index, info) in infos.enumerated() {
23+
let dataPerHost = Dictionary(grouping: info.data) { data in
24+
let location = data.location()
25+
guard let host = location.host else {
26+
return 0
27+
}
28+
29+
for character in host {
30+
// Missing paren!
31+
}
32+
33+
for _ in dataPerHost { // `dataPerHost` is inside of the closure!
34+
}
35+
}
36+
}
37+
} // expected-error@+1 {{expected '}' in struct}}

0 commit comments

Comments
 (0)