Rust doesn't like this because datatype() is not a method on T. It's a method
on MySendable. There are various proposals that will fix this (including UFCS,
and a proposal to make T::datatype() work as you just tried).
But for the time being, you basically cannot have a trait method that does not
use Self anywhere in its type signature (which is to say, it doesn't take a
`self` parameter, and it does not use the Self pseudo-type).
A common workaround here is to add a parameter of type Option<Self>, so you can
pass None in order to provide the correct type info:
trait MySendable {
fn datatype(_: Option<Self>) -> *c_void;
}
impl MySendable for int {
fn datatype(_: Option<int>) -> *c_void { DT_INT32 }
}
fn process<T: MySendable>(data: &[T]) {
unsafe {
ffi_process(data.as_ptr(), data.len(), MySendable::datatype(None::<T>));
}
}
I do have to wonder, though, how you intend to map from the type pointer back
to the original type. Or do you not need to go in that direction? If you do, I
think you'll need to ditch the trait and instead just use an enum:
enum MySendable<'a> {
SendableInt(&'a [int]),
SendableFoo(&'a [Foo]),
...
}
impl<'a> MySendable<'a> {
fn datatype(&self) -> *c_void {
match *self {
SendableInt(_) => DT_INT32,
SendableFoo(_) => DT_FOO,
...
}
}
}
This approach lets you produce a reverse mapping as well.
However, if you don't need the reverse mapping, then the trait approach seems
like a reasonable way to handle things.
-Kevin
On May 17, 2014, at 7:58 AM, Noah Watkins <[email protected]> wrote:
> I'm running into a problem creating a generic wrapper around an FFI
> interface of the following form:
>
> fn ffi_process(data: *c_void, count: c_int, type: *c_void);
>
> where `data` points to an array of `count` elements of each of type
> `type`. Each `type` is represented by a constant opaque pointer to
> some fixed symbol exported by the C library and corresponding to a
> particular type (e.g. DT_INT32, DT_FLOAT32, etc...).
>
> My approach so far has been to use a trait to map Rust data types to
> data types in the library as follows:
>
> trait MySendable {
> fn datatype() -> *c_void;
> }
>
> impl MySendable for int {
> fn datatype() -> *c_void { DT_INT32 }
> }
>
> fn process<T: MySendable>(data: &[T]) {
> unsafe {
> ffi_process(data.as_ptr(), data.len(), T::datatype());
> }
> }
>
> But, Rust does not like this at all. I have seen many many references
> on github issues and SO about methods on the types, but it isn't clear
> what the current / future approach is / will be.
>
> Is this (1) a reasonable approach to the problem (even if not
> currently possible), and (2) are there other ways to bend the type
> system to my needs here?
>
> Thanks!
> Noah
> _______________________________________________
> Rust-dev mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/rust-dev
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev