Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mutable app functions are confusing to users and awkward to work with #2911

Open
2 tasks done
epage opened this issue Oct 19, 2021 · 7 comments
Open
2 tasks done

Mutable app functions are confusing to users and awkward to work with #2911

epage opened this issue Oct 19, 2021 · 7 comments
Assignees
Labels
A-builder Area: Builder API C-bug Category: Updating dependencies E-medium Call for participation: Experience needed to fix: Medium / intermediate M-breaking-change Meta: Implementing or merging this will introduce a breaking change.
Milestone

Comments

@epage
Copy link
Member

epage commented Oct 19, 2021

Please complete the following tasks

  • I have searched the discussions
  • I have searched the existing issues

Rust Version

rustc 1.55.0 (c8dfcfe04 2021-09-06)

Clap Version

master

Minimal reproducible code

let mut app = ...;
app.render_usage();

Steps to reproduce the bug with the above code

Program with the &mut API

Actual Behaviour

Its awkward and exposing of implementation details. I've seen user confusion akin to "Why does rendering need to modify the app?"

Other uses of this API, like clap_generate, need to use the hidden _build

Expected Behaviour

The types are clean and understandable for a user without ambiguous "modify after build"

Additional Context

I propose we add a struct AppParser that derefs to App.

  • get_matches will consume App and use _build (only build what is needed for parsing)
  • App::build(self) -> AppParser will call _build_all
    • Contains all of the existing &mut functions, but without the mut

We can implement the additions without breaking behavior; we just add deprecations. Then on the next breaking release, we remove the deprecated behavior.

Debug Output

No response

@epage epage added C-bug Category: Updating dependencies M-breaking-change Meta: Implementing or merging this will introduce a breaking change. A-builder Area: Builder API labels Oct 19, 2021
@epage epage added this to the 3.0 milestone Oct 19, 2021
@epage epage self-assigned this Oct 19, 2021
@epage epage removed this from the 3.0 milestone Oct 19, 2021
@pksunkara
Copy link
Member

Same issue as print_*_help and write_*_help methods. I wanted them to be non-mut but couldn't find a way to do it without quickly blowing up the scope of it. IIRC there were some discussions around this when those signatures were implemented which might be useful here.

@epage
Copy link
Member Author

epage commented Oct 19, 2021

What are your thoughts on the proposal for solving the mut problem?

IIRC there were some discussions around this when those signatures were implemented which might be useful here.

At least in my initial search, I found #540 which didn't have any useful conversation on the subject.

@pksunkara
Copy link
Member

It would be a good approach to explore definitely. Will have to evaluate it properly when we are finalising the design though.

@pksunkara
Copy link
Member

Heh, weird. Couldn't find the discussion now. Maybe it was on something else that was related? 🤷

@epage
Copy link
Member Author

epage commented Dec 14, 2021

We should probably do #3089 first.
Done

@epage
Copy link
Member Author

epage commented Feb 15, 2022

#950 needs us to rename the get_matches functions. We should coordinate these changes together to reduce user churn.

epage added a commit to epage/clap that referenced this issue Apr 19, 2022
`Command::_build_all` started as an internal function for
`clap_complete` as a stopgap until clap-rs#2911.  Overtime, we've been finding
more cases where this function needs to be called, so now we're going to
fully embrace it until clap-rs#2911 so people aren't scrared off by the hidden
implementation from using it.

This was inspired by clap-rs#3602
epage added a commit to epage/clap that referenced this issue Apr 19, 2022
`Command::_build_all` started as an internal function for
`clap_complete` as a stopgap until clap-rs#2911.  Overtime, we've been finding
more cases where this function needs to be called, so now we're going to
fully embrace it until clap-rs#2911 so people aren't scrared off by the hidden
implementation from using it.

This was inspired by clap-rs#3602

Comptibility: Though this adds a deprecation which we general reserve
for minor or major versions, this is enough of a corner case that I'm
fine doing this in a patch release.
@epage epage modified the milestones: 4.0, 5.0 Jun 1, 2022
@epage
Copy link
Member Author

epage commented Sep 7, 2022

A simple way we can handle this is if we add the type

pub struct Built<T>(T);

impl Built<Command> {
   pub fn get_arguments(&self) -> impl Iterator<Item=Built<Arg>>;

   pub fn get_subcommands(&self) -> impl Iterator<Item=Built<Command>>;
}

impl Built<&'_ Command> {
   pub fn get_arguments(&self) -> impl Iterator<Item=Built<Arg>>;

   pub fn get_subcommands(&self) -> impl Iterator<Item=Built<Command>>;
}

impl<T> AsRef<T> for Built<T>{
    #[inline]
    fn as_ref(&self) -> &T{
        &self.0
    }
}

impl<T> Borrow<T> for Built<T>{
    #[inline]
    fn borrow(&self) -> &T{
        &self.0
    }
}

impl<T> :Deref for Built<T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T{
        &self.0
    }
}

We would also remove the get_arguments getters on Command in favor of get_arguments_mut to keep clear that Command isn't built

This still leaves trying to re-work the parser so it can work off of mut and immutable Command.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-builder Area: Builder API C-bug Category: Updating dependencies E-medium Call for participation: Experience needed to fix: Medium / intermediate M-breaking-change Meta: Implementing or merging this will introduce a breaking change.
Projects
None yet
Development

No branches or pull requests

2 participants