To-be-named-at-runtime is simply dynamic typing. It's polymorphism without static typing.
Generics based on type erasure, e.g. Java, wrap that with a type system hoping* to prove safety at compile time, yet compile to a single dynamicly typed implementation, that does not use this type info at runtime.
Generics based on code generation / specialization, e.g. C++, generate distinct run-time implementations with the type hard-coded. (Though you can plug in dynamic typing by making the hard-coded type a pointer.) In C++ this is more than optimization, it's semantics — you can specify distinct behavior for specific types.
JIT compilers can start from a single dynamic-dispatch implementation and generate specialized implemetations for some types, bridging the divide.
But in any case, the common meaning of "generics" is not merely polymorphism, it's polymorphism plus a type system where you _name_ the type you're gonna use.