Description
Given the following code (play):
fn main() {
let f = std::fs::File::open("/proc/meminfo").unwrap();
let b = std::io::BufReader(f);
for line in b.lines() { dbg!(line); }
}
The current output is:
error[[E0423]](https://doc.rust-lang.org/nightly/error-index.html#E0423): expected function, tuple struct or tuple variant, found struct `std::io::BufReader`
--> src/main.rs:3:13
|
3 | let b = std::io::BufReader(f);
| ^^^^^^^^^^^^^^^^^^^^^ help: use struct literal syntax instead: `std::io::BufReader { inner: val, buf: val }`
Ideally the output should look like:
3 | let b = std::io::BufReader(f);
| ^^^^^^^^^^^^^^^^^^^^^ help: use constructor method instead: `std::io::BufReader::new(f)`
In other words: If a type from an external crate has non-public fields, we should not be suggesting the user attempt to use them for constructing an instance of the type. Especially in the case of tuple struct expressions, which can be a sign of an omitted constructor method name. (I'm thinking specifically of people who are coming from Java, and thus may be used to writing something like new BufReader(f)
where we would write BufReader::new(f)
.)
A simple heuristic here could be to look for methods on the type that 1. do not take self
parameter, and 2. (optional) have a matching number of arguments
This issue is similar to #66067 and #52144, except worse, because (if I understand them correctly) those two are both talking about improving the UX for incorrect tuple struct expressions that at least are also referring to tuple struct definitions.
In the scenario described here, we have a record struct definition being used as a tuple struct, which, in the presence of private fields, we should interpret as a strong hint that someone probably meant to use a method.