I would generally agree that polymorphism is necessary, except maybe for embedded systems. You want more of a closed world system there, not an open world system that permits arbitrary extensions.
By open world, I'm thinking of abstractions like closures and interfaces which permit arbitrary extension and require dynamic dispatch. Given any fixed set of such abstractions, you can simulate in a closed world system via something like defunctionalization during whole program compilation, which is what you do on embedded systems. You can probably do a defunctionalization transformation with comptime, and that gets you better visibility on the state of the system in a way that's not possible with a truly open world system.
By open world, I'm thinking of abstractions like closures and interfaces which permit arbitrary extension and require dynamic dispatch. Given any fixed set of such abstractions, you can simulate in a closed world system via something like defunctionalization during whole program compilation, which is what you do on embedded systems. You can probably do a defunctionalization transformation with comptime, and that gets you better visibility on the state of the system in a way that's not possible with a truly open world system.