Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Get Started with Rust: Generics (serokell.io)
60 points by amalinovic on Jan 4, 2023 | hide | past | favorite | 10 comments



Overall a decent article but:

> T represents any data type, which means there is no way to know what T is at runtime – we can’t pattern match on it, can’t do any type-specific operations, and can’t have different code paths for different T’s.

That's not quite right - it's that we can't know what T is until compile time. The authors of the generic don't know what type it is, and but the compiler does when it's used somewhere. Runtime unknowns are handled with `dyn` pointers, and even then they are trait bound.

I found the quoted part a bit jarring particularly after a bunch of compiler errors about types were shown... not sure if OP is the author, but that sentence could use a bit of cleanup.


I think what author is saying is that Rust won't let you have any type-specific behaviors in generic code, on principle. Generic Rust code is meant to rely only on the trait bounds, and nothing else. The compiler will eventually know concrete types, but it won't let you depend on that.

This is in contrast with Rust macros and C++ templates where the template code can perform operations that work only on some concrete types and not others, without declaring that upfront with trait bounds.

In other words, Rust's generic code is type-checked at the definition time (while the type T is still a truly abstract concept), rather than type-checked at use/instantiation/monomorphisation time when the type T can be substituted for something specific.


> Rust won't let you have any type-specific behaviors in generic code, on principle

Not on principle, but an incomplete/unstable feature called specialization: https://github.com/rust-lang/rust/issues/31844


It helps with the overall goal of optimizing code for types, but I wouldn't say it changes the principles. The principle remains that generics are type-checked at definition time, and Rust tries to avoid having monomorphisation-time type errors.

• When you have `impl<T> Trait<T> for MyType` you still can't make any type-specific assumptions about T in this impl, even with specialization.

• When you have `impl Trait<i32> for MyType` then you can rely on the specific type, even without specialization.

So rules for individual implementations remain unchanged, specialization merely allows both implementations to coexist.


I think we agree that Rust allows generic code to be constrained, which means it can be eagerly type checked at the definition site. Contrast to C++ templates which are unconstrained meaning the compiler can't type check until they're expanded (barring the use of concepts).

What I was trying to say is that whether or not concrete type of a generic argument can be used as a constraint is orthogonal to those semantics, it's an implementation detail.


> specialization merely allows both implementations to coexist.

And both implementations coexisting allow for type-specific behavior in generic code


I'm not very familiar with Rust at all.

How does this work? Monomorphization? Does the rust compiler do wvole-program analysis to create each possible an instantiation following the types that implement a given trait?


The compiler does analyse the entire codebase and creates a a copy of the function for every type you use the generic with. This is why Rust compiles libraries with your binary rather than using precompiled ones like you would in C.


Generics are one of the most normal features of Rust. Right after while loop.


The author has a nice blog post series about companies using Haskell in production: https://serokell.io/blog/haskell-in-production




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: