How to use a closure in generic context?


#1

I’m having some trouble trying to get a closure to match a generic parameter, and can’t figure out what I’m doing wrong… Any ideas?

https://play.rust-lang.org/?gist=44590556e6dfec3ec3860804f5b7a708&version=stable&backtrace=0

error[E0308]: mismatched types
  --> <anon>:25:28
   |
25 | 		QueryWriter::new(writer, |_| true)
   | 		                         ^^^^^^^^ expected type parameter, found closure
   |
   = note: expected type `F`
              found type `[closure@<anon>:25:28: 25:36]`

#2

This implementation means "for any F implementing Fn(Message) -> bool, implement From<W> for QueryWriter<W>, but you’re trying to use a specific F.


#3

To clarify, you are saying that your function returns any Fn(Message) -> bool, where the exact type is decided by user of a function, which is obviously not true - your function only returns a single possible function |_| true.

Instead, don’t use generic type parameters. Function pointer will do, although it will prevent you from using closures (as each closure is its own unnameable type).

impl<W> From<W> for QueryWriter<W, fn(Message) -> bool>
    where W: Trace
{
    fn from(writer: W) -> Self {
        fn always_true(_: Message) -> bool {
            true
        }
        QueryWriter::new(writer, always_true)
    }
}

This however does have a cost of storing function pointer, so it’s clearly a workaround.


#4

Ah, right, that makes sense. Is a bit of a frustrating error message, though. Thanks for your help.


#5

Perhaps @skyschermer can define QueryWriter as a trait and then have two separate impls, one where caller supplies the predicate and the other where no predicate is stored.


#6

I’m not sure how that would work with From. It’s probably not viable for the purpose of this thing anyway, which is to be a stateful wrapper around a Write implementor, so I’m perfectly happy storing the function pointer in the object.


#7

You’d use a different From. Here’s a sketch: https://is.gd/cCuqhe