rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.23k stars 12.7k forks source link

No turbofish suggestion for complex expressions #81816

Open tesuji opened 3 years ago

tesuji commented 3 years ago

The turbofish suggestions are displayed for single expressions, but not for complex expressions. https://rust.godbolt.org/z/cbn58f

I tried this code:

use std::sync::Arc;
use std::sync::RwLock;

fn main() {
    let uuid = Arc::new(RwLock::new(std::collections::HashMap<i32, i64>::new()));
}

I expected to see this happen: Turbofish ::<> suggestion for HashMap type. Instead, this happened: Invalid suggestion to use private field to initialize HashMap.

error[E0423]: expected value, found struct `std::collections::HashMap`
   --> <source>:5:37
    |
5   |       let uuid = Arc::new(RwLock::new(std::collections::HashMap<i32, i64>::new()));
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `std::collections::HashMap { base: val }`

error[E0423]: expected value, found builtin type `i32`
 --> <source>:5:63
  |
5 |     let uuid = Arc::new(RwLock::new(std::collections::HashMap<i32, i64>::new()));
  |                                                               ^^^ not a value

Meta

rustc --version --verbose: rustc 1.51.0-nightly (e708cbd91 2021-02-03)

@rustbot label A-diagnostics D-confusing D-incorrect T-compiler D-invalid-suggestion

*This issue was detected by an user on Reddit: https://www.reddit.com/r/rust/comments/ld6q8u/bastion_of_the_turbofish_a_brief_tale_lamenting/gm5j0yz/.

SNCPlay42 commented 3 years ago

There's no turbofish suggestion currently because the code parses validly (the same bastion of the turbofish problem that the reddit thread was about) as:

let uuid = Arc::new(RwLock::new( (std::collections::HashMap < i32), (i64 > ::new()) ));

Which only errors after parsing, when the compiler checks the kind of items involved. I think the compiler could suggest a turbofish in this case as well - if the reason it expected an item to be a value is that the item is on the LHS of <, but it found a type/function instead, then it seems very likely the user meant to use a turbofish, especially if we can find the would-be matching >.

The suggestion to use literal syntax with a private field should definitely go, at any rate (but can the compiler compute visibilities of items at this early stage?)

estebank commented 1 year ago

The output has gotten even more verbose, with a misleading suggestion that hints at what the problem is.

error[E0423]: expected value, found struct `std::collections::HashMap`
 --> src/main.rs:5:37
  |
5 |     let uuid = Arc::new(RwLock::new(std::collections::HashMap<i32, i64>::new()));
  |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `std::collections::HashMap { base: val }`
 --> /rustc/ee0412d1ef81efcfabe7f66cd21476ca85d618b1/library/std/src/collections/hash/map.rs:214:1
  |
  = note: `std::collections::HashMap` defined here

error[E0423]: expected value, found builtin type `i32`
 --> src/main.rs:5:63
  |
5 |     let uuid = Arc::new(RwLock::new(std::collections::HashMap<i32, i64>::new()));
  |                                                               ^^^ not a value

error[[E0423]](https://doc.rust-lang.org/nightly/error-index.html#E0423): expected value, found builtin type `i64`
 --> src/main.rs:5:68
  |
5 |     let uuid = Arc::new(RwLock::new(std::collections::HashMap<i32, i64>::new()));
  |                                                                    ^^^ not a value

error[E0425]: cannot find external crate `new` in the crate root
 --> src/main.rs:5:74
  |
5 |     let uuid = Arc::new(RwLock::new(std::collections::HashMap<i32, i64>::new()));
  |                                                                          ^^^ not found in the crate root

error[E0061]: this function takes 1 argument but 2 arguments were supplied
 --> src/main.rs:5:25
  |
5 |     let uuid = Arc::new(RwLock::new(std::collections::HashMap<i32, i64>::new()));
  |                         ^^^^^^^^^^^                                ----------- argument of type `bool` unexpected
  |
note: associated function defined here
 --> /rustc/ee0412d1ef81efcfabe7f66cd21476ca85d618b1/library/std/src/sync/rwlock.rs:160:18
help: remove the extra argument
  |
5 |     let uuid = Arc::new(RwLock::new(std::collections::HashMap<i32));
  |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I think that with some targeted work in rustc_resolve we can make this provide an appropriate suggestion, and silence a bunch of the subsequent errors.