Love the idea of abusing the method name to extend an otherwise non-extensible interface. :-) That said, you will want a proper, future-proof design if you are really going to pursue that. An easy way would be to put a single magic number directly before the method name.
struct PyPyTypedMethodMetadata {
int arg_type;
int ret_type;
void* underlying_func;
int magic; // <--
const char ml_name[100];
};
Now either future version of PyPy or other implementation can use a different magic number to evolve that interface. (If you want to be even more careful, put another flag before `magic` and use it as a bitmap to the extension pointers... But that should be more or less covered by `ml_flags` instead.)
Or even more conservatively, you can always require a method with `METH_TYPED` to come with a publicly visible symbol `_PyPyTyped_<type name>_<method name>` or similar. (It is also possible to disambiguate duplicate names if it becomes a bigger concern.) It would be even better if you can do that without `METH_TYPED` at all, e.g. by listing all public symbols.
After some more pondering, I have another question: how about slot methods? I'm sure that you don't really have anything comparable to the method name if slots, and more recent `PyType_Slot` doesn't help either (unless PyPy starts to define its own slot ID). It looks like that there should be some centralized extension point instead of per-method extensions. Extending either `PyModuleDef.m_methods` or `PyModuleDef.m_slots`, by putting metadata before their first entry, seems doable. Discovering their presence is another problem, though.
Or even more conservatively, you can always require a method with `METH_TYPED` to come with a publicly visible symbol `_PyPyTyped_<type name>_<method name>` or similar. (It is also possible to disambiguate duplicate names if it becomes a bigger concern.) It would be even better if you can do that without `METH_TYPED` at all, e.g. by listing all public symbols.