Way to avoid listing all generic parameters?

pub fn do_thing<T, S: AsRef<str>>(s: S) {
}

fn main() {
    do_thing::<i32>("hello"); //< I'd like this to work but it doesn't, Rust tells me I have to specify both
                              //< type parameters because I've specified one of them.
}

Reduced example here, imagine the t: T parameter is used internally in the function. Key point is that I have to explicitly specify T as e.g. ::<i32> but I would like to avoid having to specify &str for S since the compiler knows what that type is.

One possible workaround is to have a dummy parameter of type T that is just used to get the compiler to fill out that type parameter, but I'd like to avoid that if possible.

You can have it inferred by writing:

do_thing::<i32, _>("hello");

But default type parameters are not a thing on functions at this time. There's some discussion in this tracking issue.

4 Likes

Ah of course, thanks. That's probably ok for me for now.

You can also use existential universal types to remove the S type parameter.

pub fn do_thing<T>(s: impl AsRef<str>) {
}

In this case, it'd be impossible to choose T explicitly at all, so it's probably not what OP would like.

2 Likes

Sorry for the late reply, but I just saw this. I was confused, but indeed:

error[E0632]: cannot provide explicit generic arguments when `impl Trait` is used in argument position
  --> src/lib.rs:13:16
   |
13 |     do_thing::<i32>("hello");
   |                ^^^ explicit generic argument not allowed

error: aborting due to previous error

I don't understand this, and it is very counterintuitive to me. But apparently it's not allowed, even when the types are totally unrelated. That's really frustrating and make universal types much less useful.

For anyone else who might be equally confused, see here.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.