rust-lang / rust-analyzer

A Rust compiler front-end for IDEs
https://rust-analyzer.github.io/
Apache License 2.0
13.81k stars 1.53k forks source link

incorrect error report: treat the Option field as iterator for `take()` method call #15027

Open gftea opened 1 year ago

gftea commented 1 year ago

rust-analyzer version: (eg. output of "rust-analyzer: Show RA Version" command, accessible in VSCode via Ctrl/⌘+Shift+P)

rust-analyzer version: 0.4.1547-standalone`

rustc version: (eg. output of rustc -V)

rustc 1.70.0 (90c541806 2023-05-31)

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

I had below config in vscode, but I think it is not relevant, because the fault is not from clippy "rust-analyzer.check.command": "clippy",

Status analysis output

Analysis:
101mb of files
5387 trees, 128 preserved
49202 trees, 512 preserved (macros)
0b of library index symbols (0)
0b of module index symbols (0)
1151mb in total

Debug info:
177243 attribute query entries, 417688 total attributes (12mb for storing entries)
54360 ast id maps
539 block def maps

File info:
Crate: libp2p_swarm(332)
Dependencies: core=Idx::<CrateData>(0), alloc=Idx::<CrateData>(1), test=Idx::<CrateData>(8), std=Idx::<CrateData>(10), proc_macro=Idx::<CrateData>(11), getrandom=Idx::<CrateData>(23), once_cell=Idx::<CrateData>(49), once_cell=Idx::<CrateData>(49), log=Idx::<CrateData>(109), async_std=Idx::<CrateData>(121), async_std=Idx::<CrateData>(121), smallvec=Idx::<CrateData>(133), tokio=Idx::<CrateData>(150), fnv=Idx::<CrateData>(158), rand=Idx::<CrateData>(173), env_logger=Idx::<CrateData>(195), futures=Idx::<CrateData>(197), futures=Idx::<CrateData>(197), either=Idx::<CrateData>(198), either=Idx::<CrateData>(198), futures_timer=Idx::<CrateData>(208), instant=Idx::<CrateData>(209), quickcheck=Idx::<CrateData>(281), void=Idx::<CrateData>(285), void=Idx::<CrateData>(285), libp2p_identity=Idx::<CrateData>(286), libp2p_identity=Idx::<CrateData>(286), libp2p_plaintext=Idx::<CrateData>(290), multistream_select=Idx::<CrateData>(321), libp2p_core=Idx::<CrateData>(322), libp2p_swarm_derive=Idx::<CrateData>(324), libp2p_swarm_derive=Idx::<CrateData>(324), libp2p_yamux=Idx::<CrateData>(326), libp2p_swarm_test=Idx::<CrateData>(327), trybuild=Idx::<CrateData>(330), wasm_bindgen_futures=Idx::<CrateData>(331)

language server output

[ERROR project_model::workspace] cyclic deps: libp2p_mplex(Idx::<CrateData>(250)) -> libp2p_core(Idx::<CrateData>(228)), alternative path: libp2p_core(Idx::<CrateData>(228)) -> libp2p_mplex(Idx::<CrateData>(250))
[ERROR project_model::workspace] cyclic deps: libp2p_muxer_test_harness(Idx::<CrateData>(253)) -> libp2p_core(Idx::<CrateData>(228)), alternative path: libp2p_core(Idx::<CrateData>(228)) -> libp2p_mplex(Idx::<CrateData>(250)) -> libp2p_muxer_test_harness(Idx::<CrateData>(253))
[ERROR project_model::workspace] cyclic deps: libp2p_noise(Idx::<CrateData>(254)) -> libp2p_core(Idx::<CrateData>(228)), alternative path: libp2p_core(Idx::<CrateData>(228)) -> libp2p_noise(Idx::<CrateData>(254))
[ERROR project_model::workspace] cyclic deps: libp2p_plaintext(Idx::<CrateData>(261)) -> libp2p_core(Idx::<CrateData>(228)), alternative path: libp2p_core(Idx::<CrateData>(228)) -> libp2p_mplex(Idx::<CrateData>(250)) -> libp2p_plaintext(Idx::<CrateData>(261))
[ERROR project_model::workspace] cyclic deps: libp2p_swarm(Idx::<CrateData>(274)) -> libp2p_identify(Idx::<CrateData>(238)), alternative path: libp2p_identify(Idx::<CrateData>(238)) -> libp2p_swarm(Idx::<CrateData>(274))
[ERROR project_model::workspace] cyclic deps: libp2p_swarm(Idx::<CrateData>(274)) -> libp2p_kad(Idx::<CrateData>(244)), alternative path: libp2p_kad(Idx::<CrateData>(244)) -> libp2p_identify(Idx::<CrateData>(238)) -> libp2p_swarm(Idx::<CrateData>(274))
[ERROR project_model::workspace] cyclic deps: libp2p_swarm(Idx::<CrateData>(274)) -> libp2p_ping(Idx::<CrateData>(259)), alternative path: libp2p_ping(Idx::<CrateData>(259)) -> libp2p_swarm(Idx::<CrateData>(274))
[ERROR project_model::workspace] cyclic deps: libp2p_swarm_test(Idx::<CrateData>(278)) -> libp2p_swarm(Idx::<CrateData>(274)), alternative path: libp2p_swarm(Idx::<CrateData>(274)) -> libp2p_swarm_test(Idx::<CrateData>(278))
[ERROR project_model::workspace] cyclic deps: libp2p_tcp(Idx::<CrateData>(279)) -> libp2p_core(Idx::<CrateData>(228)), alternative path: libp2p_core(Idx::<CrateData>(228)) -> libp2p_mplex(Idx::<CrateData>(250)) -> libp2p_tcp(Idx::<CrateData>(279))
[ERROR project_model::workspace] cyclic deps: multistream_select(Idx::<CrateData>(313)) -> libp2p_core(Idx::<CrateData>(228)), alternative path: libp2p_core(Idx::<CrateData>(228)) -> multistream_select(Idx::<CrateData>(313))
[ERROR project_model::workspace] cyclic deps: multistream_select(Idx::<CrateData>(313)) -> libp2p_swarm(Idx::<CrateData>(274)), alternative path: libp2p_swarm(Idx::<CrateData>(274)) -> libp2p_core(Idx::<CrateData>(228)) -> multistream_select(Idx::<CrateData>(313))
[ERROR project_model::workspace] cyclic deps: multistream_select(Idx::<CrateData>(313)) -> libp2p_yamux(Idx::<CrateData>(288)), alternative path: libp2p_yamux(Idx::<CrateData>(288)) -> libp2p_core(Idx::<CrateData>(228)) -> multistream_select(Idx::<CrateData>(313))

error report

See below screenshot, the this.pending_event is an Option<( ... )>, but rust-analyzer interpret it as iterator, and report error expected 1 argument, found 0

image

flodiebold commented 1 year ago

Probably https://github.com/rust-lang/chalk/issues/727 like https://github.com/rust-lang/rust-analyzer/issues/14949 and https://github.com/rust-lang/rust-analyzer/issues/14933.

davidbarsky commented 5 months ago

The reproduction in #16516 seems to be substantially smaller than other examples I've seen:

fn my_example(
    _x: impl IntoIterator<Item = impl AsRef<str>>,
    _y: impl IntoIterator<Item = impl AsRef<str>>,
) {
    let mut cmd = std::process::Command::new("foo");

    let mut child = cmd.spawn().unwrap();
    child.stdin.take();
}

fn main() {}

Interestingly, removing a single parameter doesn't doesn't result in this lint firing.

flodiebold commented 4 months ago

@davidbarsky That's the same as #10653 which I'm not so sure is the same as this issue, since there are no trait bounds on type parameters in the original example here.

In general ".take() gets inferred as Iterator::take instead of Option::take" often is just a symptom of the type of the receiver being unknown, which can have any number of root causes. Although we should at least probably not show further arg-count-mismatch diagnostics if the method receiver was unknown...

davidbarsky commented 4 months ago

@davidbarsky That's the same as #10653 which I'm not so sure is the same as this issue, since there are no trait bounds on type parameters in the original example here.

In general ".take() gets inferred as Iterator::take instead of Option::take" often is just a symptom of the type of the receiver being unknown, which can have any number of root causes. Although we should at least probably not show further arg-count-mismatch diagnostics if the method receiver was unknown...

Yeah, you're right: I mistakenly picked this one instead of the "two iterator arguments" reports.

ZhennanWu commented 3 weeks ago

I would like to give an update. In recent RA versions (rust-analyzer version: 0.3.1975-standalone (71a816a90 2024-05-26)), this error still exist, but in my case https://github.com/rust-lang/rust-analyzer/issues/14933, the error can go away if I:

  1. cargo clean
  2. Restart RA server. Invoke rust-analyzer in the error file (such as search a variable definition). Now it still reports error.
  3. Restart RA server again. Now the error goes away. Type hint is flawless. Everyone is happy.
  4. Whenever the error re-pops up after you modify some random unrelated code. Restart RA server again.

I can't explain how this works but it is definitely reproducible. Makes the error less of a nuisance.

Also, it seems a same mechanism is also causing false error report in pattern matching (it will falsely report some match expressions to be non-exhaustive if there are nested pattern bindings). They both go away after the above "restart RA server" trick.