Skip to content

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

Open
@lopopolo

Description

@lopopolo
Contributor

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.

Activity

added
A-diagnosticsArea: Messages for errors, warnings, and lints
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Mar 11, 2022
lopopolo

lopopolo commented on Mar 11, 2022

@lopopolo
ContributorAuthor

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

compiler-errors

compiler-errors commented on Jun 19, 2022

@compiler-errors
Member

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

WaffleLapkin

WaffleLapkin commented on Oct 12, 2022

@WaffleLapkin
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

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

        Participants

        @lopopolo@compiler-errors@WaffleLapkin

        Issue actions

          Calling trait function declared with both explicit generics and impl Trait gives confusing errors · Issue #94836 · rust-lang/rust