wlav / cppyy

Other
387 stars 39 forks source link

template operator< <T> gets resolved as operator<< #171

Open saraedum opened 1 year ago

saraedum commented 1 year ago

With cppyy 2.4.2 (which is currently the latest version on conda-forge) I see the following error:

   >       assert r > 0 and r < 1
  E       TypeError: Template method resolution failed:
  E         none of the 4 overloaded methods succeeded. Full details:
  E         bool exactreal::RealNumber::operator<(const exactreal::RealNumber&) =>
  E           TypeError: could not convert argument 1
  E         bool exactreal::RealNumber::operator<(const exactreal::Arf&) =>
  E           TypeError: could not convert argument 1
  E         bool exactreal::RealNumber::operator<(const mpq_class&) =>
  E           TypeError: could not convert argument 1
  E         bool exactreal::RealNumber::operator<(const mpz_class&) =>
  E           TypeError: could not convert argument 1
  E         bool exactreal::RealNumber::operator<<int>(int rhs) =>
  E           runtime_error: failed to resolve function

  real_number.py:36: TypeError
  ----------------------------- Captured stderr call -----------------------------
  input_line_34:6:85: error: no member named 'operator<<' in 'exactreal::RealNumber'
        new (ret) (bool) (((const exactreal::RealNumber*)obj)->exactreal::RealNumber::operator<<int>(*(int*)args[0]));
                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                         ^
  input_line_34:10:67: error: no member named 'operator<<' in 'exactreal::RealNumber'
        ((const exactreal::RealNumber*)obj)->exactreal::RealNumber::operator<<int>(*(int*)args[0]);

So, an operator< <T> gets resolved to an operator<< it seems. I believe I had seen errors like this before but thought that these had been fixed. Is this a regression of some sort maybe?

This happened in a CI run, the full output is here: https://github.com/flatsurf/exact-real/actions/runs/5311626921/jobs/9615090490?pr=174

I can try to create a smaller reproducer if that's helpful.

The package versions used here were:

cppyy                     2.4.2
cppyy-backend             1.14.10
cppyy-cling               6.27.1
cpycppyy                  1.12.12

I haven't found the time to upgrade cppyy on conda-forge yet. I'll probably try that now and see if that makes a difference.

saraedum commented 1 year ago

Indeed, downgrading to 2.4.1 makes the error go away.

wlav commented 1 year ago

Back from vacation. :)

Yes, this is an old one: https://bitbucket.org/wlav/cppyy/issues/93/missing-space-makes-operator-resolve-to and for that reason, a regression test exists: https://github.com/wlav/cppyy/blob/master/test/test_operators.py#L227

Does this occur only with conda?

saraedum commented 1 year ago

Btw., the linked bitbucket page says: "We can't let you see this page"

saraedum commented 1 year ago

I haven't tried with the cppyy from pip yet. I'll restart the CI to see if it makes a difference.

I would like to see if cppyy 3.0.0 makes the problem go away but I am stuck at packaging it at https://github.com/conda-forge/cppyy-cling-feedstock/pull/56#issuecomment-1598928859.

saraedum commented 1 year ago

I cannot install the cppyy from PyPI in that environment. I get

/Users/runner/miniconda3/envs/test/bin/../include/c++/v1/wchar.h:123:15: fatal error: 'wchar.h' file not found
#include_next <wchar.h>
wlav commented 1 year ago

The /Users seems to indicate MacOS? There have been a range of reports stating that it's not possible to install on Mac, and all are variations on C++ headers not found. I develop on Mac, and all runs fine, so I've not been able to reproduce it. I'll see whether installing miniconda makes it possible to break my setup.

wlav commented 1 year ago

Btw., the linked bitbucket page says: "We can't let you see this page"

I see. Has to do with the repo being provide (I was getting too much spam). This is the reproducer from that report:

>>> import cppyy
>>> cppyy.cppdef("""
... class A {
... template<typename T>
... bool operator<(T t) { return true; }
... };
... """)
True
>>> from cppyy.gbl import A
>>> A() < 1
input_line_21:6:36: error: no member named 'operator<<' in 'A'
      new (ret) (bool) (((A*)obj)->operator<<int>(*(int*)args[0]));
                        ~~~~~~~~~  ^
input_line_21:10:18: error: no member named 'operator<<' in 'A'
      ((A*)obj)->operator<<int>(*(int*)args[0]);
      ~~~~~~~~~  ^
Error in <TClingCallFunc::make_wrapper>: Failed to compile
  ==== SOURCE BEGIN ====
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-security"
__attribute__((used)) extern "C" void __cf_4(void* obj, int nargs, void** args, void* ret)
{
   if (ret) {
      new (ret) (bool) (((A*)obj)->operator<<int>(*(int*)args[0]));
      return;
   }
   else {
      ((A*)obj)->operator<<int>(*(int*)args[0]);
      return;
   }
}
#pragma clang diagnostic pop
  ==== SOURCE END ====
True
wlav commented 1 year ago

I find with HEAD that the code is okay:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-security"
__attribute__((used)) extern "C" void __cf_5(void* obj, int nargs, void** args, void* ret)
{
   if (ret) {
      new (ret) (bool) (((A*)obj)->A::operator< <int>(*(int*)args[0]));
      return;
   }
   else {
      ((A*)obj)->A::operator< <int>(*(int*)args[0]);
      return;
   }
}
#pragma clang diagnostic pop

I'm also a bit surprised b/c operators should have been simply inserted instead of spelled out like this. I'll see why that's not the case here, as simply using < would have prevented any parsing errors.