Skip to content

Commit b845620

Browse files
committed
[Diagnostics] Add an educational note explaining closure type inference rules
This note explains the difference in type inference between single expression and non-single expression closures. It is associated with the "unable to infer complex closure return type" diagnostic.
1 parent cd3ada5 commit b845620

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

include/swift/AST/EducationalNotes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,7 @@ EDUCATIONAL_NOTES(non_nominal_extension, "nominal-types.md")
2626
EDUCATIONAL_NOTES(associated_type_witness_conform_impossible,
2727
"nominal-types.md")
2828

29+
EDUCATIONAL_NOTES(cannot_infer_closure_result_type,
30+
"complex-closure-inference.md")
31+
2932
#undef EDUCATIONAL_NOTES
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
Inferring Closure Types
2+
---
3+
If a closure contains a single expression, Swift will consider its body in addition to its signature and the surrounding context when performing type inference. For example, in the following code the type of `doubler` is inferred to be `(Int) -> Int` using only its body:
4+
```
5+
let doubler = {
6+
$0 * 2
7+
}
8+
```
9+
If a closure body is not a single expression, it will not be considered when inferring the closure type. This is consistent with how type inference works in other parts of the language, where it proceeds one statement at a time. For example, in the following code an error will be reported because the type of `evenDoubler` cannot be inferred from its surrounding context and no signature was provided:
10+
```
11+
// error: unable to infer complex closure return type; add explicit type to disambiguate
12+
let evenDoubler = { x in
13+
if x.isMultiple(of: 2) {
14+
return x * 2
15+
} else {
16+
return x
17+
}
18+
}
19+
```
20+
This can be fixed by providing additional contextual information:
21+
```
22+
let evenDoubler: (Int) -> Int = { x in
23+
// ...
24+
}
25+
```
26+
Or by giving the closure an explicit signature:
27+
```
28+
let evenDoubler = { (x: Int) -> Int in
29+
// ...
30+
}
31+
```

0 commit comments

Comments
 (0)