• Dmitry Shesterkin's avatar
    Avoid incorrect type calls from cython.declare and cython.cast in Shadow.py (GH-3244) · 48dc1f01
    Dmitry Shesterkin authored
    The following code:
    ```
    # cython: infer_types=True
    import cython
    
    @cython.cclass
    class Foo:
        a: cython.double
        b: cython.double
        c: cython.double
    
        def __init__(self, a: cython.double, b: cython.double ,c: cython.double):
            self.a = a
            self.b = b
            self.c = c
    
    def bar():
        l = []
        l.append(Foo(10, 20, 30))
    
        v = cython.declare(Foo, l[0])
        r = v.a + v.b
        print( r )
    
        v2 = cython.cast(Foo, l[0]) #Faster - No __Pyx_TypeTest() call
        r = v2.b + v2.c
        print( r )
    
    bar()
    ```
    works fine when compiled and throws an exception when interpreted: `TypeError: __init__() missing 2 required positional arguments: 'b' and 'c'`
    
    It could be fixed if we change implementations as shown in the patch.
    Also, added more tests for the cases I'm trying to fix
    NB: Removed execution of `test_declare(None)` to make sure that the new `none_declare()` test works instead. `test_declare(None)` doesn't throw exception in pure mode but does it in the native mode
    
    Replacing `hasattr(t, '__call__')` to `callable(t)` in the master branch broke the implementation and the tests because the construction was used to detect typedefs. To fix that I got rid of this check completely and replaced it to exact checks which also simplified the code
    
    Changed `declare` implementation when initializing arguments are not provided. Now it correctly works with typedefs of the user classes and also directly support arrays:
        ```
        >>> EmptyClassSyn = cython.typedef(EmptyClass)
        >>> cython.declare(EmptyClassSyn) is None
        True
        >>> cython.declare(cython.int[2]) is not None
        True
        ```
    Added missed return statement to `index_type` which made the following assigment possible:
        ```
            a = cython.declare(cython.int[2])
            a[0] = 1
        ```
    48dc1f01
pure_py.py 11.6 KB