diff --git a/src/mtype.c b/src/mtype.c index 5c9b4656f2b6..dd8ddffedc14 100644 --- a/src/mtype.c +++ b/src/mtype.c @@ -5855,8 +5855,25 @@ MATCH TypeFunction::callMatch(Type *tthis, Expressions *args, int flag) { //printf("%s of type %s implicitConvTo %s\n", arg->toChars(), targ->toChars(), tprm->toChars()); if (flag) + { // for partial ordering, value is an irrelevant mockup, just look at the type - m = targ->implicitConvTo(tprm); +#if DMDV2 + /* Special rule for partial ordering between bool and non-bool integral types. + * In basic, bool is more specialized than other integers. + * But partial ordering should prefer integer parameters for integer literal arguments. + * So reverse match result in here - bool is less specialized than other integer types. + * See Bugzilla 9999. + */ + Type *tba = targ->toBasetype(); + Type *tbp = tprm->toBasetype(); + if (tba->ty == Tbool && (tbp->ty != Tbool && tbp->isintegral())) + m = MATCHnomatch; + else if ((tba->ty != Tbool && tba->isintegral()) && tbp->ty == Tbool) + m = MATCHconvert; + else +#endif + m = targ->implicitConvTo(tprm); + } else m = arg->implicitConvTo(tprm); //printf("match %d\n", m); diff --git a/test/runnable/overload.d b/test/runnable/overload.d index 13491c5935a3..699afea838ec 100644 --- a/test/runnable/overload.d +++ b/test/runnable/overload.d @@ -166,6 +166,56 @@ void test9410() assert(foo(1, S()) == 2); // Fails with: Error: S() is not an lvalue } +/***************************************************/ +// 9999 + +auto foo9999(bool) { return 1; } +auto foo9999(long) { return 2; } + +void test9999() +{ + enum int x0 = 0, x1 = 1, x2 = 2; + enum byte b0 = 0, b1 = 1, b2 = 2; + + assert(foo9999(true) == 1); + assert(foo9999(false) == 1); + assert(foo9999(0) == 2); + assert(foo9999(1) == 2); + assert(foo9999(2) == 2); + assert(foo9999(x0) == 2); + assert(foo9999(x1) == 2); + assert(foo9999(x2) == 2); + assert(foo9999(b0) == 2); + assert(foo9999(b1) == 2); + assert(foo9999(b2) == 2); + assert(foo9999('\0') == 2); + assert(foo9999('\1') == 2); + assert(foo9999('\2') == 2); + + void fooInt(int) {} + void fooLong(long) {} + void fooBool(bool) {} + + // bool value matches to integer types + bool f; + fooInt(true); + fooInt(false); + fooInt(f); + fooLong(true); + fooLong(false); + fooLong(f); + + // Integer literal 0 and 1 matches to bool + fooBool(0); + fooBool(1); + // from core.stdc.windows.windows + enum : int { FALSE = 0, TRUE = 1 } + fooBool(FALSE); + fooBool(TRUE); + // other integer literals don't match to bool + static assert(!__traits(compiles, fooBool(2))); +} + /***************************************************/ int main() @@ -176,6 +226,7 @@ int main() test8668(); test8943(); test9410(); + test9999(); printf("Success\n"); return 0;