rust-lang / rust-lang/rust

function "in_external_macro” judgment is incorrect

Open
#131,993 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-proc-macros C-bug E-needs-investigation T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I use the derive macro provided by the clap crate in my code, and then call the in_external_macro function in the context of a custom lint diagnostic code. The function determines that the code derived from the derive macro is local code.

I tried this code:

fn main() {
    let _a = 1;
}

use clap::Args;


#[derive(Args)]
pub struct ToFrom {
    #[arg(long = "workspace")]
    a: i32,
}

dependency is clap = { version = "=4.2.0", features = ["derive"] }

My lint code is:

    fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) {
           let res = in_external_macro(cx.sess(), block.span);
        info!("check block in_external_macro res {:?}", res);
        if res == false {
            info!("check block {:?}", block);
        }
}

I expected to see this happen: I think all code generated by derived macros should belong to external macros derived from external crates.

Instead, this happened: Some of the code generated by the derived macro is considered to be local code

The error macro code is expanded as follows.
The blocks inside the .arg function are considered native code.

                .arg({
                    #[allow(deprecated)]
                    let arg = clap::Arg::new("a")
                        .value_name("A")
                        .required(true && clap::ArgAction::Set.takes_values())
                        .value_parser({
                            use ::clap_builder::builder::via_prelude::*;
                            let auto = ::clap_builder::builder::_AutoValueParser::<
                                i32,
                            >::new();
                            (&&&&&&auto).value_parser()
                        })
                        .action(clap::ArgAction::Set);
                    let arg = arg.long("workspace");
                    let arg = arg.required(false);
                    arg
                });

rustc --version --verbose:

+nightly-2024-03-07

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the supplied clap derive-macro example with the custom lint and inspect the in_external_macro entry point used on block.span. Compare its result for the generated blocks inside the .arg expansion with the reported expectation that derived code from an external crate is classified as external. Done means the behavior is covered and the classification matches the agreed macro-origin semantics.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.