Description
If a run
function is defined with parameters, each of which has a default value (e.g., func run(arg: Type = defaultValue)
), the function can be called via run()
.
Each ParsableCommand
has a default run()
function that outputs its help info, however, so that gets called instead of the overload with its default values.
If run()
isn't specifically overridden in a subtype of ParsableCommand
, but it is overloaded by another function that has default values for each of its parameters, can you autogenerate a run()
that calls the defaulted overload?
This is similar to other open issues (#622 & #538), all of which stem from the default implementation of run()
in ParsableCommand
(see #622 (comment)).
ArgumentParser version:
1.5.0
Swift version:
swift-driver version: 1.62.15 Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)
Target: x86_64-apple-macosx12.0
Checklist
- If possible, I've reproduced the issue using the
main
branch of this packageI've searched for existing GitHub issues
Steps to Reproduce
@main
struct Command: ParsableCommand {
func run(param: String = "default") {
print("Ran defaulted overload")
}
}
Expected behavior
Prints "Ran defaulted overload"
Actual behavior
Prints help info for command
Activity
natecook1000 commentedon Feb 13, 2025
Unfortunately this is a result of how types satisfy requirements when conforming to protocols in Swift. The
ParsableCommand
protocol hasmutating func run() throws
as a requirement, which can be satisfied by any of these:...but not by a function with default parameters. Here's a stripped down example:
While the default-parametered
Example.run()
is callable on concrete instances ofExample
, it doesn't actually satisfy theCommand.run()
protocol requirement, so when.run()
is called on an instance where the only thing known is itsCommand
conformance (as inrunSomeCommand(_:)
), then the protocol's version is called. You can see this if you comment outextension Command { ... }
-- without that, the compiler says:because
Example
doesn't provide a method that satisfies the protocol requirment.In this case, my recommendation is to go the other way – leave the defaults off your custom method and provide them within your
run()
implementation, or use another method name:rgoldberg commentedon Feb 14, 2025
@natecook1000 Thanks for the info. I haven't had a chance to look into the following, but could
@_disfavoredOverload
be useful at all for this circumstance? I'm not sure exactly how that interacts (or other possible similar attributes interact) with function selection…FYI, when I dealt with this back then, I used your first suggestion: I didn't have defaults in my custom function, instead supplying the default values in my
run()
function implementation.