Constructor over generic struct


#1

Although i’m sure someone else has probably asked this question, i cannot seem to
grasp how to “think” about generics when dealing with functions that return types that may contain generics.

https://is.gd/4pqv2N

struct LinkedList<T> {
    next: T
}

fn new<T>() -> LinkedList<T> {
    LinkedList { 
        next: 42
    }
}

fn main() {   
    let mut ls = new();
    let mut lx = LinkedList { next: 12312 };
}

As i understood generics, if i assign a value to the next field that should hold a T value(inside fn new when assigning 42 to the next field), it should work because T means/can hold any type(disregard traits). After discussing with some devs, they told me that the compiler cannot infer the type T declared in the impl(impl<T> LinkedList<T>....).
If that is the case, why does this work let x = LinkedList { next: 12312 } and why doesn’t the compiler throw a mismatch error? Why is the compiler complaining about 42 when i said that T is generic and can hold any value?

ps - I’m positive i haven’t really grasp generics and i kinda feel stupid about it

Thanks in advance,
Dragos


#2

The problem is that your new function declares itself as generic (over T) but returns a LinkedList with a specific type (an integer). You contract is, though, that new<T> would return LinkedLists containing any type the user could ask for. This implementation would work:

struct LinkedList<T> {
    next: T
}

fn new<T>(start: T) -> LinkedList<T> {
    LinkedList { 
        next: start
    }
}

#3

Thanks for the reply, skade!

Yes, i know that explicitly passing the param to new, will make it work because x(in your ex) is of type T.
But why does let x = LinkedList { next: 42 } work, because 42 is not T?

I’m sure it’s probably stupid to think about generics in this way, but i cannot figure out a better approach.

LE: i think i understand(at least a part of it).
The compiler must know that anything T can “do”, 42 also can, so that’s why it complains


#4

The compiler infers that x is really let x: LinkedList<i32> = ..., and so you’re creating a LinkedList with a concrete type here.