Type mismatch with generic parameter returns less than helpful errors

b587f8d
Opened by Mahmoud Al-Qudsi at 2024-12-21 05:10:00

When a type does not match a generic parameter (I'm not sure if it's treated differently if it's because a generic constraint failed or because a previous usage dictated a particular variant of that generic), the resulting error message is not helpful because it seems to indicate that everything is OK.

As an example:

error[E0308]: mismatched types
  --> src/main.rs:80:23
   |
80 |             return Ok(response);
   |                       ^^^^^^^^ expected type parameter, found struct `std::io::Cursor`
   |
   = note: expected type `tiny_http::Response<R>`
              found type `tiny_http::Response<std::io::Cursor<std::vec::Vec<u8>>>`
   = help: here are some functions which might fulfill your needs:
           - .with_data(...)
           - .with_header(...)
           - .with_status_code(...)

the method in question was declared as

fn send_email<R>(req: &mut Request) -> Result<Response<R>, String>
    where R: std::io::Read

I believe the compiler message should at least indicate the constraints on R, because as it currently reads, tiny_http::Response<std::io::Cursor<std::vec::Vec<u8>>> is a valid form of tiny_http::Response<R> for R=std::io::Cursor<std::vec::Vec<u8>>

  1. Current output:

    error[E0308]: mismatched types
     --> file.rs:7:15
      |
    4 | fn send_email<R>(req: &mut Request) -> Result<Response<R>, String>
      |               - this type parameter
    ...
    7 |   Ok(Response(42))
      |               ^^ expected type parameter `R`, found integer
      |
      = note: expected type parameter `R`
                           found type `{integer}`
      = help: type parameters must be constrained to match other types
      = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
    

    Only thing missing would be to suggest using impl Trait instead. To do so we should verify that the type parameter is only used in the return type and that all of its bounds can be represented as impl Trait (no where R::Assoc: Blah shenanigans). It should look something along the lines of

    
    error[E0308]: mismatched types
     --> file.rs:7:15
      |
    4 | fn send_email<R>(req: &mut Request) -> Result<Response<R>, String>
      |               - this type parameter
    ...
    7 |   Ok(Response(42))
      |               ^^ expected type parameter `R`, found integer
      |
      = note: expected type parameter `R`
                           found type `{integer}`
      = help: type parameters must be constrained to match other types
      = note: for more information on traits as parameters, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
      = note: for more information on `impl Trait`, visit <URL>
    help: because type parameter `R` is only used in the return, you can instead use `impl Trait`:
      |
    4 | fn send_email(req: &mut Request) -> Result<Response<impl std::fmt::Display>, String>
      |             --                                      ^^^^^^^^^^^^^^^^^^^^^^
    

    When there's an error with the returned value not implementing Trait, the output is:

    error[E0277]: the trait bound `{integer}: std::io::Read` is not satisfied
     --> file.rs:4:53
      |
    4 | fn send_email(req: &mut Request) -> Result<Response<impl std::io::Read>, String> {
      |                                                     ^^^^^^^^^^^^^^^^^^ the trait `std::io::Read` is not implemented for `{integer}`
    5 |   Ok(Response(42))
      |   ---------------- this returned value is of type `std::result::Result<Response<{integer}>, std::string::String>`
      |
      = help: the following implementations were found:
                <&'a std::os::unix::net::UnixStream as std::io::Read>
                <&'a std::sys::unix::fd::FileDesc as std::io::Read>
                <&[u8] as std::io::Read>
                <&mut R as std::io::Read>
              and 19 others
      = note: the return type of a function must have a statically known size
    

    Esteban Kuber at 2020-01-22 19:02:13