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

fix(clap_generate): zsh completion generation panic #2191

Merged
merged 4 commits into from
Nov 26, 2020

Conversation

ahkrr
Copy link

@ahkrr ahkrr commented Oct 30, 2020

This PR fixes a panic that would occur when a zsh completion file was being generated
for an app that contains global arguments that have conflicts with other arguments which aren't
present in all the subcommands that the global argument would be applied to.

The added test would panic before the fix.

Only the test added without the fix to observe the problem.
git clone --branch zsh_completion_bug https://github.com/ahkrr/clap.git
cd clap/clap_generate/tests && cargo test

I haven't found an open issue regarding this panic.

hk added 2 commits October 30, 2020 21:04
zsh completion generation would panic if a global argument 
had conflicts with another argument which was present in its 
own command but not in its subcommands
the test that was added tests for a panic that would occur
when a global argument had a conflict with another argument 
that wasn't present in all the subcommands that the global 
argument was present in 

this would occur inside the get_arg_conflicts_with function
@ahkrr
Copy link
Author

ahkrr commented Oct 30, 2020

This PR would need a MSRV of 1.46.0

Maybe before 1.46.0 one couldn't immutably borrow through indexing?
This problem doesn't exist from 1.46.0. The method in question doesn't need mutable access.

vec.append(&mut self.subcommands[idx].get_subcommands_containing(arg));
^^^^^^^^^^^^^^^^ self is a & reference, so the data it refers to cannot be borrowed as mutable

Rewriting the patch to work before 1.46.0 would mean a more intrusive change.
Maybe this can be merged in a future when 1.46.0 is usable.

@pksunkara
Copy link
Member

Can you please add a TODO regarding 1.46 in the code?

@ahkrr
Copy link
Author

ahkrr commented Nov 5, 2020

The last commit fix: compatibility with rustc 1.42.0 has already solved the problem.

It was a bit silly of me to forget, that one can get at the items of a vec not only through indexing but also with the .get methods.

According to the CI, the tests now pass on 1.42.

@pksunkara
Copy link
Member

Yes, please add the TODO so that I can upgrade the code later on when moving to 1.46

@ahkrr
Copy link
Author

ahkrr commented Nov 5, 2020

I've added a TODO to the code.

src/build/app/mod.rs Outdated Show resolved Hide resolved
src/build/app/mod.rs Show resolved Hide resolved
src/build/app/mod.rs Outdated Show resolved Hide resolved
preserving the observable behavior of the existing 
public api, while handling global arguments separately in 
get_arg_conflicts_with
@ahkrr
Copy link
Author

ahkrr commented Nov 9, 2020

I have thought about the problem again.
Instead of adding new public methods wouldn't it be better if the existing get_arg_conflicts_with does the right thing?
This method is only called in clap_generate and even if it is called with global arguments by users of clap, the global conflicts are a superset of the local ones, so the result would be the same even with the branch and delegation to get_global_arg_conflicts_with.

@pksunkara
Copy link
Member

That sounds good to me.

@ahkrr
Copy link
Author

ahkrr commented Nov 17, 2020

I had already implemented my suggestion of the previous comment at the time of posting.
If there are no more issues after reviewing this PR, the merging could probably proceed.

Copy link
Member

@pksunkara pksunkara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one minor change and I can merge.

for conflict in conflicts {
if let Some(s) = conflict.get_short() {
res.push(format!("-{}", s));
match (app_global, arg.get_global()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's decrease the match scope to only get the conflicts. That way you can reduce duplication and don't even need the push_conflicts function.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Decreasing the scope is problematic because app_global and app have different lifetimes. If I try to handle the conflicts outside the match I get a lifetime mismatch error. Because this isn't performance critical and the duplication isn't that large, I would ask you, if this change is important enough, for me to take a longer look at this again or if the merge can proceed?

@pksunkara
Copy link
Member

pksunkara commented Nov 26, 2020

Can you please do me a favor and check if this fixes #2220? I still can't get zsh working locally.

@ahkrr
Copy link
Author

ahkrr commented Nov 26, 2020

Yes. I will look into #2220

Copy link
Member

@pksunkara pksunkara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bors r+

@bors
Copy link
Contributor

bors bot commented Nov 26, 2020

🕐 Waiting for PR status (Github check) to be set, probably by CI. Bors will automatically try to run when all required PR statuses are set.

@pksunkara pksunkara merged commit d36d911 into clap-rs:master Nov 26, 2020
@bors
Copy link
Contributor

bors bot commented Nov 26, 2020

Stopped waiting for PR status (Github check) without running due to duplicate requests to run. You may check Bors to see that this PR is included in a batch by one of the other requests.

@pksunkara
Copy link
Member

If you can make a draft PR removing the TODO and changing the code to 1.46, I should get to it sometime next week after upgrading the MSRV.

@ahkrr
Copy link
Author

ahkrr commented Nov 26, 2020

I can do that. In addition, maybe clap 3 should remove the panci! that caused these problems in zsh completion generation, because everything else seems to work fine if conflicts are declared that don't exist. I am not aware of all the behavior around conflicts but it should be ok and the impact would be very low.

@pksunkara
Copy link
Member

Nah. We panic much more earlier in development when this happens. So, removing it here doesn't change much.

@pksunkara
Copy link
Member

I will get the 1.46 support out tomorrow at #2228. Hopefully you can send a PR soon for this TODO item.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants