@@ -462,28 +462,42 @@ nothrow:
462462 return buf.extractString();
463463 }
464464
465+ /* Checks for equivalence,
466+ * a) comparing the filename contents (not the pointer), case-
467+ * insensitively on Windows, and
468+ * b) ignoring charnum if `global.params.showColumns` is false.
469+ */
465470 extern (C++ ) bool equals(ref const (Loc) loc) const
466471 {
467472 return (! global.params.showColumns || charnum == loc.charnum) &&
468473 linnum == loc.linnum &&
469474 FileName.equals(filename, loc.filename);
470475 }
471476
472- extern (D ) bool opEquals (Loc loc) const pure
477+ /* opEquals() / toHash() for AA key usage:
478+ *
479+ * Compare filename contents (case-sensitively on Windows too), not
480+ * the pointer - a static foreach loop repeatedly mixing in a mixin
481+ * may lead to multiple equivalent filenames (`foo.d-mixin-<line>`),
482+ * e.g., for test/runnable/test18880.d.
483+ */
484+ extern (D ) bool opEquals (ref const (Loc) loc) const @trusted pure nothrow @nogc
473485 {
486+ import core.stdc.string : strcmp;
487+
474488 return charnum == loc.charnum &&
475489 linnum == loc.linnum &&
476- FileName.equals(filename, loc.filename);
490+ (filename == loc.filename ||
491+ (filename && loc.filename && strcmp(filename, loc.filename) == 0 ));
477492 }
478493
479- extern (D ) hash_t toHash() const pure
494+ extern (D ) size_t toHash() const @trusted pure nothrow
480495 {
481- import dmd.root.hash;
482- import dmd.utils;
496+ import dmd.utils : toDString;
483497
484498 auto hash = hashOf(linnum);
485- hash = mixHash(hash, hashOf(charnum) );
486- hash = mixHash(hash, hashOf(filename.toDString) );
499+ hash = hashOf(charnum, hash );
500+ hash = hashOf(filename.toDString, hash );
487501 return hash;
488502 }
489503
0 commit comments