Skip to content

Flag misinterpreted as option when using macros on Rust 1.47.0 #439

Closed
tbillington/kondo
#34

Description

@Lakier15

It seems that with 1.47.0 macro'ing structopt causes misbehavior in the functionality of structopt. I found out that a flag gets erroneously parsed as an option instead.

In this example:

use structopt::StructOpt;

macro_rules! command {
    (
        $(#[derive($($t:tt),+)])?
        #[structopt(
            name = $name:literal,
            about = $about:literal,
            $( $var:ident = $val:expr, )*
        )]
        struct $command:ident {
            $(
                $(#[$m:meta])*
                $field:ident: $type:ty,
            )*
        }
    ) => (
        $(#[derive($($t),+)])?
        #[structopt(
            name = $name,
            about = $about,
            $( $var = $val, )*
        )]
        struct $command {
            $(
                $(#[$m])*
                $field: $type,
            )*
        }
    );
}

command!{
    #[derive(Debug, StructOpt)]
    #[structopt(
        name = "opts", 
        about = "Opts",
    )]
    struct Opts {
        #[structopt(long = "x", help = "xxx")]
        x: bool,
    }
}

fn main() {
    println!("{:?}", Opts::from_args());
}

when compiling with Rust 1.46.0

$ cargo +1.46.0 run -- --help
opts 0.1.0
Opts

USAGE:
    x [FLAGS]

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information
        --x          xxx

with Rust 1.47.0

$ cargo +1.47.0 run -- --help
opts 0.1.0
Opts

USAGE:
    x --x <x>

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information

OPTIONS:
        --x <x>    xxx

I believe that it might be because of rust-lang/rust#73084

Activity

  1. CreepySkeleton commented on Oct 12, 2020

    @CreepySkeleton
    Collaborator

    This can be further simplified to

    macro_rules! m {
        ($bool:ty) => {
            #[derive(Debug, StructOpt)]
            struct Opts {
                #[structopt(long = "x")]
                x: $bool
            }
        };
    }
    
    m!(bool);

    Basically, tokens passed to a macro and assigned to a metavariable ($bool:ty) are wrapped in an invisible Syn::Type::Group. Our type checking doesn't account for that, and bool wasn't recognized as such.

  2. added 2 commits that reference this issue on Oct 12, 2020
    ae9fd6f
    1a8f8f7
  3. added a commit that references this issue on Oct 12, 2020
    0852b91
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions