You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Implicit template instantiation from an annotated Python callable reuses the signature of an earlier callable #151
When a templated function takes a callable F and is called implicitly with an annotated Python function, F is deduced from the annotations only the first time, later calls with a different callable reuse that first instantiation, as long as the call itself succeeds: the new callable gets wrapped with the old signature and silently gives wrong results, see below
Explicit instantiation behaves correctly.
importcppjitcppjit.cppdef(r"""#include <iostream>template <typename F>void call(F f) { std::cout << __PRETTY_FUNCTION__ << std::endl; auto result = f(2.5); std::cout << " -> " << result << std::endl;}""")
defA(x: int) ->int:
returnx*10defB(x: float) ->int:
returnint(x*2)
defC(x: float) ->float:
returnx*2.0cppjit.gbl.call(A) # expected F = int (*)(int), A(2) = 20cppjit.gbl.call(B) # expected F = int (*)(float), B(2.5) = 5cppjit.gbl.call["int (*)(float)"](B) # explicit instantiation of Bcppjit.gbl.call(C) # expected F = float (*)(float), C(2.5) = 5
call(B) uses A's instantiation: 2.5 is truncated to 2 and B returns 4 instead of 5. The call succeeds, so the wrong result is kept. Calling B first, or alone, gives [F = int (*)(float)] -> 5
call(C) also tries A's instantiation first (twice), but C(2) returns the Python float 4.0, which cannot be converted to the int return type. That call raises, and only then is a new float (*)(float) instantiation made from C's annotations, which gives the right result
Activity
fix compiler-research#151
[cpyrt] Deduce a template instantiation per annotated Python callable
fix compiler-research#151