Should return dchar.
This breaks range functions like chain, example:
string name = "Jack";
auto app = appender!string();
app.put(
chain(name, toChars(10))
);
Error: template std.array.Appender!string.Appender.put cannot deduce function from argument types !()(Result), candidates are:
/usr/local/Cellar/dmd/2.073.0/include/dlang/dmd/std/array.d(2820): std.array.Appender!string.Appender.put(U)(U item) if (canPutItem!U)
/usr/local/Cellar/dmd/2.073.0/include/dlang/dmd/std/array.d(2848): std.array.Appender!string.Appender.put(Range)(Range items) if (canPutConstRange!Range)
/usr/local/Cellar/dmd/2.073.0/include/dlang/dmd/std/array.d(2857): std.array.Appender!string.Appender.put(Range)(Range items) if (canPutRange!Range)
Comment #1 by jack — 2017-02-07T18:40:07Z
Raising the priority of this because chain is really gimped by this bug. Every call to chain with character ranges requires an extra call to map to cast the results for it to work correctly.
Comment #2 by hsteoh — 2017-04-28T18:41:32Z
It's not just CommonType!(dchar, char); it's a whole slew of cases that are incorrectly handled:
------------
void main() {
import std.range;
struct CharRange(C) {
C ch = 'a';
@property C front() { return ch; }
@property bool empty() { return ch == C.init; }
void popFront() { ch = C.init; }
}
CharRange!char charRange;
CharRange!wchar wcharRange;
CharRange!dchar dcharRange;
pragma(msg, "char + char: ", ElementType!(typeof(chain(charRange, charRange))));
pragma(msg, "char + wchar: ", ElementType!(typeof(chain(charRange, wcharRange))));
pragma(msg, "wchar + char: ", ElementType!(typeof(chain(wcharRange, charRange))));
pragma(msg, "char + dchar: ", ElementType!(typeof(chain(charRange, dcharRange))));
pragma(msg, "dchar + char: ", ElementType!(typeof(chain(dcharRange, charRange))));
pragma(msg, "wchar + wchar: ", ElementType!(typeof(chain(wcharRange, wcharRange))));
pragma(msg, "wchar + dchar: ", ElementType!(typeof(chain(wcharRange, dcharRange))));
pragma(msg, "dchar + wchar: ", ElementType!(typeof(chain(dcharRange, wcharRange))));
pragma(msg, "dchar + dchar: ", ElementType!(typeof(chain(dcharRange, dcharRange))));
}
------------
Output:
------------
char + char: char
char + wchar: int
wchar + char: int
char + dchar: uint
dchar + char: uint
wchar + wchar: wchar
wchar + dchar: uint
dchar + wchar: uint
dchar + dchar: dchar
------------
Seems like the only time the correct common type is deduced, as far as character types are concerned, is when both are types are the same. All the other cases are worthy of a WAT?.
Comment #3 by hsteoh — 2017-04-28T18:43:26Z
Unfortunately, it looks like CommonType is implemented using the ?: ternary operator, meaning that it's the *compiler* that's producing these crazy results.
Comment #4 by hsteoh — 2017-04-28T18:49:27Z
Looks like this is implemented in the hairball function typeMerge() in src/ddmd/dcast.d. I'll try to trace through and see if I can find an obvious problem, but I'm not sure if I'll be able to.
Comment #5 by hsteoh — 2017-04-28T19:10:19Z
Hmph. Looks like the problem is that the very first thing typeMerge() does is to do integer promotion on the incoming types. Thus, right from the start, we've already lost the original character types. The only reason this hasn't shown up earlier is because when the two types are equal, typeMerge() is not called. So we're essentially only saved "by accident".
Oddly enough, there is an `if (op != TOKquestion || ...)`, which *seems* to suggest that the intent of the code is *not* to do integer promotions if ?: is involved. However, the second clause of the if condition, `t1b.ty != t2b.ty`, appears to be always true, so the check for ?: would appear to be always irrelevant. It would seem that && was intended here rather than ||, but I've to look more carefully to make sure this isn't going to cause massive code breakage...
Comment #6 by hsteoh — 2017-04-28T19:46:48Z
Wow, this bug goes way back to issue #5659. Looks like it was partially fixed back then, but there are still cases not fixed.
Comment #7 by jack — 2017-04-28T22:27:17Z
Raising this to critical because this is actually a bug in DMD's type inference and not a Phobos bug.
Comment #8 by schveiguy — 2017-04-30T20:29:10Z
I'm not sure the cure is better than the disease.
If CommonType!(dchar, char) becomes dchar, then chaining together a range of dchar with a range of char *integer promotes* the char range to dchar. It doesn't decode it!
Comment #9 by john.loughran.colvin — 2017-07-05T13:49:39Z