title: Why can't I pass certain expressions to a closure parameter marked @convetion(block)?
body: <p>I discovered this weird behaviour:</p>
  
  <p>Consider the following code:</p>
  
  <pre><code>func foo(_ x: () -&gt; Void) {
  
  }
  
  class Bar {
      func bar() {
          print("hello")
      }
  }
  
  var bar: Bar? = Bar()
  </code></pre>
  
  <p>These compiles:</p>
  
  <pre><code>foo(bar?.bar ?? {})
  </code></pre>
  
  <p>but this does not:</p>
  
  <pre><code>DispatchQueue.main.async(execute: bar?.bar ?? {})
  </code></pre>
  
  <p>It produces the error:</p>
  
  <blockquote>
    <p>Cannot convert value of type '() -> ()' to expected argument type '@convention(block) () -> Void'</p>
  </blockquote>
  
  <p>Now if I change <code>bar</code> to:</p>
  
  <pre><code>func bar() -&gt; (() -&gt; Void)? {
      return { print("hello") }
  }
  </code></pre>
  
  <p>and then do:</p>
  
  <pre><code>DispatchQueue.main.async(execute: bar() ?? {})
  </code></pre>
  
  <p>It compiles!</p>
  
  <p>So it's definitely not because of the <code>??</code> operator</p>
  
  <p><strong>Question:</strong> Can you explain this behaviour?</p>
  
  <p>Everything below this point is my experimentation.</p>
  
  <hr>
  
  <p>I spotted that the only difference between the <code>async</code> method and <code>foo</code> is that the <code>execute</code> parameter is marked with <code>@convention(block)</code>.</p>
  
  <p><strong>Hypothesis:</strong> I cannot pass optional chaining expressions into parameters marked with <code>@convention(block)</code>.</p>
  
  <p>But this seems to be wrong, as I can do this and it still doesn't compile:</p>
  
  <pre><code>DispatchQueue.main.async(execute: Bar().bar ?? {})
  </code></pre>
  
  <p>It also seems like I can cast the expression to a <code>() -&gt; Void</code> and it magically compiles:</p>
  
  <pre><code>DispatchQueue.main.async(execute: (bar?.bar ?? {}) as () -&gt; Void)
  </code></pre>
  
  <p>Isn't <code>bar?.bar ?? {}</code> already of type <code>() -&gt; Void</code>? This makes no sense!</p>
  
  <p>Another way to make it compile is to extract <code>bar?.bar</code> as a local variable:</p>
  
  <pre><code>let barFunc = bar?.bar
  DispatchQueue.main.async(execute: barFunc ?? {})
  </code></pre>
  
  <p>which makes even less sense...</p>