The strongest typed ORM I've ever used is
http://diesel.rs/This code (okay I made the use line up because it's not on the website and I'm lazy, you do need one though):
use some::stuff::for::the::dsl;
let versions = Version::belonging_to(krate)
.select(id)
.order(num.desc())
.limit(5);
let downloads = version_downloads
.filter(date.gt(now - 90.days()))
.filter(version_id.eq(any(versions)))
.order(date)
.load::(&conn)?;
is completely, statically typed, with zero runtime overhead. Generics + type inference makes sure that everything is valid, and if you screw it up, you get a compiler error (which honestly are not very nice at the moment).
Thanks to generics, all of this checking is computed at compile time. The end resulting code is the equivalent of
let results = handle.query("SELECT version_downloads.*
WHERE date > (NOW() - '90 days')
AND version_id = ANY(
SELECT id FROM versions
WHERE crate_id = 1
ORDER BY num DESC
LIMIT 5
)
ORDER BY date");
but you get a ton of checking at compile time. It can even, on the far end of things, connect to your database and ensure things like "the version_downloads table exists, the versions table exists, it has a crate_id column, it has a num column", etc.
You can absolutely create an ORM _without_ generics, but it cannot give you the same level of guarantees at compile time, with no overhead.