I think this is the right way to start thinking about solutions, but premature.
I know that this:
Was meant to be illustrative, not definitive, but it illustrates a structural shortcoming with the approach: networking should not be available if cryptography isn’t.
A flat table-of-optionals cannot express that kind of dependency. It’s possible (trivially: tooling can generate it) to partition the Io.VTable graph into a mostly-acyclic dependency tree: but there isn’t really a Zig data structure which can express that in a useful way.
Maybe there is an adequate division of the table which works? That would be luck, it’s not inherent to the problem domain. Also, in using something like this we’re really crossing our fingers on the devirtualization question.
One saving grace: since Io itself is a concrete type, the added awkwardness of using a collection of optional dispatch tables only has to be handled in one place. But this is going to leak into user code, by the same token: the author(s) must decide what happens when a function is called and the dependency isn’t there. The policies are: unreachable, “and then, nothing happens”, and error.IoLacksNetworkVTable. Only the last one seems responsible, but it puts a spurious error into play, since user code is generally going to either work if networking is present, or not work at all, and in neither case is handling a runtime error interesting.
It does basically solve the bloat problem though. It would make the dispatch table itself larger, but the table itself is not that big, it’s the compiled functions which are at issue, and those would never be seen if null were provided.
Full marks for being proactive! I’m choosing not to be because I view it as premature. Also because it would be long. Also for personal reasons grounded in past experience.
At this stage, I think it’s fine to note that no one would proactively and deliberately choose to compile in a hundred-plus functions just so they can use three to six. Most languages barely notice things like that, but Zig is not most languages, and in fact does something radical (lazy compilation) to ensure that this kind of thing doesn’t happen.
As a way to initially meet some ambitious goals, no problem. I’m always the one saying make your program correct, then if you still need to, make it fast(er), and the same applies to binary size. This stuff can wait a release cycle or two, the solution space is large, and includes approaches which call for no changes to Io.VTable at all: for example, a la carte primitives which the use cases which need absolute minimalism can build on.