`Vec<Vec<(String, usize)>>` panics with unsatisfied trait bounds
Vagab opened this issue · comments
Hi everyone. Probably a stupid question but I'm getting this error when trying to return Vec<Vec<(String, usize)>>
from a function and then define it as a singleton method:
error[E0599]: the method `call_handle_error` exists for fn item `fn(String, String) -> Vec<Vec<(String, usize)>> {reg}`, but its trait bounds were not satisfied
--> ext/xre2/src/lib.rs:98:43
|
98 | module.define_singleton_method("reg", function!(reg, 2))?;
| ^^^^^^^^^^^^^^^^^ method cannot be called due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`<fn(String, String) -> Vec<Vec<(String, usize)>> {reg} as FnOnce<(&Ruby, _, _)>>::Output = _`
which is required by `fn(String, String) -> Vec<Vec<(String, usize)>> {reg}: RubyFunction2<_, _, _>`
`fn(String, String) -> Vec<Vec<(String, usize)>> {reg}: Fn<(&Ruby, _, _)>`
which is required by `fn(String, String) -> Vec<Vec<(String, usize)>> {reg}: RubyFunction2<_, _, _>`
`<&fn(String, String) -> Vec<Vec<(String, usize)>> {reg} as FnOnce<(&Ruby, _, _)>>::Output = _`
which is required by `&fn(String, String) -> Vec<Vec<(String, usize)>> {reg}: RubyFunction2<_, _, _>`
`&fn(String, String) -> Vec<Vec<(String, usize)>> {reg}: Fn<(&Ruby, _, _)>`
which is required by `&fn(String, String) -> Vec<Vec<(String, usize)>> {reg}: RubyFunction2<_, _, _>`
`&mut fn(String, String) -> Vec<Vec<(String, usize)>> {reg}: Fn<(_, _)>`
which is required by `&mut fn(String, String) -> Vec<Vec<(String, usize)>> {reg}: Function2<_, _, _>`
`<&mut fn(String, String) -> Vec<Vec<(String, usize)>> {reg} as FnOnce<(&Ruby, _, _)>>::Output = _`
which is required by `&mut fn(String, String) -> Vec<Vec<(String, usize)>> {reg}: RubyFunction2<_, _, _>`
`&mut fn(String, String) -> Vec<Vec<(String, usize)>> {reg}: Fn<(&Ruby, _, _)>`
which is required by `&mut fn(String, String) -> Vec<Vec<(String, usize)>> {reg}: RubyFunction2<_, _, _>`
= note: this error originates in the macro `function` (in Nightly builds, run with -Z macro-backtrace for more info)
which in my very limited experience meant that there's no way to implicitly transform this rust type into ruby type(might be wrong, please correct me). So I was wondering why does Vec<(String, usize)>
is ok but this one is not?
This is a bug in Magnus, looks like I forgot to implement IntoValueFromNative
for Vec
.
IntoValue
is the trait that handles turning Rust types into Ruby types. Ruby types also implement it, just by returning themselves. Vec
implements it like:
impl<T> IntoValue for Vec<T>
where
T: IntoValueFromNative,
{
...
}
IntoValueFromNative
is a special version of IntoValue
that isn't implemented for Ruby types. This is done so you can't return an Vec
containing Ruby types, because you shouldn't ever put Ruby types in a Vec
, because the GC will lose track of them.
Vec
shouldn't blanket implement IntoValueFromNative
(because it could contain Ruby types), but it should impl<T> IntoValueFromNative for Vec<T> where T: IntoValueFromNative
. I missed adding this impl.
I don't have time to do it right now, but I'll try and get a patch release out this evening with a fix.
I see, makes sense. Thank you for the explanation and for such a swift response. I have some time right now so I will try to do it myself, if I do I'll ping you on a pr. Otherwise feel free to fix 👍
upd: here's the pr, let me know if I should add any tests for this or anything, but I built it on my machine and tried it out with my use case and all was fine(with more nested vecs too, makes sense 😅)
I've put out a 0.6.3 release with this fix.