Misleading diagnostics for method call

4ca3ffd
Opened by Patrick Reisert at 2020-04-08 01:08:36

The following (reduced example) code leads to a misleading error message:

trait IsARectangle<T> {}

struct GeneralRectangle<T>
{
    x: T
}

impl<T> IsARectangle<T> for GeneralRectangle<T> {}

impl<U> GeneralRectangle<U> where U: std::ops::Add<Output = U>
{
    fn from<T, R>(_: &R) -> Result<GeneralRectangle<U>, ()>
    where
        R: IsARectangle<T>,
    {
        unimplemented!()
    }
}

fn box_to_pixel<T, S>( (_, _): (S, S)) -> Result<GeneralRectangle<T>, ()>
// if you enable the following line, it will work:
//where T: std::ops::Add<Output = T>
    {
        GeneralRectangle::<T>::from::<u32, GeneralRectangle<u32>>(&GeneralRectangle::<u32> {
            x: 0,
        })
    }


fn main() {
   box_to_pixel::<u32, u32>( (0, 0) );
}

The problem is that the where-clause for box_to_pixel is missing (it works if it is added), but the compiler instead reports:

error[E0087]: too many type parameters provided: expected at most 0 type parameters, found 2 type parameters
  --> src\main.rs:22:39
   |
22 |         GeneralRectangle::<T>::from::<u32, GeneralRectangle<u32>>(&GeneralRectangle::<u32> {
   |                                       ^^^ expected 0 type parameters

error[E0277]: the trait bound `std::result::Result<GeneralRectangle<T>, ()>: std::convert::From<&GeneralRectangle<u32>>` is not satisfied
  --> src\main.rs:22:9
   |
22 |         GeneralRectangle::<T>::from::<u32, GeneralRectangle<u32>>(&GeneralRectangle::<u32> {
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<&GeneralRectangle<u32>>` is not implemented for `std::result::Result<GeneralRectangle<T>, ()>`
   |
   = note: required by `std::convert::From::from`

As a Rust beginner, who might have not yet heard about std::convert::From::from, I would now be really confused, because the from method exists (in my code!), and it does expect 2 type parameters, not 0.

The error message is better if the where U: std::ops::Add<Output = U> is moved from the impl block to the fn from, so I do understand what the compiler does here (it probably totally disregards the whole impl block because its where clause is not satisfied), but maybe the situation can be improved anyway?

  1. Current output:

    error[E0107]: wrong number of type arguments: expected 0, found 2
      --> src/main.rs:24:39
       |
    24 |         GeneralRectangle::<T>::from::<u32, GeneralRectangle<u32>>(&GeneralRectangle::<u32> {
       |                                       ^^^  ^^^^^^^^^^^^^^^^^^^^^ unexpected type argument
       |                                       |
       |                                       unexpected type argument
    
    error[E0308]: mismatched types
      --> src/main.rs:24:67
       |
    24 |           GeneralRectangle::<T>::from::<u32, GeneralRectangle<u32>>(&GeneralRectangle::<u32> {
       |  ___________________________________________________________________^
    25 | |             x: 0,
    26 | |         })
       | |_________^ expected struct `GeneralRectangle`, found reference
       |
       = note: expected struct `GeneralRectangle<T>`
               found reference `&GeneralRectangle<u32>`
    
    error[E0308]: mismatched types
      --> src/main.rs:24:9
       |
    20 |   fn box_to_pixel<T, S>( (_, _): (S, S)) -> Result<GeneralRectangle<T>, ()>
       |                                             ------------------------------- expected `std::result::Result<GeneralRectangle<T>, ()>` because of return type
    ...
    24 | /         GeneralRectangle::<T>::from::<u32, GeneralRectangle<u32>>(&GeneralRectangle::<u32> {
    25 | |             x: 0,
    26 | |         })
       | |__________^ expected enum `std::result::Result`, found struct `GeneralRectangle`
       |
       = note: expected enum `std::result::Result<GeneralRectangle<_>, ()>`
                found struct `GeneralRectangle<_>`
    help: try using a variant of the expected enum
       |
    24 |         Ok(GeneralRectangle::<T>::from::<u32, GeneralRectangle<u32>>(&GeneralRectangle::<u32> {
    25 |             x: 0,
    26 |         }))
    

    Esteban Kuber at 2020-04-08 01:08:36