rust-lang / rust

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

Better messages when using ADT constructor as value #82083

Open estebank opened 3 years ago

estebank commented 3 years ago

Given:

struct S {}
enum E {
    V,
}
struct T();

fn foo() -> S {
    S
}

fn bar() -> E {
    E
}

fn baz() -> T {
    T
}

we currently emit

error[E0423]: expected value, found struct `S`
 --> src/lib.rs:8:5
  |
1 | struct S {}
  | ----------- `S` defined here
...
5 | struct T();
  | ----------- similarly named tuple struct `T` defined here
...
8 |     S
  |     ^
  |
help: use struct literal syntax instead
  |
8 |     S {}
  |
help: a tuple struct with a similar name exists
  |
8 |     T
  |
help: consider importing this unit variant instead
  |
1 | use unicode_bidi::BidiClass::S;
  |

error[E0423]: expected value, found enum `E`
  --> src/lib.rs:12:5
   |
5  | struct T();
   | ----------- similarly named tuple struct `T` defined here
...
12 |     E
   |     ^
   |
note: the enum is defined here
  --> src/lib.rs:2:1
   |
2  | / enum E {
3  | |     V,
4  | | }
   | |_^
help: you might have meant to use the following enum variant
   |
12 |     E::V
   |
help: a tuple struct with a similar name exists
   |
12 |     T
   |
help: consider importing one of these items instead
   |
1  | use core::f32::consts::E;
   |
1  | use core::f64::consts::E;
   |
1  | use pin_utils::core_reexport::f32::consts::E;
   |
1  | use pin_utils::core_reexport::f64::consts::E;
   |
     and 2 other candidates

error[E0308]: mismatched types
  --> src/lib.rs:16:5
   |
5  | struct T();
   | ----------- fn() -> T {T} defined here
...
15 | fn baz() -> T {
   |             - expected `T` because of return type
16 |     T
   |     ^ expected struct `T`, found fn item
   |
   = note: expected struct `T`
             found fn item `fn() -> T {T}`
help: use parentheses to instantiate this tuple struct
   |
16 |     T()
   |      ^^

which is reasonable, particularly the suggestions, but it isn't entirely clear to a newcomer that S in TypeNS isn't the same as S in ValueNS.

Ideally, the output would look closer to:

error[E0423]: expected value of type `S`, found struct constructor for type `S`
 --> src/lib.rs:8:5
  |
1 | struct S {}
  | ----------- `S` defined here
...
5 | struct T();
  | ----------- similarly named tuple struct `T` defined here
...
  | fn foo() -> S {
  |             - expected because of this return type
8 |     S
  |     ^ struct constructor used as value
  |
help: use struct literal syntax instead
  |
8 |     S {}
  |

error[E0423]: expected value of type `E`, found enum type `E`
  --> src/lib.rs:12:5
   |
2  | enum E {
   | ------ `E` defined here
...
5  | struct T();
   | ----------- similarly named tuple struct `T` defined here
...
   | fn bar() -> E {
   |              - expected because of this return type
12 |     E
   |     ^ enum type used as value
   |
help: you might have meant to use the following enum variant
   |
12 |     E::V
   |

error[E0308]: mismatched types
  --> src/lib.rs:16:5
   |
5  | struct T();
   | ----------- `T` defined here
...
15 | fn baz() -> T {
   |             - expected `T` because of return type
16 |     T
   |     ^ expected struct `T`, found fn item
   |
   = note:        expected value of type `T`
         found tuple struct constructor of type `T`
help: use parentheses to instantiate this tuple struct
   |
16 |     T()
   |      ^^
ThePuzzlemaker commented 3 years ago

I'm gonna try to take a shot at this. @rustbot claim

ben0x539 commented 3 years ago

Can I throw in this one?

mod inner {
    pub struct BadStruct {
        _field: (),
    }
}

fn main() {
    let _ = inner::BadStruct();
}

suggests the following, which won't work because the field is private:

help: use struct literal syntax instead: `inner::BadStruct { _field: val }`
estebank commented 3 years ago

@ben0x539 I would say that that is better covered by https://github.com/rust-lang/rust/issues/57951

ben0x539 commented 3 years ago

mhm, stayed away from there because it talks about tuple structs and crates, but it's probably really the same thing :+1:

ThePuzzlemaker commented 3 years ago

Sorry for the inactivity. I'm going to let someone else work on this for now, I think. @rustbot release-assignment

Dylan-DPC commented 1 month ago

Current output:

error[E0423]: expected value, found struct `S`
 --> src/lib.rs:8:5
  |
1 | struct S {}
  | ----------- `S` defined here
...
5 | struct T();
  | ----------- similarly named tuple struct `T` defined here
...
8 |     S
  |     ^
  |
help: use struct literal syntax instead
  |
8 |     S {}
  |
help: a tuple struct with a similar name exists
  |
8 |     T
  |
help: consider importing this unit variant instead
  |
1 + use unicode_bidi::BidiClass::S;
  |

error[E0423]: expected value, found enum `E`
  --> src/lib.rs:12:5
   |
5  | struct T();
   | ----------- similarly named tuple struct `T` defined here
...
12 |     E
   |     ^
   |
note: the enum is defined here
  --> src/lib.rs:2:1
   |
2  | / enum E {
3  | |     V,
4  | | }
   | |_^
help: you might have meant to use the following enum variant
   |
12 |     E::V
   |
help: a tuple struct with a similar name exists
   |
12 |     T
   |
help: consider importing one of these constants instead
   |
1  + use std::f128::consts::E;
   |
1  + use std::f16::consts::E;
   |
1  + use std::f32::consts::E;
   |
1  + use std::f64::consts::E;
   |

error[E0308]: mismatched types
  --> src/lib.rs:16:5
   |
5  | struct T();
   | -------- `T` defines a struct constructor here, which should be called
...
15 | fn baz() -> T {
   |             - expected `T` because of return type
16 |     T
   |     ^ expected `T`, found struct constructor
   |
   = note:          expected struct `T`
           found struct constructor `fn() -> T {T}`
help: use parentheses to construct this tuple struct
   |
16 |     T()
   |      ++

Some errors have detailed explanations: E0308, E0423.
For more information about an error, try `rustc --explain E0308`.
error: could not compile `playground` (lib) due to 3 previous errors