Skip to content

Commit 4e3a4ff

Browse files
authored
Merge pull request #62120 from xedin/rdar-100753270
[CSSyntaxElement] Detect type variables in sequence expressions of `for-in` loops
2 parents dcfeff7 + cab0cb5 commit 4e3a4ff

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
@@ -2229,6 +2229,22 @@ void ConjunctionElement::findReferencedVariables(
22292229

22302230
TypeVariableRefFinder refFinder(cs, locator->getAnchor(), typeVars);
22312231

2232+
// If this is a pattern of `for-in` statement, let's walk into `for-in`
2233+
// sequence expression because both elements are type-checked together.
2234+
//
2235+
// Correct expressions wouldn't have any type variables in sequence but
2236+
// they could appear due to circular references or other incorrect syntax.
2237+
if (element.is<Pattern *>()) {
2238+
if (auto parent =
2239+
locator->getLastElementAs<LocatorPathElt::SyntacticElement>()) {
2240+
if (auto *forEach = getAsStmt<ForEachStmt>(parent->getElement())) {
2241+
if (auto *sequence = forEach->getParsedSequence())
2242+
sequence->walk(refFinder);
2243+
return;
2244+
}
2245+
}
2246+
}
2247+
22322248
if (auto *patternBinding =
22332249
dyn_cast_or_null<PatternBindingDecl>(element.dyn_cast<Decl *>())) {
22342250
// 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)