Skip to content

Commit 92b7e13

Browse files
authored
Merge pull request #38084 from fwcd/fix-sourcekit-var-types-if-let
[SourceKit] Determine correctly whether typed variables in `if/guard/while-let`-statements have explicit type annotations
2 parents c3ae5a1 + b33a202 commit 92b7e13

File tree

3 files changed

+56
-5
lines changed

3 files changed

+56
-5
lines changed

lib/AST/Decl.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5831,11 +5831,24 @@ void VarDecl::setNamingPattern(NamedPattern *Pat) {
58315831
}
58325832

58335833
TypeRepr *VarDecl::getTypeReprOrParentPatternTypeRepr() const {
5834-
if (auto *param = dyn_cast<ParamDecl>(this))
5835-
return param->getTypeRepr();
5836-
5837-
if (auto *parentPattern = dyn_cast_or_null<TypedPattern>(getParentPattern()))
5838-
return parentPattern->getTypeRepr();
5834+
if (auto *Param = dyn_cast<ParamDecl>(this))
5835+
return Param->getTypeRepr();
5836+
5837+
auto *ParentPattern = getParentPattern();
5838+
5839+
if (auto *TyPattern = dyn_cast_or_null<TypedPattern>(ParentPattern))
5840+
return TyPattern->getTypeRepr();
5841+
5842+
// Handle typed if/guard/while-let as a special case (e.g. `if let x: Int
5843+
// = Optional.some(4)`), since the `TypedPattern` is not the top-level
5844+
// pattern here - instead it is an implicit `OptionalSomePattern`
5845+
if (auto *SomePattern =
5846+
dyn_cast_or_null<OptionalSomePattern>(ParentPattern)) {
5847+
if (auto *TyPattern =
5848+
dyn_cast<TypedPattern>(SomePattern->getSubPattern())) {
5849+
return TyPattern->getTypeRepr();
5850+
}
5851+
}
58395852

58405853
return nullptr;
58415854
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
if case let x? = Optional.some(5) {}
2+
if case let y: Int? = Optional.some(5) {}
3+
guard case let z: String? = Optional.some("a") else { fatalError() }
4+
while case let w: String? = Optional.some("b") {}
5+
6+
enum Pair<U, V> {
7+
case pair(U, V)
8+
}
9+
10+
switch Pair.pair(Optional.some(0), "test") {
11+
case .pair(let u, var v):
12+
break
13+
}
14+
15+
// RUN: %sourcekitd-test -req=collect-var-type %s -- %s | %FileCheck %s
16+
// CHECK: (1:13, 1:14): Int (explicit type: 0)
17+
// CHECK: (2:13, 2:14): Int? (explicit type: 1)
18+
// CHECK: (3:16, 3:17): String? (explicit type: 1)
19+
// CHECK: (4:16, 4:17): String? (explicit type: 1)
20+
// CHECK: (11:16, 11:17): Int? (explicit type: 0)
21+
// CHECK: (11:23, 11:24): String (explicit type: 0)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
guard var opt: Int = .some(23) else { fatalError() }
2+
3+
func foo() {
4+
guard let x = .some("abc") else { return }
5+
guard let y: String = .some("def") else { return }
6+
7+
if let z: Int = .some(4) {}
8+
9+
while var w: Int = .some(5) {}
10+
}
11+
12+
// RUN: %sourcekitd-test -req=collect-var-type %s -- %s | %FileCheck %s
13+
// CHECK: (1:11, 1:14): Int (explicit type: 1)
14+
// CHECK: (4:13, 4:14): String (explicit type: 0)
15+
// CHECK: (5:13, 5:14): String (explicit type: 1)
16+
// CHECK: (7:10, 7:11): Int (explicit type: 1)
17+
// CHECK: (9:13, 9:14): Int (explicit type: 1)

0 commit comments

Comments
 (0)