apple / apple/swift-argument-parser

Using `main` instead of `run` in subcommands leads to unexpected behavior

Open
#622 1 comment 0 reactions 0 assignees View on GitHub
as expected
Dominant language
Swift
Stars
3.8k
Forks
411
Avg merge
7d 14h
Merged PRs (30d)
15

Description

When accidentally defining `main` instead of `run` in subcommands, no warning or error is shown, but the subcommand itself either displays a help message or swallows all arguments with no output.

**ArgumentParser version:** `1.2.0` and `1.3.0` or the `main` branch, for example.
**Swift version:** Apple Swift version 6.0-dev (LLVM ce41a43bba95b2b, Swift 1a840948a0905df), also reproducible with Swift 5.10.0 from Xcode 15.3.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](https://github.com/apple/swift-argument-parser/issues)

### Steps to Reproduce

Build and run an executable that has only this code:

```swift
import ArgumentParser

@main
struct Entrypoint: ParsableCommand {
static let configuration = CommandConfiguration(
subcommands: [Client.self, Server.self]
)
}

struct Client: ParsableCommand {
static func main() throws {
print("Client!")
}
}

struct Server: ParsableCommand {
static func main() throws {
print("Server!")
}
}
```

### Expected behavior

I realize that I should've defined `run` instead of main, but defining `main` in `Entrypoint` does work, that function is called, albeit with no argument parsing done IIUC. The actual behavior for subcommands is unexpected. The default implementation of `ParsableCommand` and `AsyncParsableCommand` should at least issue a warning, if possible, that no custom implementaiton of `run` is provided. Otherwise it's very easy to spend a long time debugging this issue.

I'd assume this can also be a very frustrating experience for first-time users who try to convert their existing `@main` entrypoint to `ParsableCommand` but don't realize they have to rename `static func main()` to `func run()`.

### Actual behavior

When running `server` or `client` subcommands on their own, a help message is shown, but not other output is produced:
```
USAGE: entrypoint server

OPTIONS:
-h, --help Show help information.
```

When passing any arguments like `server foo bar`, no output is produced whatsoever.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the minimal ParsableCommand example and then inspect the default behavior of ParsableCommand and AsyncParsableCommand when subcommands define main instead of run. Done means the mistaken implementation produces a clear warning or error rather than showing help or silently swallowing arguments.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.