Hi Jeroen, On 25/04/2019 3:42 pm, Jeroen Demeyer wrote: > On 2019-04-25 00:24, Petr Viktorin wrote: >> I believe we can achieve >> that by having PEP 590's (o+offset) point not just to function pointer, >> but to a {function pointer; flags} struct with flags defined for two >> optimizations: > > What's the rationale for putting the flags in the instance? Do you > expect flags to be different between one instance and another instance > of the same class? > >> Both type flags and >> nargs bits are very limited resources. > > Type flags are only a limited resource if you think that all flags ever > added to a type must be put into tp_flags. There is nothing wrong with > adding new fields tp_extraflags or tp_vectorcall_flags to a type. > >> What I don't like about it is that it has >> the extensions built-in; mandatory for all callers/callees. > > I don't agree with the above sentence about PEP 580: > - callers should use APIs like PyCCall_FastCall() and shouldn't need to > worry about the implementation details at all. > - callees can opt out of all the extensions by not setting any special > flags and setting cr_self to a non-NULL value. When using the flags > CCALL_FASTCALL | CCALL_KEYWORDS, then implementing the callee is exactly > the same as PEP 590. > >> As in PEP 590, any class that uses this mechanism shall not be usable as >> a base class. > > Can we please lift this restriction? There is really no reason for it. > I'm not aware of any similar restriction anywhere in CPython. Note that > allowing subclassing is not the same as inheriting the protocol. As a > compromise, we could simply never inherit the protocol. AFAICT, any limitations on subclassing exist solely to prevent tp_call and the PEP 580/590 function pointer being in conflict. This limitation is inherent and the same for both PEPs. Do you agree? Let us conside a class C that sets the Py_TPFLAGS_HAVE_CCALL/Py_TPFLAGS_HAVE_VECTORCALL flag. It will set the function pointer in a new instance, C(), when the object is created. If we create a new class D: class D(C): __call__(self, ...): ... and then create an instance `d = D()` then calling d will have two contradictory behaviours; the one installed by C in the function pointer and the one specified by D.__call__ We can ensure correct behaviour by setting the function pointer to NULL or a forwarding function (depending on the implementation) if __call__ has been overridden. This would be enforced at class creation/readying time. Cheers, Mark.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4