[Issue 17336] New: Implicit type conversion of size_t.init to int causes standard type compatibility test to break

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Thu Apr 20 12:26:31 PDT 2017


https://issues.dlang.org/show_bug.cgi?id=17336

          Issue ID: 17336
           Summary: Implicit type conversion of size_t.init to int causes
                    standard type compatibility test to break
           Product: D
           Version: D2
          Hardware: x86_64
                OS: All
            Status: NEW
          Severity: normal
          Priority: P1
         Component: dmd
          Assignee: nobody at puremagic.com
          Reporter: hsteoh at quickfur.ath.cx

Code:
------
void main()
{
    struct B {
        B opBinary(string op : "+")(int b) { return this; }
    }
    static if (is(typeof(B.init + size_t.init) : B))
    {
        size_t x = 1;
        B b1, b2;
        b1 = b2 + x; // line 9
    }
}
------

N.B.: This code was reduced from original generic code where B is a template
parameter.

The condition `is(typeof(B.init + size_t.init))` is, AFAIK, the standard way to
test if some given type B is compatible with certain operations, in this case
addition of a size_t.  It would seem, on the surface, that this condition would
fail, because B.opBinary requires an int, and size_t does not implicitly
convert to int, so the static if block should be skipped by the compiler.

However, here is what the compiler has to say:

------
test.d(9): Error: incompatible types for ((b2) + (x)): 'B' and 'ulong'
------

How did the condition pass?  Well, a little investigation showed that if
`size_t.init` is replaced by `size_t.max`, then the condition does, indeed, not
pass, and the static if block is not compiled (no compile error).

This appears to indicate that the compiler is, for whatever reason, maybe
overzealous VRP, implicitly converting size_t.init (which is 0L) to int(0),
thus causing the standard type compatibility check idiom to fail. Using
size_t.max instead forces the compiler to retain the type as size_t because
size_t.max cannot fit inside an int, thereby achieving the correct behaviour.

Expected behaviour: if size_t is explicitly asked for, as in size_t.init,
shouldn't the compiler suppress implicit conversion to a smaller type??!

--


More information about the Digitalmars-d-bugs mailing list