How to know the type required by generic fn

There is a trait in library that I'm trying to use:

pub trait ViewWrapper: 'static {
    /// Type that this view wraps.
    type V: View + ?Sized;

    /// Runs a function on the inner view, returning the result.
    ///
    /// Returns `None` if the inner view is unavailable.  This should only
    /// happen with some views if they are already borrowed by another call.
    fn with_view<F, R>(&self, f: F) -> Option<R>
    where
        F: FnOnce(&Self::V) -> R;//HOW AM I SUPPOSED TO KNOW WHAT TYPE IS THIS???

When I try to implement this method I'm getting:

fn with_view<F, R>(&self, f: F) -> Option<R>
   |                     - this type parameter
...
85 |         Some(&self.m_view)
   |              ^^^^^^^^^^^^^^^^ expected type parameter `R`, found reference

I really think that the compiler's help is unhelpful here. How am I supposed to know what should be the type of the R????

It's, really, the best compiler can do.

You are not supposed to know that. You are supposed to write code which works for any type R. Absolutely any with no limitations.

This is common mistake newcomers from C++ are doing (and the reason original 10 years+ concepts weren't accepted). In C++ you can write function which accepts not all types, but some of them.

Like this:

template<typename T>
T my_add(T a, T b) {
  return a + b;
}

And then, later, you may use it with any type that implements appropriate "operator+". Integers, strings, etc.

In Rust similar attempt would be a compile time error:

fn my_add<T>(a: T, b: T) -> T {
    a + b
}

You have to explain to the compiler what requirements you want from T:

fn my_add<T>(a: T, b: T) -> T where T: core::ops::Add<Output = T> {
    a + b
}

Similarly in your case: you promised to implement with_view for any type R. Any whatsoever, no limitations. Your user would pick the type, not you. The only limitation which is written there: f closure returns value of that type.

And I suspect your m_view is not of the appropriate type which makes compiler angry.

It's hard for me to say what you need to write because you cut so much from your example, but it must support arbitrary types R, not just the ones you like.

You don't know what the concrete type will be -- it's generic. So long as the bounds are met, the caller of the method chooses, not the writer of the method. All you know is that the bounds of the method have been met.

In this case, that means that R is the return type of the closure they passed in. You can return None or you can call f with a &Self::V and return the result in a Some. You don't know enough to get an R any other way.

1 Like