Skip to content

[SR-14824] Improve diagnostic for multi-statement closures instead of… #38153

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,8 @@ ERROR(cannot_infer_closure_parameter_type,none,
ERROR(cannot_infer_closure_type,none,
"unable to infer closure type in the current context", ())
ERROR(cannot_infer_closure_result_type,none,
"unable to infer%select{ complex|}0 closure return type; "
"add explicit type to disambiguate", (bool))
"cannot infer return type for closure with multiple statements; "
"add explicit type to disambiguate", ())
FIXIT(insert_closure_return_type_placeholder,
"%select{| () }0-> <#Result#> %select{|in }0",
(bool))
Expand Down
3 changes: 1 addition & 2 deletions lib/Sema/CSDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6845,8 +6845,7 @@ bool UnableToInferClosureParameterType::diagnoseAsError() {
bool UnableToInferClosureReturnType::diagnoseAsError() {
auto *closure = castToExpr<ClosureExpr>(getRawAnchor());

auto diagnostic = emitDiagnostic(diag::cannot_infer_closure_result_type,
closure->hasSingleExpressionBody());
auto diagnostic = emitDiagnostic(diag::cannot_infer_closure_result_type);

// If there is a location for an 'in' token, then the argument list was
// specified somehow but no return type was. Insert a "-> ReturnType "
Expand Down
10 changes: 5 additions & 5 deletions test/Constraints/closures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ struct CC {}
func callCC<U>(_ f: (CC) -> U) -> () {}

func typeCheckMultiStmtClosureCrash() {
callCC { // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{none}}
callCC { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{none}}
_ = $0
return 1
}
Expand Down Expand Up @@ -313,7 +313,7 @@ struct Thing {
init?() {}
}
// This throws a compiler error
let things = Thing().map { thing in // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{34-34=-> <#Result#> }}
let things = Thing().map { thing in // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{34-34=-> <#Result#> }}
// Commenting out this makes it compile
_ = thing
return thing
Expand All @@ -322,7 +322,7 @@ let things = Thing().map { thing in // expected-error {{unable to infer complex

// <rdar://problem/21675896> QoI: [Closure return type inference] Swift cannot find members for the result of inlined lambdas with branches
func r21675896(file : String) {
let x: String = { // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{20-20= () -> <#Result#> in }}
let x: String = { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{20-20= () -> <#Result#> in }}
if true {
return "foo"
}
Expand Down Expand Up @@ -360,7 +360,7 @@ func someGeneric19997471<T>(_ x: T) {


// <rdar://problem/20921068> Swift fails to compile: [0].map() { _ in let r = (1,2).0; return r }
[0].map { // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{5-5=-> <#Result#> }}
[0].map { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{5-5=-> <#Result#> }}
_ in
let r = (1,2).0
return r
Expand Down Expand Up @@ -408,7 +408,7 @@ func r20789423() {
print(p.f(p)()) // expected-error {{cannot convert value of type 'C' to expected argument type 'Int'}}
// expected-error@-1:11 {{cannot call value of non-function type '()'}}

let _f = { (v: Int) in // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{23-23=-> <#Result#> }}
let _f = { (v: Int) in // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{23-23=-> <#Result#> }}
print("a")
return "hi"
}
Expand Down
2 changes: 1 addition & 1 deletion test/Constraints/diagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public func myMap<T, U>(_ x: T?, _ f: (T) -> U) -> U? {

// <rdar://problem/20142523>
func rdar20142523() {
myMap(0..<10, { x in // expected-error{{unable to infer complex closure return type; add explicit type to disambiguate}} {{21-21=-> <#Result#> }} {{educational-notes=complex-closure-inference}}
myMap(0..<10, { x in // expected-error{{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{21-21=-> <#Result#> }} {{educational-notes=complex-closure-inference}}
()
return x
})
Expand Down
4 changes: 2 additions & 2 deletions test/Constraints/patterns.swift
Original file line number Diff line number Diff line change
Expand Up @@ -230,14 +230,14 @@ func good(_ a: A<EE>) -> Int {
}

func bad(_ a: A<EE>) {
a.map { // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{none}}
a.map { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{none}}
let _: EE = $0
return 1
}
}

func ugly(_ a: A<EE>) {
a.map { // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{none}}
a.map { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{none}}
switch $0 {
case .A:
return 1
Expand Down
4 changes: 2 additions & 2 deletions test/diagnostics/pretty-printed-diagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ foo(b:
// CHECK: [[#LINE-1]] |
// CHECK: [[#LINE]] | let x = { () -> Result in
// CHECK: | +++++++++++++++++
// CHECK: | ^ error: unable to infer complex closure return type; add explicit type to disambiguate
// CHECK: | ^ error: cannot infer return type for closure with multiple statements; add explicit type to disambiguate
// CHECK: [[#LINE+1]] | let y = 1

// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:8
Expand All @@ -152,7 +152,7 @@ foo(b:
// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:20
// CHECK: [[#LINE-1]] |
// CHECK: [[#LINE]] | let 👍👍👍 = {
// CHECK: | --> error: unable to infer complex closure return type; add explicit type to disambiguate [insert ' () -> <#Result#> in ']
// CHECK: | --> error: cannot infer return type for closure with multiple statements; add explicit type to disambiguate [insert ' () -> <#Result#> in ']
// CHECK: [[#LINE+1]] | let y = 1

// CHECK: SOURCE_DIR{{[/\]+}}test{{[/\]+}}diagnostics{{[/\]+}}pretty-printed-diagnostics.swift:[[#LINE:]]:5
Expand Down
4 changes: 2 additions & 2 deletions test/expr/closure/closures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ Void(0) // expected-error{{argument passed to call that takes no arguments}}
_ = {0}

// <rdar://problem/22086634> "multi-statement closures require an explicit return type" should be an error not a note
let samples = { // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{16-16= () -> <#Result#> in }}
let samples = { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{16-16= () -> <#Result#> in }}
if (i > 10) { return true }
else { return false }
}()
Expand Down Expand Up @@ -485,7 +485,7 @@ func lvalueCapture<T>(c: GenericClass<T>) {
}

// Don't expose @lvalue-ness in diagnostics.
let closure = { // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{16-16= () -> <#Result#> in }}
let closure = { // expected-error {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}} {{16-16= () -> <#Result#> in }}
var helper = true
return helper
}
Expand Down
2 changes: 1 addition & 1 deletion userdocs/diagnostics/complex-closure-inference.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ let doubler = {
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:

```swift
// error: unable to infer complex closure return type; add explicit type to disambiguate
// error: cannot infer return type for closure with multiple statements; add explicit type to disambiguate
let evenDoubler = { x in
if x.isMultiple(of: 2) {
return x * 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,4 @@ struct X { var y: Int = 0 }
var x = X()
x ~> \X.y ≈> { a in a += 1; return 3 }
// expected-error@-1 {{referencing operator function '~>' on 'P' requires that 'M<WritableKeyPath<X, Int>, R>' conform to 'P'}}
// expected-error@-2 {{unable to infer complex closure return type; add explicit type to disambiguate}}
// expected-error@-2 {{cannot infer return type for closure with multiple statements; add explicit type to disambiguate}}