How to have a list of a type which needs generic traits in one of its properties?

Here is a brief overview of what I want to achieve:

I have a struct called Constraint defined the following way:

pub struct Constraint<JointType: Joint> {
    ...
    joint: JointType,
    ...
}

and I have many struct defined which implements the Joint trait.

pub struct RevoluteJoint {}
pub struct SphericalJoint {}
....

But I want to store a list of Constraint instances.
I tried Vec<Constraint<JointType>> but that won't work because the compiler wants a list of only a specific joint type. I want a list which can hold the Constraint made with any type of JointType. How can I create a list of Constraint which can hold any JointType?

It seems to me that the easiest way is to just remove the Constraint struct and put everything in Constraint struct into all the Joint trait implementation and create a list with the following:

Vec<Box<dyn Joint>>

The above is possible but the reason I created Constraint because there are a lot of data which is same for each JointType and implementing them in each struct will make the code very verbose and error prone if I want to create a new JointType later on and forget a specifc data piece...

Then make it an enum rather than a trait.

I am writing a library and my thought process was that user should be able to make there own JointType by just implementing the Joint trait. Of course enum and the workaround I mention would also technically "work" for my usecase. I am not making a grand library to be used by millions or anything just looking for a way to not have to give up flexibililty for this.

Gotcha. The problem is that traits in Rust are only for behaviour, they don't enforce implementors to have certain data like in some OOP languages.

Yes. Well I am going with enums. It should be fine. It removes some amount of flexibility but for the program I am writing there is only so much JointTypes physically possible. So enum should do be good enough.

If your Constraint implementation doesn’t have generic-specific implementations, you can also put a Box<dyn Joint> in it. Although you may have already considered this, since you mentioned a somewhat similar alternative.

pub struct Constraint {
    // …
    joint: Box<dyn Joint>,
    // …
}

impl Joint for RevoluteJoint { /* … */ }

fn main() {
    let mut v = Vec::<Constraint>::new();
    v.push(Constraint { 
        joint: Box::new(RevoluteJoint { /* … */ }),
        /* … */ 
    });
    // …
}

another alternative, if you are ok with Box, you can use Vec<Box<Constraint<dyn Joint>>>, but you need to move the joint field to the last position in the Constrait struct, and don't forget the ?Sized bound.

pub struct Constraint<JointType: Joint + ?Sized> {
    //...
    joint: JointType, // `?Sized` type can only be used for last field of the struct
}

fn main() {
    let mut v: Vec<Box<Constraint<dyn Joint>>> = vec![];
    v.push(Box::new(Constraint::new(RevoluteJoint::new())));
    v.push(Box::new(Constraint::new(SphericalJoint::new())));
}

I, in fact, haven't considered this. Yes. It would definitely work. I can't think of any reason to have generic-specific implementation in Constraint for any use case.

Thanks a lot

Interesting, I will note it down for later projects but @Redglyph answer feels more simple and will be more than enough for my uses.