Skip to content

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

Open
@lopopolo

Description

@lopopolo

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions