Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling trait function declared with both explicit generics and impl Trait gives confusing errors #94836

Open
lopopolo opened this issue Mar 11, 2022 · 3 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@lopopolo
Copy link
Contributor

lopopolo commented Mar 11, 2022

Given the following code:

I had a trait that was originally defined like this:

pub trait LoadSources {
    fn def_file_for_type<P, T>(&mut self, path: P) -> Result<(), Box<dyn Error>>
    where
        P: AsRef<Path>,
        T: File;
}

T is a type parameter that is used to pass a function pointer into implementations of this trait.

Users of this API call it like this:

interp.def_file_for_type::<_, SecureRandomFile>("securerandom.rb")?;

I was trying to remove the P type parameter to allow for a bit nicer of a turbofish without the anonymous placeholder so I redefined the trait to look like:

pub trait LoadSources {
    fn def_file_for_type<T>(&mut self, path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>
    where
        T: File;
}

I attempted to compile this before refactoring callers.

Full program below.
Playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=49b4d1c31975f80c7cc2f3c1f8a06933

use std::error::Error;
use std::path::Path;

pub trait File {}

pub trait LoadSources {
    fn def_file_for_type<T>(&mut self, path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>
    where
        T: File;
}

struct Interp {}

impl LoadSources for Interp {
    fn def_file_for_type<T>(&mut self, path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>
    where
        T: File
    {
        todo!()
    }
}

pub struct SecureRandomFile {}

impl File for SecureRandomFile {}

pub fn main() {
    let mut interp = Interp {};
    interp.def_file_for_type::<_, SecureRandomFile>("securerandom.rb").unwrap();
}

The current output is:

   Compiling playground v0.0.1 (/playground)
error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
  --> src/main.rs:29:32
   |
29 |     interp.def_file_for_type::<_, SecureRandomFile>("securerandom.rb").unwrap();
   |                                ^  ^^^^^^^^^^^^^^^^ explicit generic argument not allowed
   |                                |
   |                                explicit generic argument not allowed
   |
   = note: see issue #83701 </~https://github.com/rust-lang/rust/issues/83701> for more information

error[E0308]: mismatched types
  --> src/main.rs:29:53
   |
29 |     interp.def_file_for_type::<_, SecureRandomFile>("securerandom.rb").unwrap();
   |                                                     ^^^^^^^^^^^^^^^^^ expected struct `SecureRandomFile`, found `&str`

error[E0277]: the trait bound `SecureRandomFile: AsRef<Path>` is not satisfied
  --> src/main.rs:29:53
   |
29 |     interp.def_file_for_type::<_, SecureRandomFile>("securerandom.rb").unwrap();
   |            -----------------                        ^^^^^^^^^^^^^^^^^ the trait `AsRef<Path>` is not implemented for `SecureRandomFile`
   |            |
   |            required by a bound introduced by this call
   |
note: required by a bound in `LoadSources::def_file_for_type`
  --> src/main.rs:7:51
   |
7  |     fn def_file_for_type<T>(&mut self, path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>
   |                                                   ^^^^^^^^^^^ required by this bound in `LoadSources::def_file_for_type`

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

Ideally the output should look like:

There are two errors here:

  • Can't use explicit type argument when impl trait is used. This one is present but comes first and cargo ouput puts it out of the scrollback in my terminal.
  • I'm using two named generic types when the function only has 1. This does not appear in the error output. Instead I get a lot of confusing things around type mismatches. I can't figure out what rustc is trying to tell me.
@lopopolo lopopolo added A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 11, 2022
@lopopolo
Copy link
Contributor Author

Linking #83701 since this ticket appears in the diagnostic output.

@compiler-errors
Copy link
Member

I think this might need revisiting since #96868 is stabilized on master.

@WaffleLapkin
Copy link
Member

The current error looks like this:

error[[E0107]](https://doc.rust-lang.org/stable/error-index.html#E0107): this associated function takes 1 generic argument but 2 generic arguments were supplied
  --> src/main.rs:29:12
   |
29 |     interp.def_file_for_type::<_, SecureRandomFile>("securerandom.rb").unwrap();
   |            ^^^^^^^^^^^^^^^^^      ---------------- help: remove this generic argument
   |            |
   |            expected 1 generic argument
   |
note: associated function defined here, with 1 generic parameter: `T`
  --> src/main.rs:7:8
   |
7  |     fn def_file_for_type<T>(&mut self, path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>
   |        ^^^^^^^^^^^^^^^^^ -
   = note: `impl Trait` cannot be explicitly specified as a generic argument

error[[E0277]](https://doc.rust-lang.org/stable/error-index.html#E0277): the trait bound `SecureRandomFile: AsRef<Path>` is not satisfied
  --> src/main.rs:29:53
   |
29 |     interp.def_file_for_type::<_, SecureRandomFile>("securerandom.rb").unwrap();
   |            -----------------                        ^^^^^^^^^^^^^^^^^ the trait `AsRef<Path>` is not implemented for `SecureRandomFile`
   |            |
   |            required by a bound introduced by this call
   |
note: required by a bound in `LoadSources::def_file_for_type`
  --> src/main.rs:7:51
   |
7  |     fn def_file_for_type<T>(&mut self, path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>
   |                                                   ^^^^^^^^^^^ required by this bound in `LoadSources::def_file_for_type`

error[[E0308]](https://doc.rust-lang.org/stable/error-index.html#E0308): mismatched types
  --> src/main.rs:29:53
   |
29 |     interp.def_file_for_type::<_, SecureRandomFile>("securerandom.rb").unwrap();
   |            ---------------------------------------- ^^^^^^^^^^^^^^^^^ expected struct `SecureRandomFile`, found `&str`
   |            |
   |            arguments to this function are incorrect
   |
note: associated function defined here
  --> src/main.rs:7:8
   |
7  |     fn def_file_for_type<T>(&mut self, path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>
   |        ^^^^^^^^^^^^^^^^^

Maybe we shouldn't set the APIT type at all, so that we don't show the latter two errors? (they are somewhat confusing IMO)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants