Compiler getting confused with overloaded functions

I have two overloaded functions:

  internal static func execute(with arguments: [Argument], completion: ((Data) -> ())? = nil) throws
  {
    …
  }
  
  internal static func execute(for fileURL: URL, arguments: [Argument], completion: ((Data) -> ())? = nil) throws
  {
    …
  }
  

But from this function, if I try to call the second one:

  
  public static func keywords(for fileURL: URL) throws -> [String]?
  {
    let arguments: [Argument] = […, …, …]
    
    var result: [String]?
    
    try execute(for: fileURL, arguments: arguments)
    {
      … // completion closure
    }
    
    return result
  }
}

The compiler complains with "Extra argument 'arguments' in call"

If I change the completion closures on the execute(…) methods to throws, everything compiles fine.

  internal static func execute(with arguments: [Argument], completion: ((Data) throws -> ())? = nil) throws
  {
    …
  }
  
  internal static func execute(for fileURL: URL, arguments: [Argument], completion: ((Data) throws -> ())? = nil) throws
  {
    …
  }
  

But I don't want the closure to throw :face_with_raised_eyebrow:

(Xcode 10 beta 4)

If I call the execute function like this, I get the same error:

try execute(for: fileURL, arguments: arguments) {
    print("execution completed")
}

But this happens because the completion handler doesn't declare or ignore its Data parameter. So the whole expression doesn't type-check and the compiler emits a (bad) error message. If I instead call the function like this, everything works fine:

try execute(for: fileURL, arguments: arguments) { _ in
    print("execution completed")
}

Since you omitted the contents of the completion handler, I can't tell, but maybe your code has the same issue.

Hmmm. I am actually using the anonymous $0 in the closure, which gives it a definite context.

I also tried it with an explicit data in and got the same thing.

Oh could it be that you have a try expression (e.g., try f()) inside the completion closure, that's not wrapped in a do {} catch {} statement? Like this:

try execute(for: fileURL, arguments: arguments) { _ in
    try f()
}

This also gives me the same error message. And it would make sense that it can be fixed by declaring the completion closure with throws.

Hi Toni

No, but I do have a throw Error.couldNotRetrieveKeywords

So, thank you. I will have to go away and have a serious cogitate on what I am actually doing here :thinking:

1 Like

I would normally ask you to still file a bug for the suboptimal diagnostic, but in this case we have one: SR-1196. I've linked this thread there.

1 Like