clap-rs / clap

A full featured, fast Command Line Argument Parser for Rust
docs.rs/clap
Apache License 2.0
14.11k stars 1.03k forks source link

#[derive(Clap)] should support empty structs #1705

Closed emilazy closed 4 years ago

emilazy commented 4 years ago

Describe your use case

This is obviously trivial compared to just doing struct Args {}, but it would be nice to maintain Rust's general consistency in allowing the same things for all three forms.

Describe the solution you'd like

#[derive(Clap)]
struct UnitLikeStruct;

#[derive(Clap)]
struct EmptyTupleStruct();

Additional context

error: `#[derive(Clap)]` only supports non-tuple structs and enums
   |
   | #[derive(Clap)]
   |          ^^^^
   |
emilazy commented 4 years ago

Arguably newtypes (single-element tuple structs) could be supported too, but that's less clear-cut.

pksunkara commented 4 years ago

There was already some discussion on this, https://github.com/clap-rs/clap_derive/pull/19

I don't really see why this is useful. There's no real difference between struct Foo and struct Foo {}, the second works already. We may also want to give some special meaning to unit structs in future, so let's leave it as is for now.

Empty tuple structs would fall into the same category.

But, single tuple struct could be a different issue. Do we support any tuple structs at all in the derive library?

emilazy commented 4 years ago

I don't think it would be a good idea to give them a different meaning; in general Rust tries to make them all behave as similarly as possible, and there's been a consistent pattern of RFCs unifying functionality and behaviour between all three so that everything works between them (.0 etc.).

I tend to make all empty structs unit-like structs by default, for general style reasons, and it does have one slight "advantage" (you get a free const for it); I found it surprising to be unable to derive Clap for them.

CreepySkeleton commented 4 years ago

@emilazy I'm not very excited of "general style reasons" argument because, you know, so many man, so many minds. Everybody tends to push their own way of making things roll; some people (myself included) like "different types of items - different behavior", some adore "similar enough - same behavior". It's merely a matter of taste, and whenever you start arguing about personal taste it becomes "it must change just because I think it's beautiful" thing real quick. So I'm going to be tenacious here and just stubbornly say that unless I hear very strong voice for the unification (something like a dozen of "I want it too" comments here) I'm not changing my mind.

in general Rust tries to make them all behave as similarly as possible, and there's been a consistent pattern of RFCs unifying functionality and behaviour between all three so that everything works between them (.0 etc.).

This is pretty good argument but only if some of those RFCs were accepted. Unfortunately, I haven't been able to find one of those; could you please share a link or two with us?

Dylan-DPC-zz commented 4 years ago

I agree with @emilazy here. If in rust struct Foo {} and struct Foo;are the same, then the corresponding derive behaviour should also be equivalent.

CreepySkeleton commented 4 years ago

Hmm, according to the Rust reference, they are the same-ish StructStruct entity, indeed:

Struct :
      StructStruct
   | TupleStruct

StructStruct :
   struct IDENTIFIER  Generics? WhereClause? ( { StructFields? } | ; )

TupleStruct :
   struct IDENTIFIER  Generics? ( TupleFields? ) WhereClause? ;

So maybe it really worth the candle, but tuple structs differ from the others even at the syntax level.

I think that, if the other members think unit structs should be supported, than we can do that, but I'm not OK with tuple structs, empty or not, unless somebody comes up with a real world use case.

TeXitoi commented 4 years ago

Empty struct with braces was added quite later, thus there is no really difference between struct Foo {} and struct Foo;

https://github.com/rust-lang/rfcs/blob/master/text/0218-empty-struct-with-braces.md (edited with the official repository)