Can anyone tell me why I'd get a "will never be executed" warning for workfunc() in this minimal case? If I comment out the if let data {} part then the warning's gone.
The program compiles fine, and triggers no complaints from concurrency even with -strict-concurrency=complete. It certainly runs workfunc() even though the analyzer thinks otherwise.
import Dispatch
import Foundation.NSData
let workItem = DispatchWorkItem(qos: .userInitiated) {
let result = workfunc()
print(result)
}
let data : Data? = {
let baseURL = URL.currentDirectory()
guard let matfileURL = URL(string: "filename.bin", relativeTo: baseURL)
else { print("URL error"); return nil }
guard let data = try? Data(contentsOf: matfileURL, options: .mappedIfSafe)
else { /* File not found */ return nil };
return data
}()
DispatchQueue.global().asyncAndWait(execute: workItem)
exit(EXIT_SUCCESS)
/*
End of top-level code
*/
func workfunc() -> Int {
/* Do something */
if let data = data {
print("File found. \(data)")
/* Additionally do something else */
}
return 0
}
this is a misleading diagnostic due to top level code generally behaving oddly in some cases. if you wrap everything in a do {} block or function, you'll see that the problem is that the closure captures a variable before it's declared:
<source>:53:54: error: closure captures 'data' before it is declared [capture_before_declaration]
51 |
52 | do {
53 | let workItem = DispatchWorkItem(qos: .userInitiated) {
| `- error: closure captures 'data' before it is declared [capture_before_declaration]
54 | let result = workfunc()
55 | print(result)
56 | }
57 |
58 | let data : Data? = {
| `- note: captured value declared here [captured_value_declared_here]
59 | let baseURL = URL.currentDirectory()
60 | guard let matfileURL = URL(string: "filename.bin", relativeTo: baseURL)
:
74 | func workfunc() -> Int {
75 | /* Do something */
76 | if let data = data {
| `- note: captured here [value_captured_here]
77 | print("File found. \(data)")
78 | /* Additionally do something else */
Compiler returned: 1
i'm fairly sure there are existing issues and threads on this matter, though they elude me at the moment...
You could even go further by not using top level code and by resisting the temptation to capture variable names in your functions.
// Driver.swift - Main entry point into the program
import Dispatch
import Foundation.NSData
@main
enum Driver {
static func main () {
let data : Data? = {
let baseURL = URL.currentDirectory()
guard let matfileURL = URL(string: "filename.bin", relativeTo: baseURL)
else { print("URL error"); return nil }
guard let data = try? Data(contentsOf: matfileURL, options: .mappedIfSafe)
else { /* File not found */ return nil };
return data
}()
let workItem = DispatchWorkItem(qos: .userInitiated) {
let result = workfunc(data)
print(result)
}
func workfunc(_ data: Data?) -> Int {
/* Do something */
if let data = data {
print("File found. \(data)")
/* Additionally do something else */
}
return 0
}
DispatchQueue.global().asyncAndWait(execute: workItem)
exit(EXIT_SUCCESS)
}
}