2

I am trying to create a struct in Rust that is itself generic with respect to other generic structs. That's pretty confusing so hopefully this example will makes things clearer:

use std::ops::Deref;
use std::rc::Rc;

struct Foo<T: Deref> {
    val: T<i32>,
    other: i32,
}

impl<T> Foo<T> {
    pub fn new(&self, val: T<i32>, other: i32) -> Self {
        Foo {val: val, other: other}
    }
}

fn main() {
    let foo = Foo::new(Rc::new(0), 0);
}

playground

I would like to be able to create a Foo object by calling new with either Rc<i32> objects or Arc<i32> objects depending on whether I need thread safety or not. I get the following error when I try this though: error[E0109]: type parameters are not allowed on this type, as the compiler complains about the i32 in val: T<i32>,. Is this possible in Rust? If so, can I safely call methods on i32 assuming it will auto dereference it?

1
  • 1
    Unlike some other languages, unfortunately Rust doesn't (yet) have higher kinded types, so type parameters have to be concrete types. However in this case I agree with @Shepmaster that you don't need it. Commented Nov 1, 2016 at 22:23

1 Answer 1

3

That syntax doesn't make sense, but this version compiles:

use std::ops::Deref;
use std::rc::Rc;
use std::sync::Arc;

struct Foo<T> {
    val: T,
    other: i32,
}

impl<T> Foo<T>
    where T: Deref<Target = i32>
{
    pub fn new(val: T, other: i32) -> Self {
        Foo {
            val: val,
            other: other,
        }
    }
}

fn main() {
    let foo = Foo::new(Rc::new(0), 0);
    let foo = Foo::new(Arc::new(0), 0);
}

Note how the trait bounds read: T: Deref<Target = i32> "Any T that implements Deref with a Target of an i32".

You can then implement methods that dereference val:

fn sum(&self) -> i32 {
    *self.val + self.other
}

In general, the concept of something like

struct Foo<T> {
    val: T<i32>,
}

Wouldn't prove useful. Just because something is parameterized over a i32 doesn't mean you can do anything with that i32. Likewise, a type could be parameterized with something besides an i32 (or not at all) and still give you access to an i32.

Sign up to request clarification or add additional context in comments.

1 Comment

Awesome, thanks for the help! Going to try this out now. I would think this would be a more common technique as a way to quickly get a generic struct that can be thread safe or not depending on your needs, do you see this a lot?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.