[Cython] non-virtual methods

Robert Bradshaw robertwb at math.washington.edu
Tue Aug 30 07:32:52 CEST 2011


On Sun, Aug 28, 2011 at 4:00 AM, Vitja Makarov <vitja.makarov at gmail.com> wrote:
> 2011/8/27 Vitja Makarov <vitja.makarov at gmail.com>:
>> 2011/8/27 Vitja Makarov <vitja.makarov at gmail.com>:
>>> 2011/8/26 Vitja Makarov <vitja.makarov at gmail.com>:
>>>> 2011/8/25 Vitja Makarov <vitja.makarov at gmail.com>:
>>>>> 2011/8/25 Vitja Makarov <vitja.makarov at gmail.com>:
>>>>>> 2011/8/25 Stefan Behnel <stefan_ml at behnel.de>:
>>>>>>> Vitja Makarov, 25.08.2011 20:32:
>>>>>>>>
>>>>>>>> 2011/8/25 Stefan Behnel<stefan_ml at behnel.de>:
>>>>>>>>>
>>>>>>>>> Vitja Makarov, 25.08.2011 18:11:
>>>>>>>>>>
>>>>>>>>>> 2011/8/24 Stefan Behnel:
>>>>>>>>>>>
>>>>>>>>>>> Vitja Makarov, 24.08.2011 21:17:
>>>>>>>>>>>>
>>>>>>>>>>>> I tried final classes:
>>>>>>>>>>>> 2. In this example foo call is done through virtual table
>>>>>>>>>>>>
>>>>>>>>>>>> cimport cython
>>>>>>>>>>>>
>>>>>>>>>>>> @cython.final
>>>>>>>>>>>> cdef class Foo:
>>>>>>>>>>>>     cdef foo(self):
>>>>>>>>>>>>         print 'haha'
>>>>>>>>>>>>
>>>>>>>>>>>> def test():
>>>>>>>>>>>>     cdef Foo a = Foo()
>>>>>>>>>>>>     a.foo()
>>>>>>>>>>>>
>>>>>>>>>>>>   __pyx_t_1 = ((struct __pyx_vtabstruct_3yyy_Foo
>>>>>>>>>>>> *)__pyx_v_a->__pyx_vtab)->foo(__pyx_v_a); if (unlikely(!__pyx_t_1))
>>>>>>>>>>>> {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno =
>>>>>>>>>>>> __LINE__; goto __pyx_L1_error;}
>>>>>>>>>>>
>>>>>>>>>>> Right, this is not implemented yet. Feel free to do so. Also see
>>>>>>>>>>>
>>>>>>>>>>> http://trac.cython.org/cython_trac/ticket/474
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>> 3. I can't use final decorator for methods (error reported)
>>>>>>>>>>>
>>>>>>>>>>> http://trac.cython.org/cython_trac/ticket/586
>>>>>>>>>>
>>>>>>>>>> What is the prefered syntax keyword inline or final decorator?
>>>>>>>>>
>>>>>>>>> "final" is the right option here.
>>>>>>>>>
>>>>>>>>> They are orthogonal concepts. Only because you declare a method "final"
>>>>>>>>> does
>>>>>>>>> not mean you want to inline it, and just because you declare it "inline"
>>>>>>>>> does not (necessarily) mean that you cannot override it. Admittedly, the
>>>>>>>>> semantics of an overridable inline method may turn out to be somewhat
>>>>>>>>> obscure and error prone, so I think it's a good idea to let "inline"
>>>>>>>>> imply
>>>>>>>>> "final". But not the other way round.
>>>>>>>>
>>>>>>>> But both inline and final methods should bypass vtab, right?
>>>>>>>
>>>>>>> Yes. But in the "final" case, it's always clear which method implementation
>>>>>>> to use - it's not overridable, so there is only one choice. In the "inline"
>>>>>>> case, it could still be overridable and we may have a subtype of the
>>>>>>> declared type in our hands at runtime, thus choosing the wrong method at
>>>>>>> compile time. That's why only the "final" case is safe.
>>>>>>>
>>>>>>> Note that I'm only talking about the semantics of the qualifier themselves
>>>>>>> here. If we allow "inline" methods, I think we should force them to be
>>>>>>> "final" as well. But that's a practical choice, not a semantic implication.
>>>>>>>
>>>>>>>
>>>>>>>> Also I'm not sure about C inline qualifier here.
>>>>>>>
>>>>>>> That's what "inline" requests.
>>>>>>>
>>>>>>>
>>>>>>>> I see three options:
>>>>>>>>
>>>>>>>>  - non-virtual: bypass vtab
>>>>>>>>  - final: non-virtual, non-overridable
>>>>>>>
>>>>>>> How would you want to bypass the vtable in the "non-virtual" case if the
>>>>>>> method is overridable?
>>>>>>>
>>>>>>>
>>>>>>>>  - inline: non-virtual, C inline qualifier is used
>>>>>>>
>>>>>>> Correct.
>>>>>>>
>>>>>>
>>>>>> Ok.
>>>>>>
>>>>>> I think it's better to implement final method then user could choose
>>>>>> to use inline qualifier or not.
>>>>>>
>>>>>
>>>>> I tried it here:
>>>>> https://github.com/vitek/cython/commit/ddf80a80dc75aced2cd92dc32afa77a7bcf2de02
>>>>>
>>>>> There is one problem: vtab bypassing should be enabled if final method
>>>>> is defined in the same module.
>>>>> I don't know how to check that final method comes from cimport (it's
>>>>> okay with pxd, the problem is pyx)
>>>>>
>>>>
>>>>
>>>> https://github.com/vitek/cython/commit/6e91fc257a683018ba6be340d384f9a7c34ef425
>>>>
>>>> Here is update version. I've add tree asserts and final method's prototypes.
>>>>
>>>> --
>>>> vitja.
>>>>
>>>
>>> I've created ticket for compiler crash when cython.final is used
>>> inside pxd file:
>>>
>>> http://trac.cython.org/cython_trac/ticket/722
>>>
>>> Also I've updated final methods test case (added tree path assertions)
>>> https://github.com/vitek/cython/commit/92edb09419c9b77a792f7c43e6ddd760b00c4e74
>>>
>>>
>>> About declaration origin detection may be it's a good idea to have a
>>> flag at scope level something like is_pxd_scope or
>>> is_declaration_scope?
>>>
>>
>> It seems to me that I found a way to fix pxd/pyx cimport problem. I've
>> created pull request:
>>
>> https://github.com/cython/cython/pull/59
>>
>
> I've add support for inline methods, now you can declare inline method
> in pxd file:
>
> cdef class Foo:
>   cdef inline foo(self):
>       return 1

Cool.

I suppose for cross-module calls, non-inline methods vtables are best
one can do short of actually linking the modules together. One
question about your code--I'm not seeing how you're disallowing
overriding final cpdef methods from Python. (Should we even allow
final cpdef methods on non-final classes?)

- Robert


More information about the cython-devel mailing list