Skip to content

no-such-field for #[cfg(not(test))] with StructOpt #11657

Closed
@kolloch

Description

@kolloch
use structopt::StructOpt;

#[derive(StructOpt)]
struct Opt {
    #[cfg(not(test))]
    arg: String, // <- error for the whole line
}

fn main() {
    #[cfg(not(test))]
    let opt = Opt::from_args();
    #[cfg(not(test))]
    println!("arg {}", opt.arg);
}

=>

no such fieldrust-analyzer[no-such-field](https://rust-analyzer.github.io/manual.html#no-such-field)

cargo test cargo build cargo build --release don't show any errors.

The error occurs only in combination with #[derive(StructOpt)].

Full source:
https://github.com/kolloch/no-such-field

itemtree.rs

Strips #[cfg(not(test))] items from main but not from struct:

pub(self) use structopt::StructOpt;

#[derive(StructOpt)]  // AttrId { ast_index: 0 }
pub(self) struct Opt {
    #[cfg(not (test))]  // AttrId { ast_index: 0 }
    pub(self) arg: String,
}

// flags = 0x2
pub(self) fn main() -> ();

cargo expand

❯ cargo expand --tests
   Compiling no-such-field v0.1.0 (/home/peter/nexxiot/no-such-field)
    Finished test [unoptimized + debuginfo] target(s) in 0.09s
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use structopt::StructOpt;
struct Opt {}
#[allow(unused_variables)]
#[allow(unknown_lints)]
#[allow(
    clippy::style,
    clippy::complexity,
    clippy::pedantic,
    clippy::restriction,
    clippy::perf,
    clippy::deprecated,
    clippy::nursery,
    clippy::cargo
)]
#[deny(clippy::correctness)]
#[allow(dead_code, unreachable_code)]
impl ::structopt::StructOpt for Opt {
    fn clap<'a, 'b>() -> ::structopt::clap::App<'a, 'b> {
        let app = ::structopt::clap::App::new("no-such-field");
        <Self as ::structopt::StructOptInternal>::augment_clap(app)
    }
    fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self {
        Opt {}
    }
}
#[allow(unused_variables)]
#[allow(unknown_lints)]
#[allow(
    clippy::style,
    clippy::complexity,
    clippy::pedantic,
    clippy::restriction,
    clippy::perf,
    clippy::deprecated,
    clippy::nursery,
    clippy::cargo
)]
#[deny(clippy::correctness)]
#[allow(dead_code, unreachable_code)]
impl ::structopt::StructOptInternal for Opt {
    fn augment_clap<'a, 'b>(app: ::structopt::clap::App<'a, 'b>) -> ::structopt::clap::App<'a, 'b> {
        {
            let app = app;
            app.version("0.1.0")
        }
    }
    fn is_subcommand() -> bool {
        false
    }
}
#[allow(dead_code)]
fn main() {}
#[rustc_main]
pub fn main() -> () {
    extern crate test;
    test::test_main_static(&[])
}
❯ cargo expand        
    Checking no-such-field v0.1.0 (/home/peter/nexxiot/no-such-field)
    Finished dev [unoptimized + debuginfo] target(s) in 0.09s
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use structopt::StructOpt;
struct Opt {
    #[cfg(not(test))]
    arg: String,
}
#[allow(unused_variables)]
#[allow(unknown_lints)]
#[allow(
    clippy::style,
    clippy::complexity,
    clippy::pedantic,
    clippy::restriction,
    clippy::perf,
    clippy::deprecated,
    clippy::nursery,
    clippy::cargo
)]
#[deny(clippy::correctness)]
#[allow(dead_code, unreachable_code)]
impl ::structopt::StructOpt for Opt {
    fn clap<'a, 'b>() -> ::structopt::clap::App<'a, 'b> {
        let app = ::structopt::clap::App::new("no-such-field");
        <Self as ::structopt::StructOptInternal>::augment_clap(app)
    }
    fn from_clap(matches: &::structopt::clap::ArgMatches) -> Self {
        Opt {
            arg: matches
                .value_of("arg")
                .map(|s| ::std::str::FromStr::from_str(s).unwrap())
                .unwrap(),
        }
    }
}
#[allow(unused_variables)]
#[allow(unknown_lints)]
#[allow(
    clippy::style,
    clippy::complexity,
    clippy::pedantic,
    clippy::restriction,
    clippy::perf,
    clippy::deprecated,
    clippy::nursery,
    clippy::cargo
)]
#[deny(clippy::correctness)]
#[allow(dead_code, unreachable_code)]
impl ::structopt::StructOptInternal for Opt {
    fn augment_clap<'a, 'b>(app: ::structopt::clap::App<'a, 'b>) -> ::structopt::clap::App<'a, 'b> {
        {
            let app = app;
            let app = app.arg(
                ::structopt::clap::Arg::with_name("arg")
                    .takes_value(true)
                    .multiple(false)
                    .required(true)
                    .validator(|s| {
                        ::std::str::FromStr::from_str(s.as_str())
                            .map(|_: String| ())
                            .map_err(|e| e.to_string())
                    }),
            );
            app.version("0.1.0")
        }
    }
    fn is_subcommand() -> bool {
        false
    }
}
fn main() {
    #[cfg(not(test))]
    let opt = Opt::from_args();
    {
        ::std::io::_print(::core::fmt::Arguments::new_v1(
            &["arg ", "\n"],
            &[::core::fmt::ArgumentV1::new_display(&opt.arg)],
        ));
    };
}

rust-analyzer version: (eg. output of "Rust Analyzer: Show RA Version" command)
rust-analyzer version: 5fae65dd2 2022-03-07 stable

rustc version: (eg. output of rustc -V)
rustc 1.59.0 (9d1b2106e 2022-02-23)

relevant settings: (eg. client settings, or environment variables like CARGO, RUSTUP_HOME or CARGO_HOME)

      "rust-analyzer.hoverActions.references": true,
      "rust-analyzer.inlayHints.parameterHints": false,
      "rust-analyzer.lens.enumVariantReferences": true,
      "rust-analyzer.hover.documentation": false,
      "rust-analyzer.workspace.symbol.search.kind": "all_symbols",

💌 thank you for providing rust analyzer

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-macromacro expansion

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions