1# cython: infer_types = True 2 3 4cimport cython 5from cython cimport typeof, infer_types 6 7from cpython cimport bool 8 9################################################## 10# type inference tests in 'full' mode 11 12cdef class MyType: 13 pass 14 15def simple(): 16 """ 17 >>> simple() 18 """ 19 i = 3 20 assert typeof(i) == "long", typeof(i) 21 x = 1.41 22 assert typeof(x) == "double", typeof(x) 23 xptr = &x 24 assert typeof(xptr) == "double *", typeof(xptr) 25 xptrptr = &xptr 26 assert typeof(xptrptr) == "double **", typeof(xptrptr) 27 b = b"abc" 28 assert typeof(b) == "bytes object", typeof(b) 29 s = "abc" 30 assert typeof(s) == "str object", typeof(s) 31 u = u"xyz" 32 assert typeof(u) == "unicode object", typeof(u) 33 L = [1,2,3] 34 assert typeof(L) == "list object", typeof(L) 35 t = (4,5,6,()) 36 assert typeof(t) == "tuple object", typeof(t) 37 t2 = (4, 5.0, 6) 38 assert typeof(t2) == "(long, double, long)", typeof(t) 39 40def builtin_types(): 41 """ 42 >>> builtin_types() 43 """ 44 b = bytes() 45 assert typeof(b) == "bytes object", typeof(b) 46 u = unicode() 47 assert typeof(u) == "unicode object", typeof(u) 48 L = list() 49 assert typeof(L) == "list object", typeof(L) 50 t = tuple() 51 assert typeof(t) == "tuple object", typeof(t) 52 d = dict() 53 assert typeof(d) == "dict object", typeof(d) 54 B = bool() 55 assert typeof(B) == "bool", typeof(B) 56 57def slicing(): 58 """ 59 >>> slicing() 60 """ 61 b = b"abc" 62 assert typeof(b) == "bytes object", typeof(b) 63 b1 = b[1:2] 64 assert typeof(b1) == "bytes object", typeof(b1) 65 b2 = b[1:2:2] 66 assert typeof(b2) == "bytes object", typeof(b2) 67 u = u"xyz" 68 assert typeof(u) == "unicode object", typeof(u) 69 u1 = u[1:2] 70 assert typeof(u1) == "unicode object", typeof(u1) 71 u2 = u[1:2:2] 72 assert typeof(u2) == "unicode object", typeof(u2) 73 s = "xyz" 74 assert typeof(s) == "str object", typeof(s) 75 s1 = s[1:2] 76 assert typeof(s1) == "str object", typeof(s1) 77 s2 = s[1:2:2] 78 assert typeof(s2) == "str object", typeof(s2) 79 L = [1,2,3] 80 assert typeof(L) == "list object", typeof(L) 81 L1 = L[1:2] 82 assert typeof(L1) == "list object", typeof(L1) 83 L2 = L[1:2:2] 84 assert typeof(L2) == "list object", typeof(L2) 85 t = (4,5,6,()) 86 assert typeof(t) == "tuple object", typeof(t) 87 t1 = t[1:2] 88 assert typeof(t1) == "tuple object", typeof(t1) 89 t2 = t[1:2:2] 90 assert typeof(t2) == "tuple object", typeof(t2) 91 92def indexing(): 93 """ 94 >>> indexing() 95 """ 96 b = b"abc" 97 assert typeof(b) == "bytes object", typeof(b) 98 b1 = b[1] 99 assert typeof(b1) == "Python object", typeof(b1) # Py2: bytes, Py3: int 100 u = u"xyz" 101 assert typeof(u) == "unicode object", typeof(u) 102 u1 = u[1] 103 assert typeof(u1) == "Py_UCS4", typeof(u1) 104 s = "xyz" 105 assert typeof(s) == "str object", typeof(s) 106 s1 = s[1] 107 assert typeof(s1) == "str object", typeof(s1) 108 L = [1,2,3] 109 assert typeof(L) == "list object", typeof(L) 110 L1 = L[1] 111 assert typeof(L1) == "Python object", typeof(L1) 112 t = (4,5,()) 113 assert typeof(t) == "tuple object", typeof(t) 114 t1 = t[1] 115 assert typeof(t1) == "long", typeof(t1) 116 t2 = ('abc', 'def', 'ghi') 117 assert typeof(t2) == "tuple object", typeof(t2) 118 t2_1 = t2[1] 119 assert typeof(t2_1) == "str object", typeof(t2_1) 120 t2_2 = t2[t[0]-3] 121 assert typeof(t2_2) == "str object", typeof(t2_2) 122 t5 = (b'abc', 'def', u'ghi') 123 t5_0 = t5[0] 124 assert typeof(t5_0) == "bytes object", typeof(t5_0) 125 t5_1 = t5[1] 126 assert typeof(t5_1) == "str object", typeof(t5_1) 127 t5_2 = t5[2] 128 assert typeof(t5_2) == "unicode object", typeof(t5_2) 129 t5_3 = t5[t[0]-3] 130 assert typeof(t5_3) == "Python object", typeof(t5_3) 131 132 133def multiple_assignments(): 134 """ 135 >>> multiple_assignments() 136 """ 137 a = 3 138 a = 4 139 a = 5 140 assert typeof(a) == "long", typeof(a) 141 b = a 142 b = 3.1 143 b = 3.14159 144 assert typeof(b) == "double", typeof(b) 145 c = a 146 c = b 147 c = [1,2,3] 148 assert typeof(c) == "Python object", typeof(c) 149 d = b'abc' 150 d = bytes() 151 d = bytes(b'xyz') 152 d = None 153 assert typeof(d) == "bytes object", typeof(d) 154 155 156def arithmetic(): 157 """ 158 >>> arithmetic() 159 """ 160 a = 1 + 2 161 assert typeof(a) == "long", typeof(a) 162 b = 1 + 1.5 163 assert typeof(b) == "double", typeof(b) 164 c = 1 + <object>2 165 assert typeof(c) == "Python object", typeof(c) 166 d = 1 * 1.5 ** 2 167 assert typeof(d) == "double", typeof(d) 168 169cdef class some_class: 170 pass 171 172def unary_operators(): 173 """ 174 >>> unary_operators() 175 """ 176 cdef int x = 1 177 assert typeof(~x) == "int", typeof(~x) 178 cdef some_class obj 179 assert typeof(~obj) == "Python object", typeof(~obj) 180 a = int(1) 181 assert typeof(a) == "Python object", typeof(a) 182 b = not int(3) 183 assert typeof(b) == "bint", typeof(b) 184 c = +int(3) 185 assert typeof(c) == "Python object", typeof(c) 186 d = -int(5) 187 assert typeof(d) == "Python object", typeof(d) 188 189 190def builtin_type_operations(): 191 """ 192 >>> builtin_type_operations() 193 """ 194 b1 = b'a' * 10 195 b1 = 10 * b'a' 196 b1 = 10 * b'a' * 10 197 assert typeof(b1) == "bytes object", typeof(b1) 198 b2 = b'a' + b'b' 199 assert typeof(b2) == "bytes object", typeof(b2) 200 u1 = u'a' * 10 201 u1 = 10 * u'a' 202 assert typeof(u1) == "unicode object", typeof(u1) 203 u2 = u'a' + u'b' 204 assert typeof(u2) == "unicode object", typeof(u2) 205 u3 = u'a%s' % u'b' 206 u3 = u'a%s' % 10 207 assert typeof(u3) == "unicode object", typeof(u3) 208 s1 = "abc %s" % "x" 209 s1 = "abc %s" % 10 210 assert typeof(s1) == "str object", typeof(s1) 211 s2 = "abc %s" + "x" 212 assert typeof(s2) == "str object", typeof(s2) 213 s3 = "abc %s" * 10 214 s3 = "abc %s" * 10 * 10 215 s3 = 10 * "abc %s" * 10 216 assert typeof(s3) == "str object", typeof(s3) 217 L1 = [] + [] 218 assert typeof(L1) == "list object", typeof(L1) 219 L2 = [] * 2 220 assert typeof(L2) == "list object", typeof(L2) 221 T1 = () + () 222 assert typeof(T1) == "tuple object", typeof(T1) 223 T2 = () * 2 224 assert typeof(T2) == "tuple object", typeof(T2) 225 226def builtin_type_methods(): 227 """ 228 >>> builtin_type_methods() 229 """ 230 l = [] 231 assert typeof(l) == 'list object', typeof(l) 232 append = l.append 233 assert typeof(append) == 'Python object', typeof(append) 234 append(1) 235 assert l == [1], str(l) 236 237cdef int cfunc(int x): 238 return x+1 239 240def c_functions(): 241 """ 242 >>> c_functions() 243 """ 244 f = cfunc 245 assert typeof(f) == 'int (*)(int)', typeof(f) 246 assert 2 == f(1) 247 248def builtin_functions(): 249 """ 250 >>> _abs, _getattr = builtin_functions() 251 Python object 252 Python object 253 >>> _abs(-1) 254 1 255 >>> class o(object): pass 256 >>> o.x = 1 257 >>> _getattr(o, 'x') 258 1 259 """ 260 _abs = abs 261 print(typeof(_abs)) 262 _getattr = getattr 263 print(typeof(_getattr)) 264 return _abs, _getattr 265 266def cascade(): 267 """ 268 >>> cascade() 269 """ 270 a = 1.0 271 b = a + 2 272 c = b + 3 273 d = c + 4 274 assert typeof(d) == "double" 275 e = a + b + c + d 276 assert typeof(e) == "double" 277 278def cascaded_assignment(): 279 """ 280 >>> cascaded_assignment() 281 """ 282 a = b = c = d = 1.0 283 assert typeof(a) == "double" 284 assert typeof(b) == "double" 285 assert typeof(c) == "double" 286 assert typeof(d) == "double" 287 e = a + b + c + d 288 assert typeof(e) == "double" 289 290 291def unpacking(x): 292 """ 293 >>> unpacking(0) 294 """ 295 a, b, c, (d, e) = x, 1, 2.0, [3, [5, 6]] 296 assert typeof(a) == "Python object", typeof(a) 297 assert typeof(b) == "long", typeof(b) 298 assert typeof(c) == "double", typeof(c) 299 assert typeof(d) == "long", typeof(d) 300 assert typeof(e) == "list object", typeof(e) 301 302 303def star_unpacking(*x): 304 """ 305 >>> star_unpacking(1, 2) 306 """ 307 a, b = x 308 c, *d = x 309 *e, f = x 310 *g, g = x # re-assignment 311 assert typeof(a) == "Python object", typeof(a) 312 assert typeof(b) == "Python object", typeof(b) 313 assert typeof(c) == "Python object", typeof(c) 314 assert typeof(d) == "list object", typeof(d) 315 assert typeof(e) == "list object", typeof(e) 316 assert typeof(f) == "Python object", typeof(f) 317 assert typeof(g) == "Python object", typeof(f) 318 319 320def increment(): 321 """ 322 >>> increment() 323 """ 324 a = 5 325 a += 1 326 assert typeof(a) == "long" 327 328def loop(): 329 """ 330 >>> loop() 331 """ 332 for a in range(10): 333 pass 334 assert typeof(a) == "long" 335 336 b = 1.0 337 for b in range(5): 338 pass 339 assert typeof(b) == "double" 340 341 for c from 0 <= c < 10 by .5: 342 pass 343 assert typeof(c) == "double" 344 345 for d in range(0, 10L, 2): 346 pass 347 assert typeof(a) == "long" 348 349def loop_over_charptr(): 350 """ 351 >>> print( loop_over_charptr() ) 352 char 353 """ 354 cdef char* char_ptr_string = 'abcdefg' 355 for c in char_ptr_string: 356 pass 357 return typeof(c) 358 359def loop_over_bytes_literal(): 360 """ 361 >>> print( loop_over_bytes_literal() ) 362 Python object 363 """ 364 for c in b'abcdefg': 365 pass 366 return typeof(c) 367 368def loop_over_bytes(): 369 """ 370 >>> print( loop_over_bytes() ) 371 Python object 372 """ 373 cdef bytes bytes_string = b'abcdefg' 374 # bytes in Py2, int in Py3 375 for c in bytes_string: 376 pass 377 return typeof(c) 378 379def loop_over_str(): 380 """ 381 >>> print( loop_over_str() ) 382 str object 383 """ 384 cdef str string = 'abcdefg' 385 # str (bytes) in Py2, str (unicode) in Py3 386 for c in string: 387 pass 388 return typeof(c) 389 390def loop_over_unicode(): 391 """ 392 >>> print( loop_over_unicode() ) 393 Py_UCS4 394 """ 395 cdef unicode ustring = u'abcdefg' 396 # Py_UCS4 can represent any Unicode character 397 for uchar in ustring: 398 pass 399 return typeof(uchar) 400 401def loop_over_unicode_literal(): 402 """ 403 >>> print( loop_over_unicode_literal() ) 404 Py_UCS4 405 """ 406 # Py_UCS4 can represent any Unicode character 407 for uchar in u'abcdefg': 408 pass 409 return typeof(uchar) 410 411def loop_over_int_array(): 412 """ 413 >>> print( loop_over_int_array() ) 414 int 415 """ 416 cdef int[10] int_array 417 for i in int_array: 418 pass 419 return typeof(i) 420 421cdef struct MyStruct: 422 int a 423 424def loop_over_struct_ptr(): 425 """ 426 >>> print( loop_over_struct_ptr() ) 427 MyStruct 428 """ 429 cdef MyStruct[10] a_list 430 cdef MyStruct *a_ptr = a_list 431 for i in a_list[:10]: 432 pass 433 return typeof(i) 434 435cdef unicode retu(): 436 return u"12345" 437 438cdef bytes retb(): 439 return b"12345" 440 441def conditional(x): 442 """ 443 >>> conditional(True) 444 (True, 'Python object') 445 >>> conditional(False) 446 (False, 'Python object') 447 """ 448 if x: 449 a = retu() 450 else: 451 a = retb() 452 return type(a) is unicode, typeof(a) 453 454################################################## 455# type inference tests that work in 'safe' mode 456 457@infer_types(None) 458def double_inference(): 459 """ 460 >>> values, types = double_inference() 461 >>> values == (1.0, 1.0*2, 1.0*2.0+2.0*2.0, 1.0*2.0) 462 True 463 >>> types 464 ('double', 'double', 'double', 'Python object') 465 """ 466 d_a = 1.0 467 d_b = d_a * float(2) 468 d_c = d_a * float(some_float_value()) + d_b * float(some_float_value()) 469 o_d = d_a * some_float_value() 470 return (d_a,d_b,d_c,o_d), (typeof(d_a), typeof(d_b), typeof(d_c), typeof(o_d)) 471 472cdef object some_float_value(): 473 return 2.0 474 475 476@infer_types(None) 477@cython.test_fail_if_path_exists('//DefNode//NameNode[@type.is_pyobject = True]') 478@cython.test_assert_path_exists('//DefNode//NameNode[@type.is_pyobject]', 479 '//DefNode//NameNode[@type.is_pyobject = False]') 480def double_loop(): 481 """ 482 >>> double_loop() == 1.0 * 10 483 True 484 """ 485 cdef int i 486 d = 1.0 487 for i in range(9): 488 d += 1.0 489 return d 490 491@infer_types(None) 492def safe_only(): 493 """ 494 >>> safe_only() 495 """ 496 a = 1.0 497 assert typeof(a) == "double", typeof(c) 498 b = 1; 499 assert typeof(b) == "long", typeof(b) 500 c = MyType() 501 assert typeof(c) == "MyType", typeof(c) 502 for i in range(10): pass 503 assert typeof(i) == "long", typeof(i) 504 d = 1 505 res = ~d 506 assert typeof(d) == "long", typeof(d) 507 508 # we special-case inference to type str, see 509 # trac #553 510 s = "abc" 511 assert typeof(s) == "Python object", typeof(s) 512 cdef str t = "def" 513 assert typeof(t) == "str object", typeof(t) 514 515 # potentially overflowing arithmetic 516 e = 1 517 e += 1 518 assert typeof(e) == "Python object", typeof(e) 519 f = 1 520 res = f * 10 521 assert typeof(f) == "Python object", typeof(f) 522 g = 1 523 res = 10*(~g) 524 assert typeof(g) == "Python object", typeof(g) 525 for j in range(10): 526 res = -j 527 assert typeof(j) == "Python object", typeof(j) 528 h = 1 529 res = abs(h) 530 assert typeof(h) == "Python object", typeof(h) 531 cdef int c_int = 1 532 assert typeof(abs(c_int)) == "int", typeof(abs(c_int)) 533 534@infer_types(None) 535def safe_c_functions(): 536 """ 537 >>> safe_c_functions() 538 """ 539 f = cfunc 540 assert typeof(f) == 'int (*)(int)', typeof(f) 541 assert 2 == f(1) 542 543@infer_types(None) 544def ptr_types(): 545 """ 546 >>> ptr_types() 547 """ 548 cdef int a 549 a_ptr = &a 550 assert typeof(a_ptr) == "int *", typeof(a_ptr) 551 a_ptr_ptr = &a_ptr 552 assert typeof(a_ptr_ptr) == "int **", typeof(a_ptr_ptr) 553 cdef int[1] b 554 b_ref = b 555 assert typeof(b_ref) == "int *", typeof(b_ref) 556 ptr = &a 557 ptr = b 558 assert typeof(ptr) == "int *", typeof(ptr) 559 560def const_types(const double x, double y, double& z): 561 """ 562 >>> const_types(1, 1, 1) 563 """ 564 a = x 565 a = y 566 a = z 567 assert typeof(a) == "double", typeof(a) 568 569@infer_types(None) 570def args_tuple_keywords(*args, **kwargs): 571 """ 572 >>> args_tuple_keywords(1,2,3, a=1, b=2) 573 """ 574 assert typeof(args) == "tuple object", typeof(args) 575 assert typeof(kwargs) == "dict object", typeof(kwargs) 576 577@infer_types(None) 578def args_tuple_keywords_reassign_same(*args, **kwargs): 579 """ 580 >>> args_tuple_keywords_reassign_same(1,2,3, a=1, b=2) 581 """ 582 assert typeof(args) == "tuple object", typeof(args) 583 assert typeof(kwargs) == "dict object", typeof(kwargs) 584 585 args = () 586 kwargs = {} 587 588@infer_types(None) 589def args_tuple_keywords_reassign_pyobjects(*args, **kwargs): 590 """ 591 >>> args_tuple_keywords_reassign_pyobjects(1,2,3, a=1, b=2) 592 """ 593 assert typeof(args) == "Python object", typeof(args) 594 assert typeof(kwargs) == "Python object", typeof(kwargs) 595 596 args = [] 597 kwargs = "test" 598 599# / A -> AA -> AAA 600# Base0 -> Base - 601# \ B -> BB 602# C -> CC 603 604cdef class Base0: pass 605cdef class Base(Base0): pass 606cdef class A(Base): pass 607cdef class AA(A): pass 608cdef class AAA(AA): pass 609cdef class B(Base): pass 610cdef class BB(B): pass 611cdef class C: pass 612cdef class CC(C): pass 613 614@infer_types(None) 615def common_extension_type_base(): 616 """ 617 >>> common_extension_type_base() 618 """ 619 x = A() 620 x = AA() 621 assert typeof(x) == "A", typeof(x) 622 y = A() 623 y = B() 624 assert typeof(y) == "Base", typeof(y) 625 z = AAA() 626 z = BB() 627 assert typeof(z) == "Base", typeof(z) 628 w = A() 629 w = CC() 630 assert typeof(w) == "Python object", typeof(w) 631 632cdef class AcceptsKeywords: 633 def __init__(self, *args, **kwds): 634 pass 635 636@infer_types(None) 637def constructor_call(): 638 """ 639 >>> constructor_call() 640 """ 641 x = AcceptsKeywords(a=1, b=2) 642 assert typeof(x) == "AcceptsKeywords", typeof(x) 643 644 645@infer_types(None) 646def large_literals(): 647 """ 648 >>> large_literals() 649 """ 650 # It's only safe to infer small integer literals. 651 a = 10 652 b = 100000000000000000000000000000000 653 assert typeof(a) == "long", typeof(a) 654 assert typeof(b) == "Python object", typeof(b) 655 c, d = 10, 100000000000000000000000000000000 656 assert typeof(c) == "long", typeof(c) 657 assert typeof(d) == "Python object", typeof(d) 658 659 660class EmptyContextManager(object): 661 def __enter__(self): 662 return None 663 def __exit__(self, *args): 664 return 0 665 666def with_statement(): 667 """ 668 >>> with_statement() 669 Python object 670 Python object 671 """ 672 x = 1.0 673 with EmptyContextManager() as x: 674 print(typeof(x)) 675 print(typeof(x)) 676 return x 677 678@cython.final 679cdef class TypedContextManager(object): 680 cpdef double __enter__(self): 681 return 2.0 682 def __exit__(self, *args): 683 return 0 684 685def with_statement_typed(): 686 """ 687 >>> with_statement_typed() 688 double 689 double 690 2.0 691 """ 692 x = 1.0 693 with TypedContextManager() as x: 694 print(typeof(x)) 695 print(typeof(x)) 696 return x 697 698def with_statement_untyped(): 699 """ 700 >>> with_statement_untyped() 701 Python object 702 Python object 703 2.0 704 """ 705 x = 1.0 706 cdef object t = TypedContextManager() 707 with t as x: 708 print(typeof(x)) 709 print(typeof(x)) 710 return x 711 712def self_lookup(a): 713 b = a 714 b = b.foo(keyword=None) 715 print typeof(b) 716 717# Regression test for trac #638. 718 719def bar(foo): 720 qux = foo 721 quux = foo[qux.baz] 722 723 724cdef enum MyEnum: 725 enum_x = 1 726 enum_y = 2 727 728ctypedef long my_long 729def test_int_typedef_inference(): 730 """ 731 >>> test_int_typedef_inference() 732 """ 733 cdef long x = 1 734 cdef my_long y = 2 735 cdef long long z = 3 736 assert typeof(x + y) == typeof(y + x) == 'my_long', typeof(x + y) 737 assert typeof(y + z) == typeof(z + y) == 'long long', typeof(y + z) 738 739from libc.stdint cimport int32_t, int64_t 740def int64_long_sum(): 741 cdef long x = 1 742 cdef int32_t x32 = 2 743 cdef int64_t x64 = 3 744 cdef unsigned long ux = 4 745 assert typeof(x + x32) == typeof(x32 + x) == 'long', typeof(x + x32) 746 assert typeof(x + x64) == typeof(x64 + x) == 'int64_t', typeof(x + x64) 747 # The correct answer here is either unsigned long or int64_t, depending on 748 # whether sizeof(long) == 64 or not. Incorrect signedness is probably 749 # preferable to incorrect width. 750 assert typeof(ux + x64) == typeof(x64 + ux) == 'int64_t', typeof(ux + x64) 751 752cdef class InferInProperties: 753 """ 754 >>> InferInProperties().x 755 ('double', 'unicode object', 'MyEnum', 'MyEnum') 756 """ 757 cdef MyEnum attr 758 def __cinit__(self): 759 self.attr = enum_x 760 761 property x: 762 def __get__(self): 763 a = 1.0 764 b = u'abc' 765 c = self.attr 766 d = enum_y 767 c = d 768 return typeof(a), typeof(b), typeof(c), typeof(d) 769 770cdef class WithMethods: 771 cdef int offset 772 def __init__(self, offset): 773 self.offset = offset 774 cpdef int one_arg(self, int x): 775 return x + self.offset 776 cpdef int default_arg(self, int x, int y=0): 777 return x + y + self.offset 778 779def test_bound_methods(): 780 """ 781 >>> test_bound_methods() 782 """ 783 o = WithMethods(10) 784 assert typeof(o) == 'WithMethods', typeof(o) 785 786 one_arg = o.one_arg 787 assert one_arg(2) == 12, one_arg(2) 788 789 default_arg = o.default_arg 790 assert default_arg(2) == 12, default_arg(2) 791 assert default_arg(2, 3) == 15, default_arg(2, 2) 792 793def test_builtin_max(): 794 """ 795 # builtin max is slightly complicated because it gets transformed to EvalWithTempExprNode 796 # See https://github.com/cython/cython/issues/4155 797 >>> test_builtin_max() 798 """ 799 class C: 800 a = 2 801 def get_max(self): 802 a = max(self.a, self.a) 803 assert typeof(a) == "Python object", typeof(a) 804 C().get_max() 805