Skip to content

Commit 2e901a1

Browse files
committed
[Sema]: suppress unexpected type warning on some async-let patterns
It is somewhat common to use an async-let binding to run a synchronous, void-returning function in an async context. In such cases, the binding's type being inferred as Void is expected, and requiring programmers to explicitly write this to suppress a warning seems like unnecessary boilerplate. This patch changes the diagnostic logic to exempt async-let bindings from the existing diagnostic when the inferred type is Void.
1 parent de51fed commit 2e901a1

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

lib/Sema/TypeCheckPattern.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1230,7 +1230,14 @@ Pattern *TypeChecker::coercePatternToType(
12301230
// If the whole pattern is implicit, the user didn't write it.
12311231
// Assume the compiler knows what it's doing.
12321232
} else if (diagTy->isEqual(Context.TheEmptyTupleType)) {
1233-
shouldRequireType = true;
1233+
// Async-let bindings are commonly used to run a Void-returning
1234+
// synchronous function in an async context. As a policy choice, don't
1235+
// diagnose a Void result on these bindings as potentially unexpected.
1236+
if (!isOptional && var->isAsyncLet()) {
1237+
shouldRequireType = false;
1238+
} else {
1239+
shouldRequireType = true;
1240+
}
12341241
} else if (auto MTT = diagTy->getAs<AnyMetatypeType>()) {
12351242
if (MTT->getInstanceType()->isAnyObject())
12361243
shouldRequireType = true;

test/decl/var/async_let.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,34 @@ func testInterpolation() async {
4242
async let y = "\(12345)"
4343
_ = await y
4444
}
45+
46+
// https://forums.swift.org/t/disable-constant-inferred-to-have-type-warning-when-using-async-let/83025
47+
48+
func testVoidResultTypeDiagnostics() async {
49+
async let void = print("hello")
50+
await void
51+
async let void2 = ()
52+
await void2
53+
async let void3 = Void()
54+
await void3
55+
async let void4 = { _ = 42 }()
56+
await void4
57+
58+
@Sendable func syncVoid() {}
59+
async let void5 = syncVoid()
60+
await void5
61+
62+
@Sendable func asyncVoid() async {}
63+
async let void6 = asyncVoid()
64+
await void6
65+
66+
// expected-warning @+2 {{constant 'maybeVoid' inferred to have type '()?', which may be unexpected}}
67+
// expected-note @+1 {{add an explicit type annotation to silence this warning}}
68+
async let maybeVoid = { Bool.random() ? () : nil }()
69+
await maybeVoid
70+
71+
// expected-warning @+2 {{constant 'boxOVoid' inferred to have type '[()]', which may be unexpected}}
72+
// expected-note @+1 {{add an explicit type annotation to silence this warning}}
73+
async let boxOVoid = { [(), (), ()] }()
74+
await boxOVoid // expected-warning {{expression of type '[()]' is unused}}
75+
}

0 commit comments

Comments
 (0)