numba-cuda 0.19.0__py3-none-any.whl → 0.20.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of numba-cuda might be problematic. Click here for more details.

Files changed (353) hide show
  1. _numba_cuda_redirector.pth +3 -0
  2. _numba_cuda_redirector.py +3 -0
  3. numba_cuda/VERSION +1 -1
  4. numba_cuda/__init__.py +2 -1
  5. numba_cuda/_version.py +2 -13
  6. numba_cuda/numba/cuda/__init__.py +4 -1
  7. numba_cuda/numba/cuda/_internal/cuda_bf16.py +12708 -1469
  8. numba_cuda/numba/cuda/_internal/cuda_fp16.py +2656 -8769
  9. numba_cuda/numba/cuda/api.py +9 -1
  10. numba_cuda/numba/cuda/api_util.py +3 -0
  11. numba_cuda/numba/cuda/args.py +3 -0
  12. numba_cuda/numba/cuda/bf16.py +288 -2
  13. numba_cuda/numba/cuda/cg.py +3 -0
  14. numba_cuda/numba/cuda/cgutils.py +5 -2
  15. numba_cuda/numba/cuda/cloudpickle/__init__.py +21 -0
  16. numba_cuda/numba/cuda/cloudpickle/cloudpickle.py +1598 -0
  17. numba_cuda/numba/cuda/cloudpickle/cloudpickle_fast.py +17 -0
  18. numba_cuda/numba/cuda/codegen.py +4 -1
  19. numba_cuda/numba/cuda/compiler.py +376 -30
  20. numba_cuda/numba/cuda/core/analysis.py +319 -0
  21. numba_cuda/numba/cuda/core/annotations/__init__.py +0 -0
  22. numba_cuda/numba/cuda/core/annotations/type_annotations.py +304 -0
  23. numba_cuda/numba/cuda/core/base.py +1289 -0
  24. numba_cuda/numba/cuda/core/bytecode.py +727 -0
  25. numba_cuda/numba/cuda/core/caching.py +5 -2
  26. numba_cuda/numba/cuda/core/callconv.py +3 -0
  27. numba_cuda/numba/cuda/core/codegen.py +3 -0
  28. numba_cuda/numba/cuda/core/compiler.py +9 -14
  29. numba_cuda/numba/cuda/core/compiler_machinery.py +497 -0
  30. numba_cuda/numba/cuda/core/config.py +747 -0
  31. numba_cuda/numba/cuda/core/consts.py +124 -0
  32. numba_cuda/numba/cuda/core/cpu.py +370 -0
  33. numba_cuda/numba/cuda/core/environment.py +68 -0
  34. numba_cuda/numba/cuda/core/event.py +511 -0
  35. numba_cuda/numba/cuda/core/funcdesc.py +330 -0
  36. numba_cuda/numba/cuda/core/inline_closurecall.py +1889 -0
  37. numba_cuda/numba/cuda/core/interpreter.py +52 -27
  38. numba_cuda/numba/cuda/core/ir_utils.py +17 -29
  39. numba_cuda/numba/cuda/core/options.py +262 -0
  40. numba_cuda/numba/cuda/core/postproc.py +249 -0
  41. numba_cuda/numba/cuda/core/pythonapi.py +1868 -0
  42. numba_cuda/numba/cuda/core/rewrites/__init__.py +26 -0
  43. numba_cuda/numba/cuda/core/rewrites/ir_print.py +90 -0
  44. numba_cuda/numba/cuda/core/rewrites/registry.py +104 -0
  45. numba_cuda/numba/cuda/core/rewrites/static_binop.py +40 -0
  46. numba_cuda/numba/cuda/core/rewrites/static_getitem.py +187 -0
  47. numba_cuda/numba/cuda/core/rewrites/static_raise.py +98 -0
  48. numba_cuda/numba/cuda/core/sigutils.py +3 -0
  49. numba_cuda/numba/cuda/core/ssa.py +496 -0
  50. numba_cuda/numba/cuda/core/targetconfig.py +329 -0
  51. numba_cuda/numba/cuda/core/tracing.py +231 -0
  52. numba_cuda/numba/cuda/core/transforms.py +952 -0
  53. numba_cuda/numba/cuda/core/typed_passes.py +741 -7
  54. numba_cuda/numba/cuda/core/typeinfer.py +1948 -0
  55. numba_cuda/numba/cuda/core/unsafe/__init__.py +0 -0
  56. numba_cuda/numba/cuda/core/unsafe/bytes.py +67 -0
  57. numba_cuda/numba/cuda/core/unsafe/eh.py +66 -0
  58. numba_cuda/numba/cuda/core/unsafe/refcount.py +98 -0
  59. numba_cuda/numba/cuda/core/untyped_passes.py +1983 -0
  60. numba_cuda/numba/cuda/cpython/cmathimpl.py +560 -0
  61. numba_cuda/numba/cuda/cpython/mathimpl.py +499 -0
  62. numba_cuda/numba/cuda/cpython/numbers.py +1474 -0
  63. numba_cuda/numba/cuda/cuda_paths.py +425 -246
  64. numba_cuda/numba/cuda/cudadecl.py +4 -1
  65. numba_cuda/numba/cuda/cudadrv/__init__.py +4 -1
  66. numba_cuda/numba/cuda/cudadrv/devicearray.py +5 -1
  67. numba_cuda/numba/cuda/cudadrv/devices.py +3 -0
  68. numba_cuda/numba/cuda/cudadrv/driver.py +14 -140
  69. numba_cuda/numba/cuda/cudadrv/drvapi.py +3 -0
  70. numba_cuda/numba/cuda/cudadrv/dummyarray.py +114 -24
  71. numba_cuda/numba/cuda/cudadrv/enums.py +3 -0
  72. numba_cuda/numba/cuda/cudadrv/error.py +4 -0
  73. numba_cuda/numba/cuda/cudadrv/libs.py +8 -5
  74. numba_cuda/numba/cuda/cudadrv/linkable_code.py +3 -0
  75. numba_cuda/numba/cuda/cudadrv/mappings.py +4 -1
  76. numba_cuda/numba/cuda/cudadrv/ndarray.py +3 -0
  77. numba_cuda/numba/cuda/cudadrv/nvrtc.py +22 -8
  78. numba_cuda/numba/cuda/cudadrv/nvvm.py +4 -4
  79. numba_cuda/numba/cuda/cudadrv/rtapi.py +3 -0
  80. numba_cuda/numba/cuda/cudadrv/runtime.py +4 -1
  81. numba_cuda/numba/cuda/cudaimpl.py +8 -1
  82. numba_cuda/numba/cuda/cudamath.py +3 -0
  83. numba_cuda/numba/cuda/debuginfo.py +88 -2
  84. numba_cuda/numba/cuda/decorators.py +6 -3
  85. numba_cuda/numba/cuda/descriptor.py +6 -4
  86. numba_cuda/numba/cuda/device_init.py +3 -0
  87. numba_cuda/numba/cuda/deviceufunc.py +69 -2
  88. numba_cuda/numba/cuda/dispatcher.py +21 -39
  89. numba_cuda/numba/cuda/errors.py +10 -0
  90. numba_cuda/numba/cuda/extending.py +3 -0
  91. numba_cuda/numba/cuda/flags.py +143 -1
  92. numba_cuda/numba/cuda/fp16.py +3 -2
  93. numba_cuda/numba/cuda/include/13/cuda_bf16.h +5118 -0
  94. numba_cuda/numba/cuda/include/13/cuda_bf16.hpp +3865 -0
  95. numba_cuda/numba/cuda/include/13/cuda_fp16.h +5363 -0
  96. numba_cuda/numba/cuda/include/13/cuda_fp16.hpp +3483 -0
  97. numba_cuda/numba/cuda/initialize.py +4 -0
  98. numba_cuda/numba/cuda/intrinsic_wrapper.py +3 -0
  99. numba_cuda/numba/cuda/intrinsics.py +3 -0
  100. numba_cuda/numba/cuda/itanium_mangler.py +3 -0
  101. numba_cuda/numba/cuda/kernels/__init__.py +2 -0
  102. numba_cuda/numba/cuda/kernels/reduction.py +3 -0
  103. numba_cuda/numba/cuda/kernels/transpose.py +3 -0
  104. numba_cuda/numba/cuda/libdevice.py +4 -0
  105. numba_cuda/numba/cuda/libdevicedecl.py +3 -0
  106. numba_cuda/numba/cuda/libdevicefuncs.py +3 -0
  107. numba_cuda/numba/cuda/libdeviceimpl.py +3 -0
  108. numba_cuda/numba/cuda/locks.py +3 -0
  109. numba_cuda/numba/cuda/lowering.py +59 -159
  110. numba_cuda/numba/cuda/mathimpl.py +5 -1
  111. numba_cuda/numba/cuda/memory_management/__init__.py +3 -0
  112. numba_cuda/numba/cuda/memory_management/memsys.cu +5 -0
  113. numba_cuda/numba/cuda/memory_management/memsys.cuh +5 -0
  114. numba_cuda/numba/cuda/memory_management/nrt.cu +5 -0
  115. numba_cuda/numba/cuda/memory_management/nrt.cuh +5 -0
  116. numba_cuda/numba/cuda/memory_management/nrt.py +48 -18
  117. numba_cuda/numba/cuda/misc/findlib.py +75 -0
  118. numba_cuda/numba/cuda/models.py +12 -1
  119. numba_cuda/numba/cuda/np/npdatetime_helpers.py +217 -0
  120. numba_cuda/numba/cuda/np/npyfuncs.py +1807 -0
  121. numba_cuda/numba/cuda/np/numpy_support.py +553 -0
  122. numba_cuda/numba/cuda/np/ufunc/ufuncbuilder.py +59 -0
  123. numba_cuda/numba/cuda/nvvmutils.py +4 -1
  124. numba_cuda/numba/cuda/printimpl.py +15 -1
  125. numba_cuda/numba/cuda/random.py +4 -1
  126. numba_cuda/numba/cuda/reshape_funcs.cu +5 -0
  127. numba_cuda/numba/cuda/serialize.py +4 -1
  128. numba_cuda/numba/cuda/simulator/__init__.py +4 -1
  129. numba_cuda/numba/cuda/simulator/_internal/__init__.py +3 -0
  130. numba_cuda/numba/cuda/simulator/_internal/cuda_bf16.py +2 -0
  131. numba_cuda/numba/cuda/simulator/api.py +4 -1
  132. numba_cuda/numba/cuda/simulator/bf16.py +3 -0
  133. numba_cuda/numba/cuda/simulator/compiler.py +7 -0
  134. numba_cuda/numba/cuda/simulator/cudadrv/__init__.py +3 -0
  135. numba_cuda/numba/cuda/simulator/cudadrv/devicearray.py +4 -1
  136. numba_cuda/numba/cuda/simulator/cudadrv/devices.py +3 -0
  137. numba_cuda/numba/cuda/simulator/cudadrv/driver.py +3 -0
  138. numba_cuda/numba/cuda/simulator/cudadrv/drvapi.py +3 -0
  139. numba_cuda/numba/cuda/simulator/cudadrv/dummyarray.py +3 -0
  140. numba_cuda/numba/cuda/simulator/cudadrv/error.py +4 -0
  141. numba_cuda/numba/cuda/simulator/cudadrv/libs.py +4 -0
  142. numba_cuda/numba/cuda/simulator/cudadrv/linkable_code.py +4 -0
  143. numba_cuda/numba/cuda/simulator/cudadrv/nvrtc.py +3 -0
  144. numba_cuda/numba/cuda/simulator/cudadrv/nvvm.py +3 -0
  145. numba_cuda/numba/cuda/simulator/cudadrv/runtime.py +3 -0
  146. numba_cuda/numba/cuda/simulator/dispatcher.py +4 -0
  147. numba_cuda/numba/cuda/simulator/kernel.py +3 -0
  148. numba_cuda/numba/cuda/simulator/kernelapi.py +4 -1
  149. numba_cuda/numba/cuda/simulator/memory_management/__init__.py +3 -0
  150. numba_cuda/numba/cuda/simulator/memory_management/nrt.py +17 -2
  151. numba_cuda/numba/cuda/simulator/reduction.py +3 -0
  152. numba_cuda/numba/cuda/simulator/vector_types.py +3 -0
  153. numba_cuda/numba/cuda/simulator_init.py +3 -0
  154. numba_cuda/numba/cuda/stubs.py +3 -0
  155. numba_cuda/numba/cuda/target.py +38 -17
  156. numba_cuda/numba/cuda/testing.py +7 -19
  157. numba_cuda/numba/cuda/tests/__init__.py +4 -1
  158. numba_cuda/numba/cuda/tests/cloudpickle_main_class.py +9 -0
  159. numba_cuda/numba/cuda/tests/complex_usecases.py +3 -0
  160. numba_cuda/numba/cuda/tests/core/serialize_usecases.py +3 -0
  161. numba_cuda/numba/cuda/tests/core/test_itanium_mangler.py +3 -0
  162. numba_cuda/numba/cuda/tests/core/test_serialize.py +7 -4
  163. numba_cuda/numba/cuda/tests/cudadrv/__init__.py +3 -0
  164. numba_cuda/numba/cuda/tests/cudadrv/test_array_attr.py +3 -0
  165. numba_cuda/numba/cuda/tests/cudadrv/test_context_stack.py +3 -0
  166. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_array_slicing.py +3 -0
  167. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_auto_context.py +3 -0
  168. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_devicerecord.py +4 -1
  169. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_driver.py +3 -0
  170. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_libraries.py +4 -1
  171. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_memory.py +3 -0
  172. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_ndarray.py +3 -0
  173. numba_cuda/numba/cuda/tests/cudadrv/test_deallocations.py +4 -1
  174. numba_cuda/numba/cuda/tests/cudadrv/test_detect.py +9 -3
  175. numba_cuda/numba/cuda/tests/cudadrv/test_emm_plugins.py +4 -1
  176. numba_cuda/numba/cuda/tests/cudadrv/test_events.py +3 -0
  177. numba_cuda/numba/cuda/tests/cudadrv/test_host_alloc.py +3 -0
  178. numba_cuda/numba/cuda/tests/cudadrv/test_init.py +3 -0
  179. numba_cuda/numba/cuda/tests/cudadrv/test_inline_ptx.py +3 -0
  180. numba_cuda/numba/cuda/tests/cudadrv/test_is_fp16.py +3 -0
  181. numba_cuda/numba/cuda/tests/cudadrv/test_linker.py +21 -2
  182. numba_cuda/numba/cuda/tests/cudadrv/test_managed_alloc.py +3 -0
  183. numba_cuda/numba/cuda/tests/cudadrv/test_module_callbacks.py +5 -1
  184. numba_cuda/numba/cuda/tests/cudadrv/test_nvjitlink.py +4 -1
  185. numba_cuda/numba/cuda/tests/cudadrv/test_nvrtc.py +3 -0
  186. numba_cuda/numba/cuda/tests/cudadrv/test_nvvm_driver.py +3 -0
  187. numba_cuda/numba/cuda/tests/cudadrv/test_pinned.py +3 -0
  188. numba_cuda/numba/cuda/tests/cudadrv/test_profiler.py +3 -0
  189. numba_cuda/numba/cuda/tests/cudadrv/test_ptds.py +4 -1
  190. numba_cuda/numba/cuda/tests/cudadrv/test_reset_device.py +3 -0
  191. numba_cuda/numba/cuda/tests/cudadrv/test_runtime.py +3 -0
  192. numba_cuda/numba/cuda/tests/cudadrv/test_select_device.py +3 -0
  193. numba_cuda/numba/cuda/tests/cudadrv/test_streams.py +3 -0
  194. numba_cuda/numba/cuda/tests/cudapy/__init__.py +3 -0
  195. numba_cuda/numba/cuda/tests/cudapy/cache_usecases.py +3 -0
  196. numba_cuda/numba/cuda/tests/cudapy/cache_with_cpu_usecases.py +3 -0
  197. numba_cuda/numba/cuda/tests/cudapy/cg_cache_usecases.py +3 -0
  198. numba_cuda/numba/cuda/tests/cudapy/extensions_usecases.py +4 -1
  199. numba_cuda/numba/cuda/tests/cudapy/recursion_usecases.py +3 -0
  200. numba_cuda/numba/cuda/tests/cudapy/test_alignment.py +3 -0
  201. numba_cuda/numba/cuda/tests/cudapy/test_array.py +5 -1
  202. numba_cuda/numba/cuda/tests/cudapy/test_array_alignment.py +3 -0
  203. numba_cuda/numba/cuda/tests/cudapy/test_array_args.py +3 -0
  204. numba_cuda/numba/cuda/tests/cudapy/test_array_methods.py +3 -0
  205. numba_cuda/numba/cuda/tests/cudapy/test_atomics.py +4 -1
  206. numba_cuda/numba/cuda/tests/cudapy/test_bfloat16.py +542 -2
  207. numba_cuda/numba/cuda/tests/cudapy/test_bfloat16_bindings.py +84 -1
  208. numba_cuda/numba/cuda/tests/cudapy/test_blackscholes.py +3 -0
  209. numba_cuda/numba/cuda/tests/cudapy/test_boolean.py +3 -0
  210. numba_cuda/numba/cuda/tests/cudapy/test_caching.py +4 -3
  211. numba_cuda/numba/cuda/tests/cudapy/test_casting.py +3 -0
  212. numba_cuda/numba/cuda/tests/cudapy/test_cffi.py +3 -0
  213. numba_cuda/numba/cuda/tests/cudapy/test_compiler.py +3 -0
  214. numba_cuda/numba/cuda/tests/cudapy/test_complex.py +4 -1
  215. numba_cuda/numba/cuda/tests/cudapy/test_complex_kernel.py +3 -0
  216. numba_cuda/numba/cuda/tests/cudapy/test_const_string.py +3 -0
  217. numba_cuda/numba/cuda/tests/cudapy/test_constmem.py +4 -1
  218. numba_cuda/numba/cuda/tests/cudapy/test_cooperative_groups.py +5 -3
  219. numba_cuda/numba/cuda/tests/cudapy/test_copy_propagate.py +130 -0
  220. numba_cuda/numba/cuda/tests/cudapy/test_cuda_array_interface.py +3 -0
  221. numba_cuda/numba/cuda/tests/cudapy/test_cuda_jit_no_types.py +3 -0
  222. numba_cuda/numba/cuda/tests/cudapy/test_datetime.py +4 -1
  223. numba_cuda/numba/cuda/tests/cudapy/test_debug.py +4 -1
  224. numba_cuda/numba/cuda/tests/cudapy/test_debuginfo.py +314 -3
  225. numba_cuda/numba/cuda/tests/cudapy/test_debuginfo_types.py +4 -1
  226. numba_cuda/numba/cuda/tests/cudapy/test_device_func.py +3 -0
  227. numba_cuda/numba/cuda/tests/cudapy/test_dispatcher.py +4 -1
  228. numba_cuda/numba/cuda/tests/cudapy/test_enums.py +3 -0
  229. numba_cuda/numba/cuda/tests/cudapy/test_errors.py +4 -1
  230. numba_cuda/numba/cuda/tests/cudapy/test_exception.py +4 -1
  231. numba_cuda/numba/cuda/tests/cudapy/test_extending.py +5 -1
  232. numba_cuda/numba/cuda/tests/cudapy/test_fastmath.py +3 -0
  233. numba_cuda/numba/cuda/tests/cudapy/test_forall.py +3 -0
  234. numba_cuda/numba/cuda/tests/cudapy/test_freevar.py +3 -0
  235. numba_cuda/numba/cuda/tests/cudapy/test_frexp_ldexp.py +3 -0
  236. numba_cuda/numba/cuda/tests/cudapy/test_globals.py +3 -0
  237. numba_cuda/numba/cuda/tests/cudapy/test_gufunc.py +3 -0
  238. numba_cuda/numba/cuda/tests/cudapy/test_gufunc_scalar.py +3 -0
  239. numba_cuda/numba/cuda/tests/cudapy/test_gufunc_scheduling.py +3 -0
  240. numba_cuda/numba/cuda/tests/cudapy/test_idiv.py +3 -0
  241. numba_cuda/numba/cuda/tests/cudapy/test_inline.py +21 -8
  242. numba_cuda/numba/cuda/tests/cudapy/test_inspect.py +3 -0
  243. numba_cuda/numba/cuda/tests/cudapy/test_intrinsics.py +3 -0
  244. numba_cuda/numba/cuda/tests/cudapy/test_ipc.py +3 -0
  245. numba_cuda/numba/cuda/tests/cudapy/test_ir_utils.py +13 -37
  246. numba_cuda/numba/cuda/tests/cudapy/test_iterators.py +3 -0
  247. numba_cuda/numba/cuda/tests/cudapy/test_lang.py +3 -0
  248. numba_cuda/numba/cuda/tests/cudapy/test_laplace.py +4 -1
  249. numba_cuda/numba/cuda/tests/cudapy/test_libdevice.py +3 -0
  250. numba_cuda/numba/cuda/tests/cudapy/test_lineinfo.py +3 -0
  251. numba_cuda/numba/cuda/tests/cudapy/test_localmem.py +3 -0
  252. numba_cuda/numba/cuda/tests/cudapy/test_mandel.py +3 -0
  253. numba_cuda/numba/cuda/tests/cudapy/test_math.py +4 -1
  254. numba_cuda/numba/cuda/tests/cudapy/test_matmul.py +4 -1
  255. numba_cuda/numba/cuda/tests/cudapy/test_minmax.py +3 -0
  256. numba_cuda/numba/cuda/tests/cudapy/test_montecarlo.py +3 -0
  257. numba_cuda/numba/cuda/tests/cudapy/test_multigpu.py +3 -0
  258. numba_cuda/numba/cuda/tests/cudapy/test_multiprocessing.py +3 -0
  259. numba_cuda/numba/cuda/tests/cudapy/test_multithreads.py +3 -0
  260. numba_cuda/numba/cuda/tests/cudapy/test_nondet.py +3 -0
  261. numba_cuda/numba/cuda/tests/cudapy/test_operator.py +4 -1
  262. numba_cuda/numba/cuda/tests/cudapy/test_optimization.py +3 -0
  263. numba_cuda/numba/cuda/tests/cudapy/test_overload.py +3 -0
  264. numba_cuda/numba/cuda/tests/cudapy/test_powi.py +3 -0
  265. numba_cuda/numba/cuda/tests/cudapy/test_print.py +23 -0
  266. numba_cuda/numba/cuda/tests/cudapy/test_py2_div_issue.py +3 -0
  267. numba_cuda/numba/cuda/tests/cudapy/test_random.py +3 -0
  268. numba_cuda/numba/cuda/tests/cudapy/test_record_dtype.py +4 -1
  269. numba_cuda/numba/cuda/tests/cudapy/test_recursion.py +3 -0
  270. numba_cuda/numba/cuda/tests/cudapy/test_reduction.py +4 -1
  271. numba_cuda/numba/cuda/tests/cudapy/test_retrieve_autoconverted_arrays.py +3 -0
  272. numba_cuda/numba/cuda/tests/cudapy/test_serialize.py +4 -1
  273. numba_cuda/numba/cuda/tests/cudapy/test_slicing.py +3 -0
  274. numba_cuda/numba/cuda/tests/cudapy/test_sm.py +4 -1
  275. numba_cuda/numba/cuda/tests/cudapy/test_sm_creation.py +3 -0
  276. numba_cuda/numba/cuda/tests/cudapy/test_ssa.py +453 -0
  277. numba_cuda/numba/cuda/tests/cudapy/test_stream_api.py +3 -0
  278. numba_cuda/numba/cuda/tests/cudapy/test_sync.py +4 -1
  279. numba_cuda/numba/cuda/tests/cudapy/test_transpose.py +3 -0
  280. numba_cuda/numba/cuda/tests/cudapy/test_typeinfer.py +538 -0
  281. numba_cuda/numba/cuda/tests/cudapy/test_ufuncs.py +266 -2
  282. numba_cuda/numba/cuda/tests/cudapy/test_userexc.py +4 -1
  283. numba_cuda/numba/cuda/tests/cudapy/test_vector_type.py +4 -1
  284. numba_cuda/numba/cuda/tests/cudapy/test_vectorize.py +3 -0
  285. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_complex.py +3 -0
  286. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_decor.py +115 -6
  287. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_device.py +3 -0
  288. numba_cuda/numba/cuda/tests/cudapy/test_vectorize_scalar_arg.py +3 -0
  289. numba_cuda/numba/cuda/tests/cudapy/test_warning.py +4 -1
  290. numba_cuda/numba/cuda/tests/cudapy/test_warp_ops.py +4 -1
  291. numba_cuda/numba/cuda/tests/cudasim/__init__.py +3 -0
  292. numba_cuda/numba/cuda/tests/cudasim/support.py +3 -0
  293. numba_cuda/numba/cuda/tests/cudasim/test_cudasim_issues.py +3 -0
  294. numba_cuda/numba/cuda/tests/data/__init__.py +2 -0
  295. numba_cuda/numba/cuda/tests/data/cta_barrier.cu +5 -0
  296. numba_cuda/numba/cuda/tests/data/cuda_include.cu +5 -0
  297. numba_cuda/numba/cuda/tests/data/error.cu +5 -0
  298. numba_cuda/numba/cuda/tests/data/include/add.cuh +5 -0
  299. numba_cuda/numba/cuda/tests/data/jitlink.cu +5 -0
  300. numba_cuda/numba/cuda/tests/data/warn.cu +5 -0
  301. numba_cuda/numba/cuda/tests/doc_examples/__init__.py +3 -0
  302. numba_cuda/numba/cuda/tests/doc_examples/ffi/__init__.py +2 -0
  303. numba_cuda/numba/cuda/tests/doc_examples/ffi/functions.cu +5 -0
  304. numba_cuda/numba/cuda/tests/doc_examples/ffi/include/mul.cuh +5 -0
  305. numba_cuda/numba/cuda/tests/doc_examples/ffi/saxpy.cu +5 -0
  306. numba_cuda/numba/cuda/tests/doc_examples/test_cg.py +3 -2
  307. numba_cuda/numba/cuda/tests/doc_examples/test_cpointer.py +3 -0
  308. numba_cuda/numba/cuda/tests/doc_examples/test_cpu_gpu_compat.py +3 -0
  309. numba_cuda/numba/cuda/tests/doc_examples/test_ffi.py +6 -2
  310. numba_cuda/numba/cuda/tests/doc_examples/test_laplace.py +3 -2
  311. numba_cuda/numba/cuda/tests/doc_examples/test_matmul.py +3 -0
  312. numba_cuda/numba/cuda/tests/doc_examples/test_montecarlo.py +3 -0
  313. numba_cuda/numba/cuda/tests/doc_examples/test_random.py +3 -0
  314. numba_cuda/numba/cuda/tests/doc_examples/test_reduction.py +3 -0
  315. numba_cuda/numba/cuda/tests/doc_examples/test_sessionize.py +3 -2
  316. numba_cuda/numba/cuda/tests/doc_examples/test_ufunc.py +3 -0
  317. numba_cuda/numba/cuda/tests/doc_examples/test_vecadd.py +3 -0
  318. numba_cuda/numba/cuda/tests/enum_usecases.py +3 -0
  319. numba_cuda/numba/cuda/tests/nocuda/__init__.py +3 -0
  320. numba_cuda/numba/cuda/tests/nocuda/test_dummyarray.py +3 -0
  321. numba_cuda/numba/cuda/tests/nocuda/test_function_resolution.py +3 -0
  322. numba_cuda/numba/cuda/tests/nocuda/test_import.py +6 -1
  323. numba_cuda/numba/cuda/tests/nocuda/test_library_lookup.py +27 -12
  324. numba_cuda/numba/cuda/tests/nocuda/test_nvvm.py +3 -0
  325. numba_cuda/numba/cuda/tests/nrt/__init__.py +3 -0
  326. numba_cuda/numba/cuda/tests/nrt/test_nrt.py +5 -1
  327. numba_cuda/numba/cuda/tests/nrt/test_nrt_refct.py +3 -0
  328. numba_cuda/numba/cuda/tests/support.py +58 -15
  329. numba_cuda/numba/cuda/tests/test_binary_generation/Makefile +3 -0
  330. numba_cuda/numba/cuda/tests/test_binary_generation/generate_raw_ltoir.py +2 -1
  331. numba_cuda/numba/cuda/tests/test_binary_generation/nrt_extern.cu +5 -0
  332. numba_cuda/numba/cuda/tests/test_binary_generation/test_device_functions.cu +5 -0
  333. numba_cuda/numba/cuda/tests/test_binary_generation/undefined_extern.cu +5 -0
  334. numba_cuda/numba/cuda/tests/test_tracing.py +200 -0
  335. numba_cuda/numba/cuda/types.py +59 -0
  336. numba_cuda/numba/cuda/typing/__init__.py +12 -1
  337. numba_cuda/numba/cuda/typing/cffi_utils.py +55 -0
  338. numba_cuda/numba/cuda/typing/context.py +751 -0
  339. numba_cuda/numba/cuda/typing/enumdecl.py +74 -0
  340. numba_cuda/numba/cuda/typing/npydecl.py +658 -0
  341. numba_cuda/numba/cuda/typing/templates.py +10 -14
  342. numba_cuda/numba/cuda/ufuncs.py +6 -3
  343. numba_cuda/numba/cuda/utils.py +9 -112
  344. numba_cuda/numba/cuda/vector_types.py +3 -0
  345. numba_cuda/numba/cuda/vectorizers.py +3 -0
  346. {numba_cuda-0.19.0.dist-info → numba_cuda-0.20.0.dist-info}/METADATA +6 -2
  347. numba_cuda-0.20.0.dist-info/RECORD +357 -0
  348. {numba_cuda-0.19.0.dist-info → numba_cuda-0.20.0.dist-info}/licenses/LICENSE +1 -0
  349. numba_cuda-0.20.0.dist-info/licenses/LICENSE.numba +24 -0
  350. numba_cuda/numba/cuda/tests/cudadrv/test_mvc.py +0 -57
  351. numba_cuda-0.19.0.dist-info/RECORD +0 -301
  352. {numba_cuda-0.19.0.dist-info → numba_cuda-0.20.0.dist-info}/WHEEL +0 -0
  353. {numba_cuda-0.19.0.dist-info → numba_cuda-0.20.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1948 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: BSD-2-Clause
3
+
4
+ # ========================================================================== #
5
+ # #
6
+ # IMPORTANT: Before modifying type inference, it is important to port the #
7
+ # following tests from `numba.tests.test_typeinfer`: #
8
+ # #
9
+ # - TestArgRetCasting #
10
+ # - TestUnifyUseCases #
11
+ # - TestMiscIssues, with exceptions: #
12
+ # - test_list_unify{1,2}: Lists not supported #
13
+ # - test_load_fast_and_clear*: Uses list comprehensions #
14
+ # #
15
+ # ========================================================================== #
16
+ """
17
+ Type inference base on CPA.
18
+ The algorithm guarantees monotonic growth of type-sets for each variable.
19
+
20
+ Steps:
21
+ 1. seed initial types
22
+ 2. build constraints
23
+ 3. propagate constraints
24
+ 4. unify types
25
+
26
+ Constraint propagation is precise and does not regret (no backtracing).
27
+ Constraints push types forward following the dataflow.
28
+ """
29
+
30
+ import logging
31
+ import operator
32
+ import contextlib
33
+ import itertools
34
+ from pprint import pprint
35
+ from collections import OrderedDict, defaultdict
36
+ from functools import reduce
37
+
38
+ from numba.core import types, utils, typing, config, ir
39
+ from numba.core.typing.templates import Signature
40
+ from numba.core.errors import (
41
+ TypingError,
42
+ UntypedAttributeError,
43
+ new_error_context,
44
+ termcolor,
45
+ UnsupportedError,
46
+ ForceLiteralArg,
47
+ CompilerError,
48
+ NumbaValueError,
49
+ )
50
+ from numba.core.funcdesc import qualifying_prefix
51
+ from numba.core.typeconv import Conversion
52
+
53
+ _logger = logging.getLogger(__name__)
54
+
55
+
56
+ class NOTSET:
57
+ pass
58
+
59
+
60
+ # terminal color markup
61
+ _termcolor = termcolor()
62
+
63
+
64
+ class TypeVar(object):
65
+ def __init__(self, context, var):
66
+ self.context = context
67
+ self.var = var
68
+ self.type = None
69
+ self.locked = False
70
+ # Stores source location of first definition
71
+ self.define_loc = None
72
+ # Qualifiers
73
+ self.literal_value = NOTSET
74
+
75
+ def add_type(self, tp, loc):
76
+ assert isinstance(tp, types.Type), type(tp)
77
+ # Special case for _undef_var.
78
+ # If the typevar is the _undef_var, use the incoming type directly.
79
+ if self.type is types._undef_var:
80
+ self.type = tp
81
+ return self.type
82
+
83
+ if self.locked:
84
+ if tp != self.type:
85
+ if self.context.can_convert(tp, self.type) is None:
86
+ msg = "No conversion from %s to %s for '%s', defined at %s"
87
+ raise TypingError(
88
+ msg % (tp, self.type, self.var, self.define_loc),
89
+ loc=loc,
90
+ )
91
+ else:
92
+ if self.type is not None:
93
+ unified = self.context.unify_pairs(self.type, tp)
94
+ if unified is None:
95
+ msg = "Cannot unify %s and %s for '%s', defined at %s"
96
+ raise TypingError(
97
+ msg % (self.type, tp, self.var, self.define_loc),
98
+ loc=self.define_loc,
99
+ )
100
+ else:
101
+ # First time definition
102
+ unified = tp
103
+ self.define_loc = loc
104
+
105
+ self.type = unified
106
+
107
+ return self.type
108
+
109
+ def lock(self, tp, loc, literal_value=NOTSET):
110
+ assert isinstance(tp, types.Type), type(tp)
111
+
112
+ if self.locked:
113
+ msg = (
114
+ "Invalid reassignment of a type-variable detected, type "
115
+ "variables are locked according to the user provided "
116
+ "function signature or from an ir.Const node. This is a "
117
+ "bug! Type={}. {}"
118
+ ).format(tp, self.type)
119
+ raise CompilerError(msg, loc)
120
+
121
+ # If there is already a type, ensure we can convert it to the
122
+ # locked type.
123
+ if (
124
+ self.type is not None
125
+ and self.context.can_convert(self.type, tp) is None
126
+ ):
127
+ raise TypingError(
128
+ "No conversion from %s to %s for "
129
+ "'%s'" % (tp, self.type, self.var),
130
+ loc=loc,
131
+ )
132
+
133
+ self.type = tp
134
+ self.locked = True
135
+ if self.define_loc is None:
136
+ self.define_loc = loc
137
+ self.literal_value = literal_value
138
+
139
+ def union(self, other, loc):
140
+ if other.type is not None:
141
+ self.add_type(other.type, loc=loc)
142
+
143
+ return self.type
144
+
145
+ def __repr__(self):
146
+ return "%s := %s" % (self.var, self.type or "<undecided>")
147
+
148
+ @property
149
+ def defined(self):
150
+ return self.type is not None
151
+
152
+ def get(self):
153
+ return (self.type,) if self.type is not None else ()
154
+
155
+ def getone(self):
156
+ if self.type is None:
157
+ raise TypingError("Undecided type {}".format(self))
158
+ return self.type
159
+
160
+ def __len__(self):
161
+ return 1 if self.type is not None else 0
162
+
163
+
164
+ class ConstraintNetwork(object):
165
+ """
166
+ TODO: It is possible to optimize constraint propagation to consider only
167
+ dirty type variables.
168
+ """
169
+
170
+ def __init__(self):
171
+ self.constraints = []
172
+
173
+ def append(self, constraint):
174
+ self.constraints.append(constraint)
175
+
176
+ def propagate(self, typeinfer):
177
+ """
178
+ Execute all constraints. Errors are caught and returned as a list.
179
+ This allows progressing even though some constraints may fail
180
+ due to lack of information
181
+ (e.g. imprecise types such as List(undefined)).
182
+ """
183
+ errors = []
184
+ for constraint in self.constraints:
185
+ loc = constraint.loc
186
+ with typeinfer.warnings.catch_warnings(
187
+ filename=loc.filename, lineno=loc.line
188
+ ):
189
+ try:
190
+ constraint(typeinfer)
191
+ except ForceLiteralArg as e:
192
+ errors.append(e)
193
+ except TypingError as e:
194
+ _logger.debug("captured error", exc_info=e)
195
+ new_exc = TypingError(
196
+ str(e),
197
+ loc=constraint.loc,
198
+ highlighting=False,
199
+ )
200
+ errors.append(utils.chain_exception(new_exc, e))
201
+
202
+ return errors
203
+
204
+
205
+ class Propagate(object):
206
+ """
207
+ A simple constraint for direct propagation of types for assignments.
208
+ """
209
+
210
+ def __init__(self, dst, src, loc):
211
+ self.dst = dst
212
+ self.src = src
213
+ self.loc = loc
214
+
215
+ def __call__(self, typeinfer):
216
+ with new_error_context(
217
+ "typing of assignment at {0}", self.loc, loc=self.loc
218
+ ):
219
+ typeinfer.copy_type(self.src, self.dst, loc=self.loc)
220
+ # If `dst` is refined, notify us
221
+ typeinfer.refine_map[self.dst] = self
222
+
223
+ def refine(self, typeinfer, target_type):
224
+ # Do not back-propagate to locked variables (e.g. constants)
225
+ assert target_type.is_precise()
226
+ typeinfer.add_type(
227
+ self.src, target_type, unless_locked=True, loc=self.loc
228
+ )
229
+
230
+
231
+ class ArgConstraint(object):
232
+ def __init__(self, dst, src, loc):
233
+ self.dst = dst
234
+ self.src = src
235
+ self.loc = loc
236
+
237
+ def __call__(self, typeinfer):
238
+ with new_error_context("typing of argument at {0}", self.loc):
239
+ typevars = typeinfer.typevars
240
+ src = typevars[self.src]
241
+ if not src.defined:
242
+ return
243
+ ty = src.getone()
244
+ if isinstance(ty, types.Omitted):
245
+ ty = typeinfer.context.resolve_value_type_prefer_literal(
246
+ ty.value,
247
+ )
248
+ if not ty.is_precise():
249
+ raise TypingError("non-precise type {}".format(ty))
250
+ typeinfer.add_type(self.dst, ty, loc=self.loc)
251
+
252
+
253
+ class BuildTupleConstraint(object):
254
+ def __init__(self, target, items, loc):
255
+ self.target = target
256
+ self.items = items
257
+ self.loc = loc
258
+
259
+ def __call__(self, typeinfer):
260
+ with new_error_context("typing of tuple at {0}", self.loc):
261
+ typevars = typeinfer.typevars
262
+ tsets = [typevars[i.name].get() for i in self.items]
263
+ for vals in itertools.product(*tsets):
264
+ if vals and all(vals[0] == v for v in vals):
265
+ tup = types.UniTuple(dtype=vals[0], count=len(vals))
266
+ else:
267
+ # empty tuples fall here as well
268
+ tup = types.Tuple(vals)
269
+ assert tup.is_precise()
270
+ typeinfer.add_type(self.target, tup, loc=self.loc)
271
+
272
+
273
+ class _BuildContainerConstraint(object):
274
+ def __init__(self, target, items, loc):
275
+ self.target = target
276
+ self.items = items
277
+ self.loc = loc
278
+
279
+ def __call__(self, typeinfer):
280
+ with new_error_context(
281
+ "typing of {0} at {1}", self.container_type, self.loc
282
+ ):
283
+ typevars = typeinfer.typevars
284
+ tsets = [typevars[i.name].get() for i in self.items]
285
+ if not tsets:
286
+ typeinfer.add_type(
287
+ self.target,
288
+ self.container_type(types.undefined),
289
+ loc=self.loc,
290
+ )
291
+ else:
292
+ for typs in itertools.product(*tsets):
293
+ unified = typeinfer.context.unify_types(*typs)
294
+ if unified is not None:
295
+ typeinfer.add_type(
296
+ self.target,
297
+ self.container_type(unified),
298
+ loc=self.loc,
299
+ )
300
+
301
+
302
+ class BuildListConstraint(_BuildContainerConstraint):
303
+ def __init__(self, target, items, loc):
304
+ self.target = target
305
+ self.items = items
306
+ self.loc = loc
307
+
308
+ def __call__(self, typeinfer):
309
+ with new_error_context("typing of {0} at {1}", types.List, self.loc):
310
+ typevars = typeinfer.typevars
311
+ tsets = [typevars[i.name].get() for i in self.items]
312
+ if not tsets:
313
+ typeinfer.add_type(
314
+ self.target, types.List(types.undefined), loc=self.loc
315
+ )
316
+ else:
317
+ for typs in itertools.product(*tsets):
318
+ unified = typeinfer.context.unify_types(*typs)
319
+ if unified is not None:
320
+ # pull out literals if available
321
+ islit = [isinstance(x, types.Literal) for x in typs]
322
+ iv = None
323
+ if all(islit):
324
+ iv = [x.literal_value for x in typs]
325
+ typeinfer.add_type(
326
+ self.target,
327
+ types.List(unified, initial_value=iv),
328
+ loc=self.loc,
329
+ )
330
+ else:
331
+ typeinfer.add_type(
332
+ self.target, types.LiteralList(typs), loc=self.loc
333
+ )
334
+
335
+
336
+ class BuildSetConstraint(_BuildContainerConstraint):
337
+ container_type = types.Set
338
+
339
+
340
+ class BuildMapConstraint(object):
341
+ def __init__(self, target, items, special_value, value_indexes, loc):
342
+ self.target = target
343
+ self.items = items
344
+ self.special_value = special_value
345
+ self.value_indexes = value_indexes
346
+ self.loc = loc
347
+
348
+ def __call__(self, typeinfer):
349
+ with new_error_context("typing of dict at {0}", self.loc):
350
+ typevars = typeinfer.typevars
351
+
352
+ # figure out what sort of dict is being dealt with
353
+ tsets = [
354
+ (typevars[k.name].getone(), typevars[v.name].getone())
355
+ for k, v in self.items
356
+ ]
357
+
358
+ if not tsets:
359
+ typeinfer.add_type(
360
+ self.target,
361
+ types.DictType(
362
+ types.undefined, types.undefined, self.special_value
363
+ ),
364
+ loc=self.loc,
365
+ )
366
+ else:
367
+ # all the info is known about the dict, if its
368
+ # str keys -> random heterogeneous values treat as literalstrkey
369
+ ktys = [x[0] for x in tsets]
370
+ vtys = [x[1] for x in tsets]
371
+ strkey = all([isinstance(x, types.StringLiteral) for x in ktys])
372
+ literalvty = all([isinstance(x, types.Literal) for x in vtys])
373
+ vt0 = types.unliteral(vtys[0])
374
+
375
+ # homogeneous values comes in the form of being able to cast
376
+ # all the other values in the ctor to the type of the first.
377
+ # The order is important as `typed.Dict` takes it's type from
378
+ # the first element.
379
+ def check(other):
380
+ conv = typeinfer.context.can_convert(other, vt0)
381
+ return conv is not None and conv < Conversion.unsafe
382
+
383
+ homogeneous = all([check(types.unliteral(x)) for x in vtys])
384
+
385
+ # Special cases:
386
+ # Single key:value in ctor, key is str, value is an otherwise
387
+ # illegal container type, e.g. LiteralStrKeyDict or
388
+ # List, there's no way to put this into a typed.Dict, so make it
389
+ # a LiteralStrKeyDict, same goes for LiteralList.
390
+ if len(vtys) == 1:
391
+ valty = vtys[0]
392
+ if isinstance(
393
+ valty,
394
+ (
395
+ types.LiteralStrKeyDict,
396
+ types.List,
397
+ types.LiteralList,
398
+ ),
399
+ ):
400
+ homogeneous = False
401
+
402
+ if strkey and not homogeneous:
403
+ resolved_dict = {x: y for x, y in zip(ktys, vtys)}
404
+ ty = types.LiteralStrKeyDict(
405
+ resolved_dict, self.value_indexes
406
+ )
407
+ typeinfer.add_type(self.target, ty, loc=self.loc)
408
+ else:
409
+ init_value = self.special_value if literalvty else None
410
+ key_type, value_type = tsets[0]
411
+ typeinfer.add_type(
412
+ self.target,
413
+ types.DictType(key_type, value_type, init_value),
414
+ loc=self.loc,
415
+ )
416
+
417
+
418
+ class ExhaustIterConstraint(object):
419
+ def __init__(self, target, count, iterator, loc):
420
+ self.target = target
421
+ self.count = count
422
+ self.iterator = iterator
423
+ self.loc = loc
424
+
425
+ def __call__(self, typeinfer):
426
+ with new_error_context("typing of exhaust iter at {0}", self.loc):
427
+ typevars = typeinfer.typevars
428
+ for tp in typevars[self.iterator.name].get():
429
+ # unpack optional
430
+ tp = tp.type if isinstance(tp, types.Optional) else tp
431
+ if isinstance(tp, types.BaseTuple):
432
+ if len(tp) == self.count:
433
+ assert tp.is_precise()
434
+ typeinfer.add_type(self.target, tp, loc=self.loc)
435
+ break
436
+ else:
437
+ msg = (
438
+ f"wrong tuple length for {self.iterator.name}: ",
439
+ f"expected {self.count}, got {len(tp)}",
440
+ )
441
+ raise NumbaValueError(msg)
442
+ elif isinstance(tp, types.IterableType):
443
+ tup = types.UniTuple(
444
+ dtype=tp.iterator_type.yield_type, count=self.count
445
+ )
446
+ assert tup.is_precise()
447
+ typeinfer.add_type(self.target, tup, loc=self.loc)
448
+ break
449
+ else:
450
+ raise TypingError(
451
+ "failed to unpack {}".format(tp), loc=self.loc
452
+ )
453
+
454
+
455
+ class PairFirstConstraint(object):
456
+ def __init__(self, target, pair, loc):
457
+ self.target = target
458
+ self.pair = pair
459
+ self.loc = loc
460
+
461
+ def __call__(self, typeinfer):
462
+ with new_error_context("typing of pair-first at {0}", self.loc):
463
+ typevars = typeinfer.typevars
464
+ for tp in typevars[self.pair.name].get():
465
+ if not isinstance(tp, types.Pair):
466
+ # XXX is this an error?
467
+ continue
468
+ assert (
469
+ isinstance(tp.first_type, types.UndefinedFunctionType)
470
+ or tp.first_type.is_precise()
471
+ )
472
+ typeinfer.add_type(self.target, tp.first_type, loc=self.loc)
473
+
474
+
475
+ class PairSecondConstraint(object):
476
+ def __init__(self, target, pair, loc):
477
+ self.target = target
478
+ self.pair = pair
479
+ self.loc = loc
480
+
481
+ def __call__(self, typeinfer):
482
+ with new_error_context("typing of pair-second at {0}", self.loc):
483
+ typevars = typeinfer.typevars
484
+ for tp in typevars[self.pair.name].get():
485
+ if not isinstance(tp, types.Pair):
486
+ # XXX is this an error?
487
+ continue
488
+ assert tp.second_type.is_precise()
489
+ typeinfer.add_type(self.target, tp.second_type, loc=self.loc)
490
+
491
+
492
+ class StaticGetItemConstraint(object):
493
+ def __init__(self, target, value, index, index_var, loc):
494
+ self.target = target
495
+ self.value = value
496
+ self.index = index
497
+ if index_var is not None:
498
+ self.fallback = IntrinsicCallConstraint(
499
+ target, operator.getitem, (value, index_var), {}, None, loc
500
+ )
501
+ else:
502
+ self.fallback = None
503
+ self.loc = loc
504
+
505
+ def __call__(self, typeinfer):
506
+ with new_error_context("typing of static-get-item at {0}", self.loc):
507
+ typevars = typeinfer.typevars
508
+ for ty in typevars[self.value.name].get():
509
+ sig = typeinfer.context.resolve_static_getitem(
510
+ value=ty,
511
+ index=self.index,
512
+ )
513
+
514
+ if sig is not None:
515
+ itemty = sig.return_type
516
+ # if the itemty is not precise, let it through, unification
517
+ # will catch it and produce a better error message
518
+ typeinfer.add_type(self.target, itemty, loc=self.loc)
519
+ elif self.fallback is not None:
520
+ self.fallback(typeinfer)
521
+
522
+ def get_call_signature(self):
523
+ # The signature is only needed for the fallback case in lowering
524
+ return self.fallback and self.fallback.get_call_signature()
525
+
526
+
527
+ class TypedGetItemConstraint(object):
528
+ def __init__(self, target, value, dtype, index, loc):
529
+ self.target = target
530
+ self.value = value
531
+ self.dtype = dtype
532
+ self.index = index
533
+ self.loc = loc
534
+
535
+ def __call__(self, typeinfer):
536
+ with new_error_context("typing of typed-get-item at {0}", self.loc):
537
+ typevars = typeinfer.typevars
538
+ idx_ty = typevars[self.index.name].get()
539
+ ty = typevars[self.value.name].get()
540
+ self.signature = Signature(self.dtype, ty + idx_ty, None)
541
+ typeinfer.add_type(self.target, self.dtype, loc=self.loc)
542
+
543
+ def get_call_signature(self):
544
+ return self.signature
545
+
546
+
547
+ def fold_arg_vars(typevars, args, vararg, kws):
548
+ """
549
+ Fold and resolve the argument variables of a function call.
550
+ """
551
+ # Fetch all argument types, bail if any is unknown
552
+ n_pos_args = len(args)
553
+ kwds = [kw for (kw, var) in kws]
554
+ argtypes = [typevars[a.name] for a in args]
555
+ argtypes += [typevars[var.name] for (kw, var) in kws]
556
+ if vararg is not None:
557
+ argtypes.append(typevars[vararg.name])
558
+
559
+ if not all(a.defined for a in argtypes):
560
+ return
561
+
562
+ args = tuple(a.getone() for a in argtypes)
563
+
564
+ pos_args = args[:n_pos_args]
565
+ if vararg is not None:
566
+ errmsg = "*args in function call should be a tuple, got %s"
567
+ # Handle constant literal used for `*args`
568
+ if isinstance(args[-1], types.Literal):
569
+ const_val = args[-1].literal_value
570
+ # Is the constant value a tuple?
571
+ if not isinstance(const_val, tuple):
572
+ raise TypingError(errmsg % (args[-1],))
573
+ # Append the elements in the const tuple to the positional args
574
+ pos_args += const_val
575
+ # Handle non-constant
576
+ elif not isinstance(args[-1], types.BaseTuple):
577
+ # Unsuitable for *args
578
+ # (Python is more lenient and accepts all iterables)
579
+ raise TypingError(errmsg % (args[-1],))
580
+ else:
581
+ # Append the elements in the tuple to the positional args
582
+ pos_args += args[-1].types
583
+ # Drop the last arg
584
+ args = args[:-1]
585
+ kw_args = dict(zip(kwds, args[n_pos_args:]))
586
+ return pos_args, kw_args
587
+
588
+
589
+ def _is_array_not_precise(arrty):
590
+ """Check type is array and it is not precise"""
591
+ return isinstance(arrty, types.Array) and not arrty.is_precise()
592
+
593
+
594
+ class CallConstraint(object):
595
+ """Constraint for calling functions.
596
+ Perform case analysis foreach combinations of argument types.
597
+ """
598
+
599
+ signature = None
600
+
601
+ def __init__(self, target, func, args, kws, vararg, loc):
602
+ self.target = target
603
+ self.func = func
604
+ self.args = args
605
+ self.kws = kws or {}
606
+ self.vararg = vararg
607
+ self.loc = loc
608
+
609
+ def __call__(self, typeinfer):
610
+ msg = "typing of call at {0}\n".format(self.loc)
611
+ with new_error_context(msg):
612
+ typevars = typeinfer.typevars
613
+ with new_error_context(
614
+ "resolving caller type: {}".format(self.func)
615
+ ):
616
+ fnty = typevars[self.func].getone()
617
+ with new_error_context("resolving callee type: {0}", fnty):
618
+ self.resolve(typeinfer, typevars, fnty)
619
+
620
+ def resolve(self, typeinfer, typevars, fnty):
621
+ assert fnty
622
+ context = typeinfer.context
623
+
624
+ r = fold_arg_vars(typevars, self.args, self.vararg, self.kws)
625
+ if r is None:
626
+ # Cannot resolve call type until all argument types are known
627
+ return
628
+ pos_args, kw_args = r
629
+
630
+ # Check argument to be precise
631
+ for a in itertools.chain(pos_args, kw_args.values()):
632
+ # Forbids imprecise type except array of undefined dtype
633
+ if not a.is_precise() and not isinstance(a, types.Array):
634
+ return
635
+
636
+ # Resolve call type
637
+ if isinstance(fnty, types.TypeRef):
638
+ # Unwrap TypeRef
639
+ fnty = fnty.instance_type
640
+ try:
641
+ sig = typeinfer.resolve_call(fnty, pos_args, kw_args)
642
+ except ForceLiteralArg as e:
643
+ # Adjust for bound methods
644
+ folding_args = (
645
+ (fnty.this,) + tuple(self.args)
646
+ if isinstance(fnty, types.BoundFunction)
647
+ else self.args
648
+ )
649
+ folded = e.fold_arguments(folding_args, self.kws)
650
+ requested = set()
651
+ unsatisfied = set()
652
+ for idx in e.requested_args:
653
+ maybe_arg = typeinfer.func_ir.get_definition(folded[idx])
654
+ if isinstance(maybe_arg, ir.Arg):
655
+ requested.add(maybe_arg.index)
656
+ else:
657
+ unsatisfied.add(idx)
658
+ if unsatisfied:
659
+ raise TypingError("Cannot request literal type.", loc=self.loc)
660
+ elif requested:
661
+ raise ForceLiteralArg(requested, loc=self.loc)
662
+ if sig is None:
663
+ # Note: duplicated error checking.
664
+ # See types.BaseFunction.get_call_type
665
+ # Arguments are invalid => explain why
666
+ headtemp = "Invalid use of {0} with parameters ({1})"
667
+ args = [str(a) for a in pos_args]
668
+ args += ["%s=%s" % (k, v) for k, v in sorted(kw_args.items())]
669
+ head = headtemp.format(fnty, ", ".join(map(str, args)))
670
+ desc = context.explain_function_type(fnty)
671
+ msg = "\n".join([head, desc])
672
+ raise TypingError(msg)
673
+
674
+ typeinfer.add_type(self.target, sig.return_type, loc=self.loc)
675
+
676
+ # If the function is a bound function and its receiver type
677
+ # was refined, propagate it.
678
+ if (
679
+ isinstance(fnty, types.BoundFunction)
680
+ and sig.recvr is not None
681
+ and sig.recvr != fnty.this
682
+ ):
683
+ refined_this = context.unify_pairs(sig.recvr, fnty.this)
684
+ if (
685
+ refined_this is None
686
+ and fnty.this.is_precise()
687
+ and sig.recvr.is_precise()
688
+ ):
689
+ msg = "Cannot refine type {} to {}".format(
690
+ sig.recvr,
691
+ fnty.this,
692
+ )
693
+ raise TypingError(msg, loc=self.loc)
694
+ if refined_this is not None and refined_this.is_precise():
695
+ refined_fnty = fnty.copy(this=refined_this)
696
+ typeinfer.propagate_refined_type(self.func, refined_fnty)
697
+
698
+ # If the return type is imprecise but can be unified with the
699
+ # target variable's inferred type, use the latter.
700
+ # Useful for code such as::
701
+ # s = set()
702
+ # s.add(1)
703
+ # (the set() call must be typed as int64(), not undefined())
704
+ if not sig.return_type.is_precise():
705
+ target = typevars[self.target]
706
+ if target.defined:
707
+ targetty = target.getone()
708
+ if context.unify_pairs(targetty, sig.return_type) == targetty:
709
+ sig = sig.replace(return_type=targetty)
710
+
711
+ self.signature = sig
712
+ self._add_refine_map(typeinfer, typevars, sig)
713
+
714
+ def _add_refine_map(self, typeinfer, typevars, sig):
715
+ """Add this expression to the refine_map base on the type of target_type"""
716
+ target_type = typevars[self.target].getone()
717
+ # Array
718
+ if isinstance(target_type, types.Array) and isinstance(
719
+ sig.return_type.dtype, types.Undefined
720
+ ):
721
+ typeinfer.refine_map[self.target] = self
722
+ # DictType
723
+ if (
724
+ isinstance(target_type, types.DictType)
725
+ and not target_type.is_precise()
726
+ ):
727
+ typeinfer.refine_map[self.target] = self
728
+
729
+ def refine(self, typeinfer, updated_type):
730
+ # Is getitem?
731
+ if self.func == operator.getitem:
732
+ aryty = typeinfer.typevars[self.args[0].name].getone()
733
+ # is array not precise?
734
+ if _is_array_not_precise(aryty):
735
+ # allow refinement of dtype
736
+ assert updated_type.is_precise()
737
+ newtype = aryty.copy(dtype=updated_type.dtype)
738
+ typeinfer.add_type(self.args[0].name, newtype, loc=self.loc)
739
+ else:
740
+ m = "no type refinement implemented for function {} updating to {}"
741
+ raise TypingError(m.format(self.func, updated_type))
742
+
743
+ def get_call_signature(self):
744
+ return self.signature
745
+
746
+
747
+ class IntrinsicCallConstraint(CallConstraint):
748
+ def __call__(self, typeinfer):
749
+ with new_error_context("typing of intrinsic-call at {0}", self.loc):
750
+ fnty = self.func
751
+ if fnty in utils.OPERATORS_TO_BUILTINS:
752
+ fnty = typeinfer.resolve_value_type(None, fnty)
753
+ self.resolve(typeinfer, typeinfer.typevars, fnty=fnty)
754
+
755
+
756
+ class GetAttrConstraint(object):
757
+ def __init__(self, target, attr, value, loc, inst):
758
+ self.target = target
759
+ self.attr = attr
760
+ self.value = value
761
+ self.loc = loc
762
+ self.inst = inst
763
+
764
+ def __call__(self, typeinfer):
765
+ with new_error_context("typing of get attribute at {0}", self.loc):
766
+ typevars = typeinfer.typevars
767
+ valtys = typevars[self.value.name].get()
768
+ for ty in valtys:
769
+ attrty = typeinfer.context.resolve_getattr(ty, self.attr)
770
+ if attrty is None:
771
+ raise UntypedAttributeError(
772
+ ty, self.attr, loc=self.inst.loc
773
+ )
774
+ else:
775
+ assert attrty.is_precise()
776
+ typeinfer.add_type(self.target, attrty, loc=self.loc)
777
+ typeinfer.refine_map[self.target] = self
778
+
779
+ def refine(self, typeinfer, target_type):
780
+ if isinstance(target_type, types.BoundFunction):
781
+ recvr = target_type.this
782
+ assert recvr.is_precise()
783
+ typeinfer.add_type(self.value.name, recvr, loc=self.loc)
784
+ source_constraint = typeinfer.refine_map.get(self.value.name)
785
+ if source_constraint is not None:
786
+ source_constraint.refine(typeinfer, recvr)
787
+
788
+ def __repr__(self):
789
+ return 'resolving type of attribute "{attr}" of "{value}"'.format(
790
+ value=self.value, attr=self.attr
791
+ )
792
+
793
+
794
+ class SetItemRefinement(object):
795
+ """A mixin class to provide the common refinement logic in setitem
796
+ and static setitem.
797
+ """
798
+
799
+ def _refine_target_type(self, typeinfer, targetty, idxty, valty, sig):
800
+ """Refine the target-type given the known index type and value type."""
801
+ # For array setitem, refine imprecise array dtype
802
+ if _is_array_not_precise(targetty):
803
+ typeinfer.add_type(self.target.name, sig.args[0], loc=self.loc)
804
+ # For Dict setitem
805
+ if isinstance(targetty, types.DictType):
806
+ if not targetty.is_precise():
807
+ refined = targetty.refine(idxty, valty)
808
+ typeinfer.add_type(
809
+ self.target.name,
810
+ refined,
811
+ loc=self.loc,
812
+ )
813
+ elif isinstance(targetty, types.LiteralStrKeyDict):
814
+ typeinfer.add_type(
815
+ self.target.name,
816
+ types.DictType(idxty, valty),
817
+ loc=self.loc,
818
+ )
819
+
820
+
821
+ class SetItemConstraint(SetItemRefinement):
822
+ def __init__(self, target, index, value, loc):
823
+ self.target = target
824
+ self.index = index
825
+ self.value = value
826
+ self.loc = loc
827
+
828
+ def __call__(self, typeinfer):
829
+ with new_error_context("typing of setitem at {0}", self.loc):
830
+ typevars = typeinfer.typevars
831
+ if not all(
832
+ typevars[var.name].defined
833
+ for var in (self.target, self.index, self.value)
834
+ ):
835
+ return
836
+ targetty = typevars[self.target.name].getone()
837
+ idxty = typevars[self.index.name].getone()
838
+ valty = typevars[self.value.name].getone()
839
+
840
+ sig = typeinfer.context.resolve_setitem(targetty, idxty, valty)
841
+ if sig is None:
842
+ raise TypingError(
843
+ "Cannot resolve setitem: %s[%s] = %s"
844
+ % (targetty, idxty, valty),
845
+ loc=self.loc,
846
+ )
847
+
848
+ self.signature = sig
849
+ self._refine_target_type(typeinfer, targetty, idxty, valty, sig)
850
+
851
+ def get_call_signature(self):
852
+ return self.signature
853
+
854
+
855
+ class StaticSetItemConstraint(SetItemRefinement):
856
+ def __init__(self, target, index, index_var, value, loc):
857
+ self.target = target
858
+ self.index = index
859
+ self.index_var = index_var
860
+ self.value = value
861
+ self.loc = loc
862
+
863
+ def __call__(self, typeinfer):
864
+ with new_error_context("typing of staticsetitem at {0}", self.loc):
865
+ typevars = typeinfer.typevars
866
+ if not all(
867
+ typevars[var.name].defined
868
+ for var in (self.target, self.index_var, self.value)
869
+ ):
870
+ return
871
+ targetty = typevars[self.target.name].getone()
872
+ idxty = typevars[self.index_var.name].getone()
873
+ valty = typevars[self.value.name].getone()
874
+
875
+ sig = typeinfer.context.resolve_static_setitem(
876
+ targetty, self.index, valty
877
+ )
878
+ if sig is None:
879
+ sig = typeinfer.context.resolve_setitem(targetty, idxty, valty)
880
+ if sig is None:
881
+ raise TypingError(
882
+ "Cannot resolve setitem: %s[%r] = %s"
883
+ % (targetty, self.index, valty),
884
+ loc=self.loc,
885
+ )
886
+ self.signature = sig
887
+ self._refine_target_type(typeinfer, targetty, idxty, valty, sig)
888
+
889
+ def get_call_signature(self):
890
+ return self.signature
891
+
892
+
893
+ class DelItemConstraint(object):
894
+ def __init__(self, target, index, loc):
895
+ self.target = target
896
+ self.index = index
897
+ self.loc = loc
898
+
899
+ def __call__(self, typeinfer):
900
+ with new_error_context("typing of delitem at {0}", self.loc):
901
+ typevars = typeinfer.typevars
902
+ if not all(
903
+ typevars[var.name].defined for var in (self.target, self.index)
904
+ ):
905
+ return
906
+ targetty = typevars[self.target.name].getone()
907
+ idxty = typevars[self.index.name].getone()
908
+
909
+ sig = typeinfer.context.resolve_delitem(targetty, idxty)
910
+ if sig is None:
911
+ raise TypingError(
912
+ "Cannot resolve delitem: %s[%s]" % (targetty, idxty),
913
+ loc=self.loc,
914
+ )
915
+ self.signature = sig
916
+
917
+ def get_call_signature(self):
918
+ return self.signature
919
+
920
+
921
+ class SetAttrConstraint(object):
922
+ def __init__(self, target, attr, value, loc):
923
+ self.target = target
924
+ self.attr = attr
925
+ self.value = value
926
+ self.loc = loc
927
+
928
+ def __call__(self, typeinfer):
929
+ with new_error_context(
930
+ "typing of set attribute {0!r} at {1}", self.attr, self.loc
931
+ ):
932
+ typevars = typeinfer.typevars
933
+ if not all(
934
+ typevars[var.name].defined for var in (self.target, self.value)
935
+ ):
936
+ return
937
+ targetty = typevars[self.target.name].getone()
938
+ valty = typevars[self.value.name].getone()
939
+ sig = typeinfer.context.resolve_setattr(targetty, self.attr, valty)
940
+ if sig is None:
941
+ raise TypingError(
942
+ "Cannot resolve setattr: (%s).%s = %s"
943
+ % (targetty, self.attr, valty),
944
+ loc=self.loc,
945
+ )
946
+ self.signature = sig
947
+
948
+ def get_call_signature(self):
949
+ return self.signature
950
+
951
+
952
+ class PrintConstraint(object):
953
+ def __init__(self, args, vararg, loc):
954
+ self.args = args
955
+ self.vararg = vararg
956
+ self.loc = loc
957
+
958
+ def __call__(self, typeinfer):
959
+ typevars = typeinfer.typevars
960
+
961
+ r = fold_arg_vars(typevars, self.args, self.vararg, {})
962
+ if r is None:
963
+ # Cannot resolve call type until all argument types are known
964
+ return
965
+ pos_args, kw_args = r
966
+
967
+ fnty = typeinfer.context.resolve_value_type(print)
968
+ assert fnty is not None
969
+ sig = typeinfer.resolve_call(fnty, pos_args, kw_args)
970
+ self.signature = sig
971
+
972
+ def get_call_signature(self):
973
+ return self.signature
974
+
975
+
976
+ class TypeVarMap(dict):
977
+ def set_context(self, context):
978
+ self.context = context
979
+
980
+ def __getitem__(self, name):
981
+ if name not in self:
982
+ self[name] = TypeVar(self.context, name)
983
+ return super(TypeVarMap, self).__getitem__(name)
984
+
985
+ def __setitem__(self, name, value):
986
+ assert isinstance(name, str)
987
+ if name in self:
988
+ raise KeyError("Cannot redefine typevar %s" % name)
989
+ else:
990
+ super(TypeVarMap, self).__setitem__(name, value)
991
+
992
+
993
+ # A temporary mapping of {function name: dispatcher object}
994
+ _temporary_dispatcher_map = {}
995
+ # A temporary mapping of {function name: dispatcher object reference count}
996
+ # Reference: https://github.com/numba/numba/issues/3658
997
+ _temporary_dispatcher_map_ref_count = defaultdict(int)
998
+
999
+
1000
+ @contextlib.contextmanager
1001
+ def register_dispatcher(disp):
1002
+ """
1003
+ Register a Dispatcher for inference while it is not yet stored
1004
+ as global or closure variable (e.g. during execution of the @jit()
1005
+ call). This allows resolution of recursive calls with eager
1006
+ compilation.
1007
+ """
1008
+ assert callable(disp)
1009
+ assert callable(disp.py_func)
1010
+ name = disp.py_func.__name__
1011
+ _temporary_dispatcher_map[name] = disp
1012
+ _temporary_dispatcher_map_ref_count[name] += 1
1013
+ try:
1014
+ yield
1015
+ finally:
1016
+ _temporary_dispatcher_map_ref_count[name] -= 1
1017
+ if not _temporary_dispatcher_map_ref_count[name]:
1018
+ del _temporary_dispatcher_map[name]
1019
+
1020
+
1021
+ typeinfer_extensions = {}
1022
+
1023
+
1024
+ class TypeInferer(object):
1025
+ """
1026
+ Operates on block that shares the same ir.Scope.
1027
+ """
1028
+
1029
+ def __init__(self, context, func_ir, warnings):
1030
+ self.context = context
1031
+ # sort based on label, ensure iteration order!
1032
+ self.blocks = OrderedDict()
1033
+ for k in sorted(func_ir.blocks.keys()):
1034
+ self.blocks[k] = func_ir.blocks[k]
1035
+ self.generator_info = func_ir.generator_info
1036
+ self.func_id = func_ir.func_id
1037
+ self.func_ir = func_ir
1038
+
1039
+ self.typevars = TypeVarMap()
1040
+ self.typevars.set_context(context)
1041
+ self.constraints = ConstraintNetwork()
1042
+ self.warnings = warnings
1043
+
1044
+ # { index: mangled name }
1045
+ self.arg_names = {}
1046
+ # self.return_type = None
1047
+ # Set of assumed immutable globals
1048
+ self.assumed_immutables = set()
1049
+ # Track all calls and associated constraints
1050
+ self.calls = []
1051
+ # The inference result of the above calls
1052
+ self.calltypes = utils.UniqueDict()
1053
+ # Target var -> constraint with refine hook
1054
+ self.refine_map = {}
1055
+
1056
+ if config.DEBUG or config.DEBUG_TYPEINFER:
1057
+ self.debug = TypeInferDebug(self)
1058
+ else:
1059
+ self.debug = NullDebug()
1060
+
1061
+ self._skip_recursion = False
1062
+
1063
+ def copy(self, skip_recursion=False):
1064
+ clone = TypeInferer(self.context, self.func_ir, self.warnings)
1065
+ clone.arg_names = self.arg_names.copy()
1066
+ clone._skip_recursion = skip_recursion
1067
+
1068
+ for k, v in self.typevars.items():
1069
+ if not v.locked and v.defined:
1070
+ clone.typevars[k].add_type(v.getone(), loc=v.define_loc)
1071
+
1072
+ return clone
1073
+
1074
+ def _mangle_arg_name(self, name):
1075
+ # Disambiguise argument name
1076
+ return "arg.%s" % (name,)
1077
+
1078
+ def _get_return_vars(self):
1079
+ rets = []
1080
+ for blk in self.blocks.values():
1081
+ inst = blk.terminator
1082
+ if isinstance(inst, ir.Return):
1083
+ rets.append(inst.value)
1084
+ return rets
1085
+
1086
+ def get_argument_types(self):
1087
+ return [self.typevars[k].getone() for k in self.arg_names.values()]
1088
+
1089
+ def seed_argument(self, name, index, typ):
1090
+ name = self._mangle_arg_name(name)
1091
+ self.seed_type(name, typ)
1092
+ self.arg_names[index] = name
1093
+
1094
+ def seed_type(self, name, typ):
1095
+ """All arguments should be seeded."""
1096
+ self.lock_type(name, typ, loc=None)
1097
+
1098
+ def seed_return(self, typ):
1099
+ """Seeding of return value is optional."""
1100
+ for var in self._get_return_vars():
1101
+ self.lock_type(var.name, typ, loc=None)
1102
+
1103
+ def build_constraint(self):
1104
+ for blk in self.blocks.values():
1105
+ for inst in blk.body:
1106
+ self.constrain_statement(inst)
1107
+
1108
+ def return_types_from_partial(self):
1109
+ """
1110
+ Resume type inference partially to deduce the return type.
1111
+ Note: No side-effect to `self`.
1112
+
1113
+ Returns the inferred return type or None if it cannot deduce the return
1114
+ type.
1115
+ """
1116
+ # Clone the typeinferer and disable typing recursive calls
1117
+ cloned = self.copy(skip_recursion=True)
1118
+ # rebuild constraint network
1119
+ cloned.build_constraint()
1120
+ # propagate without raising
1121
+ cloned.propagate(raise_errors=False)
1122
+ # get return types
1123
+ rettypes = set()
1124
+ for retvar in cloned._get_return_vars():
1125
+ if retvar.name in cloned.typevars:
1126
+ typevar = cloned.typevars[retvar.name]
1127
+ if typevar and typevar.defined:
1128
+ rettypes.add(types.unliteral(typevar.getone()))
1129
+ if not rettypes:
1130
+ return
1131
+ # unify return types
1132
+ return cloned._unify_return_types(rettypes)
1133
+
1134
+ def propagate(self, raise_errors=True):
1135
+ newtoken = self.get_state_token()
1136
+ oldtoken = None
1137
+ # Since the number of types are finite, the typesets will eventually
1138
+ # stop growing.
1139
+
1140
+ while newtoken != oldtoken:
1141
+ self.debug.propagate_started()
1142
+ oldtoken = newtoken
1143
+ # Errors can appear when the type set is incomplete; only
1144
+ # raise them when there is no progress anymore.
1145
+ errors = self.constraints.propagate(self)
1146
+ newtoken = self.get_state_token()
1147
+ self.debug.propagate_finished()
1148
+ if errors:
1149
+ if raise_errors:
1150
+ force_lit_args = [
1151
+ e for e in errors if isinstance(e, ForceLiteralArg)
1152
+ ]
1153
+ if not force_lit_args:
1154
+ raise errors[0]
1155
+ else:
1156
+ raise reduce(operator.or_, force_lit_args)
1157
+ else:
1158
+ return errors
1159
+
1160
+ def add_type(self, var, tp, loc, unless_locked=False):
1161
+ assert isinstance(var, str), type(var)
1162
+ tv = self.typevars[var]
1163
+ if unless_locked and tv.locked:
1164
+ return
1165
+ oldty = tv.type
1166
+ unified = tv.add_type(tp, loc=loc)
1167
+ if unified != oldty:
1168
+ self.propagate_refined_type(var, unified)
1169
+
1170
+ def add_calltype(self, inst, signature):
1171
+ assert signature is not None
1172
+ self.calltypes[inst] = signature
1173
+
1174
+ def copy_type(self, src_var, dest_var, loc):
1175
+ self.typevars[dest_var].union(self.typevars[src_var], loc=loc)
1176
+
1177
+ def lock_type(self, var, tp, loc, literal_value=NOTSET):
1178
+ tv = self.typevars[var]
1179
+ tv.lock(tp, loc=loc, literal_value=literal_value)
1180
+
1181
+ def propagate_refined_type(self, updated_var, updated_type):
1182
+ source_constraint = self.refine_map.get(updated_var)
1183
+ if source_constraint is not None:
1184
+ source_constraint.refine(self, updated_type)
1185
+
1186
+ def unify(self, raise_errors=True):
1187
+ """
1188
+ Run the final unification pass over all inferred types, and
1189
+ catch imprecise types.
1190
+ """
1191
+ typdict = utils.UniqueDict()
1192
+
1193
+ def find_offender(name, exhaustive=False):
1194
+ # finds the offending variable definition by name
1195
+ # if exhaustive is set it will try and trace through temporary
1196
+ # variables to find a concrete offending definition.
1197
+ offender = None
1198
+ for block in self.func_ir.blocks.values():
1199
+ offender = block.find_variable_assignment(name)
1200
+ if offender is not None:
1201
+ if not exhaustive:
1202
+ break
1203
+ try: # simple assignment
1204
+ hasattr(offender.value, "name")
1205
+ offender_value = offender.value.name
1206
+ except (AttributeError, KeyError):
1207
+ break
1208
+ orig_offender = offender
1209
+ if offender_value.startswith("$"):
1210
+ offender = find_offender(
1211
+ offender_value, exhaustive=exhaustive
1212
+ )
1213
+ if offender is None:
1214
+ offender = orig_offender
1215
+ break
1216
+ return offender
1217
+
1218
+ def diagnose_imprecision(offender):
1219
+ # helper for diagnosing imprecise types
1220
+
1221
+ list_msg = """\n
1222
+ For Numba to be able to compile a list, the list must have a known and
1223
+ precise type that can be inferred from the other variables. Whilst sometimes
1224
+ the type of empty lists can be inferred, this is not always the case, see this
1225
+ documentation for help:
1226
+
1227
+ https://numba.readthedocs.io/en/stable/user/troubleshoot.html#my-code-has-an-untyped-list-problem
1228
+ """
1229
+ if offender is not None:
1230
+ # This block deals with imprecise lists
1231
+ if hasattr(offender, "value"):
1232
+ if hasattr(offender.value, "op"):
1233
+ # might be `foo = []`
1234
+ if offender.value.op == "build_list":
1235
+ return list_msg
1236
+ # or might be `foo = list()`
1237
+ elif offender.value.op == "call":
1238
+ try: # assignment involving a call
1239
+ call_name = offender.value.func.name
1240
+ # find the offender based on the call name
1241
+ offender = find_offender(call_name)
1242
+ if isinstance(offender.value, ir.Global):
1243
+ if offender.value.name == "list":
1244
+ return list_msg
1245
+ except (AttributeError, KeyError):
1246
+ pass
1247
+ return "" # no help possible
1248
+
1249
+ def check_var(name):
1250
+ tv = self.typevars[name]
1251
+ if not tv.defined:
1252
+ if raise_errors:
1253
+ offender = find_offender(name)
1254
+ val = getattr(offender, "value", "unknown operation")
1255
+ loc = getattr(offender, "loc", ir.unknown_loc)
1256
+ msg = (
1257
+ "Type of variable '%s' cannot be determined, "
1258
+ "operation: %s, location: %s"
1259
+ )
1260
+ raise TypingError(msg % (var, val, loc), loc)
1261
+ else:
1262
+ typdict[var] = types.unknown
1263
+ return
1264
+ tp = tv.getone()
1265
+
1266
+ if isinstance(tp, types.UndefinedFunctionType):
1267
+ tp = tp.get_precise()
1268
+
1269
+ if not tp.is_precise():
1270
+ offender = find_offender(name, exhaustive=True)
1271
+ msg = (
1272
+ "Cannot infer the type of variable '%s'%s, "
1273
+ "have imprecise type: %s. %s"
1274
+ )
1275
+ istmp = " (temporary variable)" if var.startswith("$") else ""
1276
+ loc = getattr(offender, "loc", ir.unknown_loc)
1277
+ # is this an untyped list? try and provide help
1278
+ extra_msg = diagnose_imprecision(offender)
1279
+ if raise_errors:
1280
+ raise TypingError(msg % (var, istmp, tp, extra_msg), loc)
1281
+ else:
1282
+ typdict[var] = types.unknown
1283
+ return
1284
+ else: # type is precise, hold it
1285
+ typdict[var] = tp
1286
+
1287
+ # For better error display, check first user-visible vars, then
1288
+ # temporaries
1289
+ temps = set(k for k in self.typevars if not k[0].isalpha())
1290
+ others = set(self.typevars) - temps
1291
+ for var in sorted(others):
1292
+ check_var(var)
1293
+ for var in sorted(temps):
1294
+ check_var(var)
1295
+
1296
+ try:
1297
+ retty = self.get_return_type(typdict)
1298
+ except Exception as e:
1299
+ # partial type inference may raise e.g. attribute error if a
1300
+ # constraint has no computable signature, ignore this as needed
1301
+ if raise_errors:
1302
+ raise e
1303
+ else:
1304
+ retty = None
1305
+ else:
1306
+ typdict = utils.UniqueDict(
1307
+ typdict, **{v.name: retty for v in self._get_return_vars()}
1308
+ )
1309
+
1310
+ try:
1311
+ fntys = self.get_function_types(typdict)
1312
+ except Exception as e:
1313
+ # partial type inference may raise e.g. attribute error if a
1314
+ # constraint has no computable signature, ignore this as needed
1315
+ if raise_errors:
1316
+ raise e
1317
+ else:
1318
+ fntys = None
1319
+
1320
+ if self.generator_info:
1321
+ retty = self.get_generator_type(
1322
+ typdict, retty, raise_errors=raise_errors
1323
+ )
1324
+
1325
+ def check_undef_var_in_calls():
1326
+ # Check for undefined variables in the call arguments.
1327
+ for callnode, calltype in self.calltypes.items():
1328
+ if calltype is not None:
1329
+ for i, v in enumerate(calltype.args, start=1):
1330
+ if v is types._undef_var:
1331
+ m = f"undefined variable used in call argument #{i}"
1332
+ raise TypingError(m, loc=callnode.loc)
1333
+
1334
+ check_undef_var_in_calls()
1335
+
1336
+ self.debug.unify_finished(typdict, retty, fntys)
1337
+
1338
+ return typdict, retty, fntys
1339
+
1340
+ def get_generator_type(self, typdict, retty, raise_errors=True):
1341
+ gi = self.generator_info
1342
+ arg_types = [None] * len(self.arg_names)
1343
+ for index, name in self.arg_names.items():
1344
+ arg_types[index] = typdict[name]
1345
+
1346
+ state_types = None
1347
+ try:
1348
+ state_types = [typdict[var_name] for var_name in gi.state_vars]
1349
+ except KeyError:
1350
+ msg = "Cannot type generator: state variable types cannot be found"
1351
+ if raise_errors:
1352
+ raise TypingError(msg)
1353
+ state_types = [types.unknown for _ in gi.state_vars]
1354
+
1355
+ yield_types = None
1356
+ try:
1357
+ yield_types = [
1358
+ typdict[y.inst.value.name] for y in gi.get_yield_points()
1359
+ ]
1360
+ except KeyError:
1361
+ msg = "Cannot type generator: yield type cannot be found"
1362
+ if raise_errors:
1363
+ raise TypingError(msg)
1364
+ if not yield_types:
1365
+ msg = "Cannot type generator: it does not yield any value"
1366
+ if raise_errors:
1367
+ raise TypingError(msg)
1368
+ yield_types = [types.unknown for _ in gi.get_yield_points()]
1369
+
1370
+ if not yield_types or all(yield_types) == types.unknown:
1371
+ # unknown yield, probably partial type inference, escape
1372
+ return types.Generator(
1373
+ self.func_id.func,
1374
+ types.unknown,
1375
+ arg_types,
1376
+ state_types,
1377
+ has_finalizer=True,
1378
+ )
1379
+
1380
+ yield_type = self.context.unify_types(*yield_types)
1381
+ if yield_type is None or isinstance(yield_type, types.Optional):
1382
+ msg = "Cannot type generator: cannot unify yielded types %s"
1383
+ yp_highlights = []
1384
+ for y in gi.get_yield_points():
1385
+ msg = _termcolor.errmsg(
1386
+ "Yield of: IR '%s', type '%s', location: %s"
1387
+ )
1388
+ yp_highlights.append(
1389
+ msg
1390
+ % (
1391
+ str(y.inst),
1392
+ typdict[y.inst.value.name],
1393
+ y.inst.loc.strformat(),
1394
+ )
1395
+ )
1396
+
1397
+ explain_ty = set()
1398
+ for ty in yield_types:
1399
+ if isinstance(ty, types.Optional):
1400
+ explain_ty.add(ty.type)
1401
+ explain_ty.add(types.NoneType("none"))
1402
+ else:
1403
+ explain_ty.add(ty)
1404
+ if raise_errors:
1405
+ raise TypingError(
1406
+ "Can't unify yield type from the "
1407
+ "following types: %s"
1408
+ % ", ".join(sorted(map(str, explain_ty)))
1409
+ + "\n\n"
1410
+ + "\n".join(yp_highlights)
1411
+ )
1412
+
1413
+ return types.Generator(
1414
+ self.func_id.func,
1415
+ yield_type,
1416
+ arg_types,
1417
+ state_types,
1418
+ has_finalizer=True,
1419
+ )
1420
+
1421
+ def get_function_types(self, typemap):
1422
+ """
1423
+ Fill and return the calltypes map.
1424
+ """
1425
+ # XXX why can't this be done on the fly?
1426
+ calltypes = self.calltypes
1427
+ for call, constraint in self.calls:
1428
+ calltypes[call] = constraint.get_call_signature()
1429
+ return calltypes
1430
+
1431
+ def _unify_return_types(self, rettypes):
1432
+ if rettypes:
1433
+ unified = self.context.unify_types(*rettypes)
1434
+ if isinstance(unified, types.FunctionType):
1435
+ # unified is allowed to be UndefinedFunctionType
1436
+ # instance (that is imprecise).
1437
+ return unified
1438
+ if unified is None or not unified.is_precise():
1439
+
1440
+ def check_type(atype):
1441
+ lst = []
1442
+ for k, v in self.typevars.items():
1443
+ if atype == v.type:
1444
+ lst.append(k)
1445
+ returns = {}
1446
+ for x in reversed(lst):
1447
+ for block in self.func_ir.blocks.values():
1448
+ for instr in block.find_insts(ir.Return):
1449
+ value = instr.value
1450
+ if isinstance(value, ir.Var):
1451
+ name = value.name
1452
+ else:
1453
+ pass
1454
+ if x == name:
1455
+ returns[x] = instr
1456
+ break
1457
+
1458
+ interped = ""
1459
+ for name, offender in returns.items():
1460
+ loc = getattr(offender, "loc", ir.unknown_loc)
1461
+ msg = "Return of: IR name '%s', type '%s', location: %s"
1462
+ interped = msg % (name, atype, loc.strformat())
1463
+ return interped
1464
+
1465
+ problem_str = []
1466
+ for xtype in rettypes:
1467
+ problem_str.append(_termcolor.errmsg(check_type(xtype)))
1468
+
1469
+ raise TypingError(
1470
+ "Can't unify return type from the "
1471
+ "following types: %s"
1472
+ % ", ".join(sorted(map(str, rettypes)))
1473
+ + "\n"
1474
+ + "\n".join(problem_str)
1475
+ )
1476
+ return unified
1477
+ else:
1478
+ # Function without a successful return path
1479
+ return types.none
1480
+
1481
+ def get_return_type(self, typemap):
1482
+ rettypes = set()
1483
+ for var in self._get_return_vars():
1484
+ rettypes.add(typemap[var.name])
1485
+ retty = self._unify_return_types(rettypes)
1486
+ # Check return value is not undefined
1487
+ if retty is types._undef_var:
1488
+ raise TypingError("return value is undefined")
1489
+ return retty
1490
+
1491
+ def get_state_token(self):
1492
+ """The algorithm is monotonic. It can only grow or "refine" the
1493
+ typevar map.
1494
+ """
1495
+ return [tv.type for name, tv in sorted(self.typevars.items())]
1496
+
1497
+ def constrain_statement(self, inst):
1498
+ if isinstance(inst, ir.Assign):
1499
+ self.typeof_assign(inst)
1500
+ elif isinstance(inst, ir.SetItem):
1501
+ self.typeof_setitem(inst)
1502
+ elif isinstance(inst, ir.StaticSetItem):
1503
+ self.typeof_static_setitem(inst)
1504
+ elif isinstance(inst, ir.DelItem):
1505
+ self.typeof_delitem(inst)
1506
+ elif isinstance(inst, ir.SetAttr):
1507
+ self.typeof_setattr(inst)
1508
+ elif isinstance(inst, ir.Print):
1509
+ self.typeof_print(inst)
1510
+ elif isinstance(inst, ir.StoreMap):
1511
+ self.typeof_storemap(inst)
1512
+ elif isinstance(inst, (ir.Jump, ir.Branch, ir.Return, ir.Del)):
1513
+ pass
1514
+ elif isinstance(inst, (ir.DynamicRaise, ir.DynamicTryRaise)):
1515
+ pass
1516
+ elif isinstance(inst, (ir.StaticRaise, ir.StaticTryRaise)):
1517
+ pass
1518
+ elif isinstance(inst, ir.PopBlock):
1519
+ pass # It's a marker statement
1520
+ elif type(inst) in typeinfer_extensions:
1521
+ # let external calls handle stmt if type matches
1522
+ f = typeinfer_extensions[type(inst)]
1523
+ f(inst, self)
1524
+ else:
1525
+ msg = "Unsupported constraint encountered: %s" % inst
1526
+ raise UnsupportedError(msg, loc=inst.loc)
1527
+
1528
+ def typeof_setitem(self, inst):
1529
+ constraint = SetItemConstraint(
1530
+ target=inst.target, index=inst.index, value=inst.value, loc=inst.loc
1531
+ )
1532
+ self.constraints.append(constraint)
1533
+ self.calls.append((inst, constraint))
1534
+
1535
+ def typeof_storemap(self, inst):
1536
+ constraint = SetItemConstraint(
1537
+ target=inst.dct, index=inst.key, value=inst.value, loc=inst.loc
1538
+ )
1539
+ self.constraints.append(constraint)
1540
+ self.calls.append((inst, constraint))
1541
+
1542
+ def typeof_static_setitem(self, inst):
1543
+ constraint = StaticSetItemConstraint(
1544
+ target=inst.target,
1545
+ index=inst.index,
1546
+ index_var=inst.index_var,
1547
+ value=inst.value,
1548
+ loc=inst.loc,
1549
+ )
1550
+ self.constraints.append(constraint)
1551
+ self.calls.append((inst, constraint))
1552
+
1553
+ def typeof_delitem(self, inst):
1554
+ constraint = DelItemConstraint(
1555
+ target=inst.target, index=inst.index, loc=inst.loc
1556
+ )
1557
+ self.constraints.append(constraint)
1558
+ self.calls.append((inst, constraint))
1559
+
1560
+ def typeof_setattr(self, inst):
1561
+ constraint = SetAttrConstraint(
1562
+ target=inst.target, attr=inst.attr, value=inst.value, loc=inst.loc
1563
+ )
1564
+ self.constraints.append(constraint)
1565
+ self.calls.append((inst, constraint))
1566
+
1567
+ def typeof_print(self, inst):
1568
+ constraint = PrintConstraint(
1569
+ args=inst.args, vararg=inst.vararg, loc=inst.loc
1570
+ )
1571
+ self.constraints.append(constraint)
1572
+ self.calls.append((inst, constraint))
1573
+
1574
+ def typeof_assign(self, inst):
1575
+ value = inst.value
1576
+ if isinstance(value, ir.Const):
1577
+ self.typeof_const(inst, inst.target, value.value)
1578
+ elif isinstance(value, ir.Var):
1579
+ self.constraints.append(
1580
+ Propagate(dst=inst.target.name, src=value.name, loc=inst.loc)
1581
+ )
1582
+ elif isinstance(value, (ir.Global, ir.FreeVar)):
1583
+ self.typeof_global(inst, inst.target, value)
1584
+ elif isinstance(value, ir.Arg):
1585
+ self.typeof_arg(inst, inst.target, value)
1586
+ elif isinstance(value, ir.Expr):
1587
+ self.typeof_expr(inst, inst.target, value)
1588
+ elif isinstance(value, ir.Yield):
1589
+ self.typeof_yield(inst, inst.target, value)
1590
+ else:
1591
+ msg = "Unsupported assignment encountered: %s %s" % (
1592
+ type(value),
1593
+ str(value),
1594
+ )
1595
+ raise UnsupportedError(msg, loc=inst.loc)
1596
+
1597
+ def resolve_value_type(self, inst, val):
1598
+ """
1599
+ Resolve the type of a simple Python value, such as can be
1600
+ represented by literals.
1601
+ """
1602
+ try:
1603
+ return self.context.resolve_value_type(val)
1604
+ except ValueError as e:
1605
+ msg = str(e)
1606
+ raise TypingError(msg, loc=inst.loc)
1607
+
1608
+ def typeof_arg(self, inst, target, arg):
1609
+ src_name = self._mangle_arg_name(arg.name)
1610
+ self.constraints.append(
1611
+ ArgConstraint(dst=target.name, src=src_name, loc=inst.loc)
1612
+ )
1613
+
1614
+ def typeof_const(self, inst, target, const):
1615
+ ty = self.resolve_value_type(inst, const)
1616
+ if inst.value.use_literal_type:
1617
+ lit = types.maybe_literal(value=const)
1618
+ else:
1619
+ lit = None
1620
+ self.add_type(target.name, lit or ty, loc=inst.loc)
1621
+
1622
+ def typeof_yield(self, inst, target, yield_):
1623
+ # Sending values into generators isn't supported.
1624
+ self.add_type(target.name, types.none, loc=inst.loc)
1625
+
1626
+ def sentry_modified_builtin(self, inst, gvar):
1627
+ """
1628
+ Ensure that builtins are not modified.
1629
+ """
1630
+ if gvar.name == "range" and gvar.value is not range:
1631
+ bad = True
1632
+ elif gvar.name == "slice" and gvar.value is not slice:
1633
+ bad = True
1634
+ elif gvar.name == "len" and gvar.value is not len:
1635
+ bad = True
1636
+ else:
1637
+ bad = False
1638
+
1639
+ if bad:
1640
+ raise TypingError("Modified builtin '%s'" % gvar.name, loc=inst.loc)
1641
+
1642
+ def resolve_call(self, fnty, pos_args, kw_args):
1643
+ """
1644
+ Resolve a call to a given function type. A signature is returned.
1645
+ """
1646
+ if isinstance(fnty, types.FunctionType):
1647
+ return fnty.get_call_type(self, pos_args, kw_args)
1648
+ if isinstance(fnty, types.RecursiveCall) and not self._skip_recursion:
1649
+ # Recursive call
1650
+ disp = fnty.dispatcher_type.dispatcher
1651
+ pysig, args = disp.fold_argument_types(pos_args, kw_args)
1652
+
1653
+ frame = self.context.callstack.match(disp.py_func, args)
1654
+
1655
+ # If the signature is not being compiled
1656
+ if frame is None:
1657
+ sig = self.context.resolve_function_type(
1658
+ fnty.dispatcher_type, pos_args, kw_args
1659
+ )
1660
+ fndesc = disp.overloads[args].fndesc
1661
+ qual = qualifying_prefix(fndesc.modname, fndesc.qualname)
1662
+ fnty.add_overloads(args, qual, fndesc.uid)
1663
+ return sig
1664
+
1665
+ fnid = frame.func_id
1666
+ qual = qualifying_prefix(fnid.modname, fnid.func_qualname)
1667
+ fnty.add_overloads(args, qual, fnid.unique_id)
1668
+ # Resume propagation in parent frame
1669
+ return_type = frame.typeinfer.return_types_from_partial()
1670
+ # No known return type
1671
+ if return_type is None:
1672
+ raise TypingError("cannot type infer runaway recursion")
1673
+
1674
+ sig = typing.signature(return_type, *args)
1675
+ sig = sig.replace(pysig=pysig)
1676
+ # Keep track of unique return_type
1677
+ frame.add_return_type(return_type)
1678
+ return sig
1679
+ else:
1680
+ # Normal non-recursive call
1681
+ return self.context.resolve_function_type(fnty, pos_args, kw_args)
1682
+
1683
+ def typeof_global(self, inst, target, gvar):
1684
+ try:
1685
+ typ = self.resolve_value_type(inst, gvar.value)
1686
+ except TypingError as e:
1687
+ if (
1688
+ gvar.name == self.func_id.func_name
1689
+ and gvar.name in _temporary_dispatcher_map
1690
+ ):
1691
+ # Self-recursion case where the dispatcher is not (yet?) known
1692
+ # as a global variable
1693
+ typ = types.Dispatcher(_temporary_dispatcher_map[gvar.name])
1694
+ else:
1695
+ from numba.misc import special
1696
+
1697
+ nm = gvar.name
1698
+ # check if the problem is actually a name error
1699
+ func_glbls = self.func_id.func.__globals__
1700
+ if (
1701
+ nm not in func_glbls.keys()
1702
+ and nm not in special.__all__
1703
+ and nm not in __builtins__.keys()
1704
+ and nm not in self.func_id.code.co_freevars
1705
+ ):
1706
+ errstr = "NameError: name '%s' is not defined"
1707
+ msg = _termcolor.errmsg(errstr % nm)
1708
+ e.patch_message(msg)
1709
+ raise
1710
+ else:
1711
+ msg = _termcolor.errmsg("Untyped global name '%s':" % nm)
1712
+ msg += " %s" # interps the actual error
1713
+
1714
+ # if the untyped global is a numba internal function then add
1715
+ # to the error message asking if it's been imported.
1716
+
1717
+ if nm in special.__all__:
1718
+ tmp = (
1719
+ "\n'%s' looks like a Numba internal function, has "
1720
+ "it been imported (i.e. 'from numba import %s')?\n"
1721
+ % (nm, nm)
1722
+ )
1723
+ msg += _termcolor.errmsg(tmp)
1724
+ e.patch_message(msg % e)
1725
+ raise
1726
+
1727
+ if isinstance(typ, types.Dispatcher) and typ.dispatcher.is_compiling:
1728
+ # Recursive call
1729
+ callstack = self.context.callstack
1730
+ callframe = callstack.findfirst(typ.dispatcher.py_func)
1731
+ if callframe is not None:
1732
+ typ = types.RecursiveCall(typ)
1733
+ else:
1734
+ raise NotImplementedError(
1735
+ "call to %s: unsupported recursion" % typ.dispatcher
1736
+ )
1737
+
1738
+ if isinstance(typ, types.Array):
1739
+ # Global array in nopython mode is constant
1740
+ typ = typ.copy(readonly=True)
1741
+
1742
+ if isinstance(typ, types.BaseAnonymousTuple):
1743
+ # if it's a tuple of literal types, swap the type for the more
1744
+ # specific literal version
1745
+ literaled = [types.maybe_literal(x) for x in gvar.value]
1746
+ if all(literaled):
1747
+ typ = types.Tuple(literaled)
1748
+
1749
+ # if any of the items in the tuple are arrays, they need to be
1750
+ # typed as readonly, mutating an array in a global container
1751
+ # is not supported (should be compile time constant etc).
1752
+ def mark_array_ro(tup):
1753
+ newtup = []
1754
+ for item in tup.types:
1755
+ if isinstance(item, types.Array):
1756
+ item = item.copy(readonly=True)
1757
+ elif isinstance(item, types.BaseAnonymousTuple):
1758
+ item = mark_array_ro(item)
1759
+ newtup.append(item)
1760
+ return types.BaseTuple.from_types(newtup)
1761
+
1762
+ typ = mark_array_ro(typ)
1763
+
1764
+ self.sentry_modified_builtin(inst, gvar)
1765
+ # Setting literal_value for globals because they are handled
1766
+ # like const value in numba
1767
+ lit = types.maybe_literal(gvar.value)
1768
+ # The user may have provided the type for this variable already.
1769
+ # In this case, call add_type() to make sure the value type is
1770
+ # consistent. See numba.tests.test_array_reductions
1771
+ # TestArrayReductions.test_array_cumsum for examples.
1772
+ # Variable type locked by using the locals dict.
1773
+ tv = self.typevars[target.name]
1774
+ if tv.locked:
1775
+ tv.add_type(lit or typ, loc=inst.loc)
1776
+ else:
1777
+ self.lock_type(target.name, lit or typ, loc=inst.loc)
1778
+ self.assumed_immutables.add(inst)
1779
+
1780
+ def typeof_expr(self, inst, target, expr):
1781
+ if expr.op == "call":
1782
+ self.typeof_call(inst, target, expr)
1783
+ elif expr.op in ("getiter", "iternext"):
1784
+ self.typeof_intrinsic_call(inst, target, expr.op, expr.value)
1785
+ elif expr.op == "exhaust_iter":
1786
+ constraint = ExhaustIterConstraint(
1787
+ target.name, count=expr.count, iterator=expr.value, loc=expr.loc
1788
+ )
1789
+ self.constraints.append(constraint)
1790
+ elif expr.op == "pair_first":
1791
+ constraint = PairFirstConstraint(
1792
+ target.name, pair=expr.value, loc=expr.loc
1793
+ )
1794
+ self.constraints.append(constraint)
1795
+ elif expr.op == "pair_second":
1796
+ constraint = PairSecondConstraint(
1797
+ target.name, pair=expr.value, loc=expr.loc
1798
+ )
1799
+ self.constraints.append(constraint)
1800
+ elif expr.op == "binop":
1801
+ self.typeof_intrinsic_call(
1802
+ inst, target, expr.fn, expr.lhs, expr.rhs
1803
+ )
1804
+ elif expr.op == "inplace_binop":
1805
+ self.typeof_intrinsic_call(
1806
+ inst, target, expr.fn, expr.lhs, expr.rhs
1807
+ )
1808
+ elif expr.op == "unary":
1809
+ self.typeof_intrinsic_call(inst, target, expr.fn, expr.value)
1810
+ elif expr.op == "static_getitem":
1811
+ constraint = StaticGetItemConstraint(
1812
+ target.name,
1813
+ value=expr.value,
1814
+ index=expr.index,
1815
+ index_var=expr.index_var,
1816
+ loc=expr.loc,
1817
+ )
1818
+ self.constraints.append(constraint)
1819
+ self.calls.append((inst.value, constraint))
1820
+ elif expr.op == "getitem":
1821
+ self.typeof_intrinsic_call(
1822
+ inst,
1823
+ target,
1824
+ operator.getitem,
1825
+ expr.value,
1826
+ expr.index,
1827
+ )
1828
+ elif expr.op == "typed_getitem":
1829
+ constraint = TypedGetItemConstraint(
1830
+ target.name,
1831
+ value=expr.value,
1832
+ dtype=expr.dtype,
1833
+ index=expr.index,
1834
+ loc=expr.loc,
1835
+ )
1836
+ self.constraints.append(constraint)
1837
+ self.calls.append((inst.value, constraint))
1838
+
1839
+ elif expr.op == "getattr":
1840
+ constraint = GetAttrConstraint(
1841
+ target.name,
1842
+ attr=expr.attr,
1843
+ value=expr.value,
1844
+ loc=inst.loc,
1845
+ inst=inst,
1846
+ )
1847
+ self.constraints.append(constraint)
1848
+ elif expr.op == "build_tuple":
1849
+ constraint = BuildTupleConstraint(
1850
+ target.name, items=expr.items, loc=inst.loc
1851
+ )
1852
+ self.constraints.append(constraint)
1853
+ elif expr.op == "build_list":
1854
+ constraint = BuildListConstraint(
1855
+ target.name, items=expr.items, loc=inst.loc
1856
+ )
1857
+ self.constraints.append(constraint)
1858
+ elif expr.op == "build_set":
1859
+ constraint = BuildSetConstraint(
1860
+ target.name, items=expr.items, loc=inst.loc
1861
+ )
1862
+ self.constraints.append(constraint)
1863
+ elif expr.op == "build_map":
1864
+ constraint = BuildMapConstraint(
1865
+ target.name,
1866
+ items=expr.items,
1867
+ special_value=expr.literal_value,
1868
+ value_indexes=expr.value_indexes,
1869
+ loc=inst.loc,
1870
+ )
1871
+ self.constraints.append(constraint)
1872
+ elif expr.op == "cast":
1873
+ self.constraints.append(
1874
+ Propagate(dst=target.name, src=expr.value.name, loc=inst.loc)
1875
+ )
1876
+ elif expr.op == "phi":
1877
+ for iv in expr.incoming_values:
1878
+ if iv is not ir.UNDEFINED:
1879
+ self.constraints.append(
1880
+ Propagate(dst=target.name, src=iv.name, loc=inst.loc)
1881
+ )
1882
+ elif expr.op == "make_function":
1883
+ self.lock_type(
1884
+ target.name,
1885
+ types.MakeFunctionLiteral(expr),
1886
+ loc=inst.loc,
1887
+ literal_value=expr,
1888
+ )
1889
+
1890
+ elif expr.op == "undef":
1891
+ self.add_type(target.name, types._undef_var, loc=inst.loc)
1892
+
1893
+ else:
1894
+ msg = "Unsupported op-code encountered: %s" % expr
1895
+ raise UnsupportedError(msg, loc=inst.loc)
1896
+
1897
+ def typeof_call(self, inst, target, call):
1898
+ constraint = CallConstraint(
1899
+ target.name,
1900
+ call.func.name,
1901
+ call.args,
1902
+ call.kws,
1903
+ call.vararg,
1904
+ loc=inst.loc,
1905
+ )
1906
+ self.constraints.append(constraint)
1907
+ self.calls.append((inst.value, constraint))
1908
+
1909
+ def typeof_intrinsic_call(self, inst, target, func, *args):
1910
+ constraint = IntrinsicCallConstraint(
1911
+ target.name, func, args, kws=(), vararg=None, loc=inst.loc
1912
+ )
1913
+ self.constraints.append(constraint)
1914
+ self.calls.append((inst.value, constraint))
1915
+
1916
+
1917
+ class NullDebug(object):
1918
+ def propagate_started(self):
1919
+ pass
1920
+
1921
+ def propagate_finished(self):
1922
+ pass
1923
+
1924
+ def unify_finished(self, typdict, retty, fntys):
1925
+ pass
1926
+
1927
+
1928
+ class TypeInferDebug(object):
1929
+ def __init__(self, typeinfer):
1930
+ self.typeinfer = typeinfer
1931
+
1932
+ def _dump_state(self):
1933
+ print("---- type variables ----")
1934
+ pprint([v for k, v in sorted(self.typeinfer.typevars.items())])
1935
+
1936
+ def propagate_started(self):
1937
+ print("propagate".center(80, "-"))
1938
+
1939
+ def propagate_finished(self):
1940
+ self._dump_state()
1941
+
1942
+ def unify_finished(self, typdict, retty, fntys):
1943
+ print("Variable types".center(80, "-"))
1944
+ pprint(typdict)
1945
+ print("Return type".center(80, "-"))
1946
+ pprint(retty)
1947
+ print("Call types".center(80, "-"))
1948
+ pprint(fntys)