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

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

Closed
kolloch opened this issue Mar 8, 2022 · 3 comments
Closed

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

kolloch opened this issue Mar 8, 2022 · 3 comments
Labels
A-macro macro expansion

Comments

@kolloch
Copy link

kolloch commented Mar 8, 2022

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

@Veykril Veykril added the A-macro macro expansion label Mar 8, 2022
@bjorn3
Copy link
Member

bjorn3 commented Mar 8, 2022

#[cfg(test)] is enabled by default, so that field should be omitted. It shouldn't even be passed to the derive macro, which I suspect happens here. If the field is passed to the derive macro, it would result in an access in the macro output, thus resulting in a no-such-field error.

@jonas-schievink
Copy link
Contributor

cc #8434

bors added a commit that referenced this issue Mar 12, 2024
cfg Attribute Stripping for Proc Macro Expansion

This will attempt to process cfg attributes and cfg_attr attributes for proc macro expansion.
![image](https://github.com/rust-lang/rust-analyzer/assets/11785959/b85ef203-14a5-44c9-9b67-59a65a5f2d96)

Closes #8434 , #11657, and #13904
@Veykril
Copy link
Member

Veykril commented Mar 12, 2024

Fixed in #16789

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

No branches or pull requests

4 participants