swift-argument-parser icon indicating copy to clipboard operation
swift-argument-parser copied to clipboard

Running Command.main() on an AsyncParseableCommand with AsyncParseableCommand sub commands will crash

Open bolsinga opened this issue 1 year ago • 3 comments

I have a AsyncParseableCommand with one AsyncParseableCommand sub commands. My package is built targeting macOS 15.

If I run the "parent" Command with Command.main(CommandLine.arguments) it will fail with the message:

ArgumentParser/ParsableCommand.swift:264: Fatal error: 
--------------------------------------------------------------------
Asynchronous root command needs availability annotation.

The asynchronous root command `CommandIssue` needs an availability
annotation in order to be executed asynchronously. To fix this issue,
add the following availability attribute to your `CommandIssue`
declaration or set the minimum platform in your "Package.swift" file.

@available(macOS 10.15, macCatalyst 13, iOS 13, tvOS 13, watchOS 6, *)
--------------------------------------------------------------------

ArgumentParser version: 1.5.0 Swift version: swift-driver version: 1.115.1 Apple Swift version 6.0.3 (swiftlang-6.0.3.1.10 clang-1600.0.30.1) Target: arm64-apple-macosx15.0

Checklist

  • [x ] If possible, I've reproduced the issue using the main branch of this package
  • [ x] I've searched for existing GitHub issues

Steps to Reproduce

Open CommandIssue.zip

Set up the reproducible directory: swift run Tool It will crash with the above.

Remove the SubCommand from the CommandIssue.configuration. swift run Tool It will not crash.

Expected behavior

I expect that this will not report that it is not working due to building for an asynchronous command supporting platform, since it is. I expect it to print a hello world message. FWIW I also filed FB16143524.

Actual behavior

It will crash as described above.

bolsinga avatar Dec 22 '24 18:12 bolsinga

I found a workaround. It seems that the main.swift call of CommandIssue.main() calls the ParsableCommand version, not the AsyncParsableCommand version. I could not figure out how to "cast" it. Adding await CommandIssue.main() did not help. So I added static func go(_ arguments: [String]) async, and I call that from the main.swift file.

bolsinga avatar Dec 23 '24 00:12 bolsinga

What works for me is:

@main
struct CLI {
   static func main() async {
      await SomeAsyncCommand.main()
   }
}

stuartro avatar Dec 30 '24 06:12 stuartro

What works for me is:

Awesome, thanks for your tip!

bolsinga avatar Dec 31 '24 16:12 bolsinga