"cannot infer type for type parameter" on self

Consider the following (very cut down) code. It will not compile, on the self.is_x() call with "cannot infer type for type parameter S declared on the trait Refiner". I'm not completely sure what the problem is, and I'm also not sure how to fix it -- how can I "type annotate" self?

pub trait Refiner<S> {
    fn name(&self) -> usize;
    fn is_x(&self) -> bool;
}

pub struct Q { }

impl<T> Refiner<T> for Q {
    fn name(&self) -> usize {
        if self.is_x() { 2 } else { 3 }
    }

    fn is_x(&self) -> bool {
        true
    }
}

You can use universal function call syntax:

    fn name(&self) -> usize {
        if <Self as Refiner<()>>::is_x(self) { 2 } else { 3 }
    }

The problem is that

  • the compiler sees that Q: Refiner<T> for every T, because of your blanket impl
  • whenever you try to call a Refiner method like is_x on a value foo of type Q, the compiler sees <Q as Refiner<???>>::is_x(&foo) and has no idea what type to put in the blank, because of the previous point
  • in fact any type would give the same result, again because of the blanket impl, but the compiler is not aware of that

So you must specify the generic parameter explicitly.

ETA: I just discovered on the playground that you can actually omit the Self type: <_ as Refiner<()>>::is_x(self). Cool!

4 Likes

They'd probably want something like this, so that T is used:

fn name(&self) -> usize {
    if <Self as Refiner<T>>::is_x(self) { 2 } else { 3 }
}
3 Likes

Yeah, I just used () because the blanket impl makes it clear that the actual type doesn't matter (and the compiler didn't complain about T being unused), but in general re-using T here is the better practice.

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.