Sorry, but I have a hard time believing the common trope that something silly like more language complexity will significantly help keeping the complexity of the code down. Personally, I believe it is often the opposite.
So you can't abstract over data types in C? I often do. Some random thing I often do:
void linear_allocate(Linear_Allocator *alloc, size_t size, size_t align, size_t count);
#define linear_allocate_type(alloc, type, count) ((type *) (linear_allocate((alloc), sizeof (type), alignof (type), (count))))
(Anybody objecting they don't like macros and this is not a real abstraction: You are all fools. To a certain point, that is - before you possibly start being right. But don't underestimate how far this can go, and how long this can be a superior solution over alternatives.)
You know something that is very hard to abstract over? Programming language FEATURES! Anybody, please show me the ways of doing computation over all the data that was encoded as fancy programming language syntax. This requires even more language features to get this data back from the compiler in some weird form... if possible at all.