Bug 21884 – [betterC] can't compare arrays with -betterC

Status
NEW
Severity
minor
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2021-04-30T20:34:29Z
Last change time
2024-12-13T19:16:03Z
Keywords
betterC
Assigned to
No Owner
Creator
Blatnik
Moved to GitHub: dmd#19915 →

Comments

Comment #0 by blatblatnik — 2021-04-30T20:34:29Z
Without -betterC, the following code compiles: bool fine() { float[2] a; return a == a; } It does exactly what you'd expect, and I'm happy. With -betterC however: bool error() { float[2] a; return a == a; // Error: `TypeInfo` cannot be used with -betterC. } I don't know why dmd needs to emit type info for array comparisons. The type is clearly known at compile time. I don't see why this wouldn't be possible in -betterC. By itself, this wouldn't be a massive issue, because we can also do bool fine() { float[2] a; return a[] == a[]; } And now this will compile and work as expected in -betterC. In fact I even prefer this syntax personally since it's more consistent with other array operations. But this doesn't work for multi-dimensional arrays. bool error() { float[2][2] a; return a == a; // Error: `TypeInfo` cannot be used with -betterC. return a[] == a[]; // Error: `TypeInfo` cannot be used with -betterC. } And it definitely should work - at least one of these should work.
Comment #1 by blatblatnik — 2021-04-30T20:40:48Z
It's also important to point out that fixing the first issue (type[N] == type[N]) would also fix the second issue. The only reason type[N][] == type[N][] doesn't work, is because it internally tries to compare every element in the two slices, and every element just happens to be a type[N]. So if type[N] == type[N] is fixed, both types of notation would work.
Comment #2 by blatblatnik — 2021-04-30T20:50:13Z
It also seems like the fixed size array comparisons (type[N] == type[N]) are implemented internally in DMD. However slice comparisons (type[N][] == type[N][]) are implemented in the runtime. The compiler converts float[2][2] a; bool b = a[] == b[]; into: float[2][2] a; bool b = core.internal.array.equality.__equals!(float[2], float[2])(a[], a[]); And this __equals template is something we can change very easily without digging through the compiler. The offending lines in this function effectively try to do: foreach(i; 0 .. a.length) if (a[i] != a[i]) return false; return true; But a[i] is a float[2], which can't be compared in -betterC.. If we had a special case for arrays that did this instead foreach(i; 0 .. a.length) if (a[i][] != a[i][]) return false; return true; Then at least type[N][] == type[N][] would work, until a better fix was found for type[N] == type[N].
Comment #3 by blatblatnik — 2021-04-30T20:58:18Z
Here's a "fixed" version of core.internal.array.equality.__equals that acts correctly in betterC. I'm sure it could be done better but at least it works. bool __equals(T1, T2)(scope T1[] lhs, scope T2[] rhs) if (!__traits(isScalar, T1) || !__traits(isScalar, T2)) { if (lhs.length != rhs.length) return false; if (lhs.length == 0) return true; static if (useMemcmp!(T1, T2)) { if (!__ctfe) { static bool trustedMemcmp(scope T1[] lhs, scope T2[] rhs) @trusted @nogc nothrow pure { pragma(inline, true); import core.stdc.string : memcmp; return memcmp(cast(void*) lhs.ptr, cast(void*) rhs.ptr, lhs.length * T1.sizeof) == 0; } return trustedMemcmp(lhs, rhs); } } foreach (const i; 0 .. lhs.length) { static if (__traits(isStaticArray, at(lhs, 0))) // "Fix" for -betterC { if (at(lhs, i)[] != at(rhs, i)[]) // T1[N] != T2[N] doesn't compile with -betterC. return false; } else { if (at(lhs, i) != at(rhs, i)) return false; } } return true; }
Comment #4 by robert.schadek — 2024-12-13T19:16:03Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19915 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB