The short answer is that i32 implements the Copy attribute, but T does not. If you use fn generic_main<T: Copy>(t: Test<T>) , your immediate problem will be fixed.
The longer answer is that Copy is a special feature, which means that values can be copied by simply copying bits. Types like i32 implement Copy . Types such as String do not implement Copy because, for example, this requires heap allocation. If you copied String only by copying the bits, you will get two String values pointing to the same piece of memory. That would be bad (it’s not safe!).
Therefore, providing your T a Copy binding is pretty restrictive. A less restrictive assessment would be T: Clone . The Clone character is similar to Copy (in that it copies the values), but usually this is not done simply by “copying bits”. For example, the String type implements Clone , creating a new heap allocation for base memory.
This requires you to change your generic_main text:
fn generic_main<T: Clone>(t: Test<T>) { let x = t.get_first(); t.do_something_with_x(x.clone()); }
Alternatively, if you do not want to have Clone or Copy borders, you can change your do_something_with_x method to get a reference to T , not to the one belonging to T :
impl<T> Test<T> { // other methods elided fn do_something_with_x(&self, x: &T) { // Irrelevant } }
And your generic_main remains basically the same, except that you are not looking for x :
fn generic_main<T>(t: Test<T>) { let x = t.get_first(); t.do_something_with_x(x); }
Read more about Copy in the documentation . There are some good examples, including how to implement Copy for your own types.