Skip to content

Commit

Permalink
require opEquals for AA keys
Browse files Browse the repository at this point in the history
- Check that the compiler can generate a runtime function to test AA keys for equality.

- This is necessary to switch the druntime implementation from opCmp to opEquals.
  • Loading branch information
MartinNowak committed May 29, 2014
1 parent f15bd87 commit bfa8d60
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 2 deletions.
19 changes: 18 additions & 1 deletion src/mtype.c
Expand Up @@ -4684,13 +4684,23 @@ printf("index->ito->ito = x%x\n", index->ito->ito);
return Type::terror;
case Tstruct:
{
/* AA's need opCmp. Issue error if not correctly set up.
/* AA's need opEquals and opCmp. Issue error if not correctly set up.
*/
StructDeclaration *sd = ((TypeStruct *)index->toBasetype())->sym;
if (sd->scope)
sd->semantic(NULL);

// duplicate a part of StructDeclaration::semanticTypeInfoMembers
if (sd->xeq &&
sd->xeq->scope &&
sd->xeq->semanticRun < PASSsemantic3done)
{
unsigned errors = global.startGagging();
sd->xeq->semantic3(sd->xeq->scope);
if (global.endGagging(errors))
sd->xeq = sd->xerreq;
}

if (sd->xcmp &&
sd->xcmp->scope &&
sd->xcmp->semanticRun < PASSsemantic3done)
Expand All @@ -4701,6 +4711,13 @@ printf("index->ito->ito = x%x\n", index->ito->ito);
sd->xcmp = sd->xerrcmp;
}

if (sd->xeq == sd->xerreq)
{
error(loc, "associative array key type %s does not have 'const bool opEquals(ref const %s)' member function",
index->toBasetype()->toChars(), sd->toChars());
return Type::terror;
}
// the opCmp requirement can go away once druntime fully switched to using opEquals
if (sd->xcmp == sd->xerrcmp)
{
error(loc, "associative array key type %s does not have 'const int opCmp(ref const %s)' member function",
Expand Down
34 changes: 34 additions & 0 deletions test/fail_compilation/fail11591b.d
@@ -0,0 +1,34 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail11591b.d(16): Error: associative array key type S11591 does not have 'const bool opEquals(ref const S11591)' member function
---
*/

struct S11591
{
bool opEquals(int i) { return false; }
Object o; // needed to suppress compiler generated opEquals
}

void test11591()
{
int[S11591] aa;
}

/*
TEST_OUTPUT:
---
fail_compilation/fail11591b.d(30): Error: associative array key type S12307a does not have 'const bool opEquals(ref const S12307a)' member function
fail_compilation/fail11591b.d(31): Error: associative array key type S12307b does not have 'const bool opEquals(ref const S12307b)' member function
---
*/
struct S12307a { bool opEquals(T : typeof(this))(T) { return false; } }

void test12307()
{
int[S12307a] aa1; // a
int[S12307b] aa2; // b
}

struct S12307b { bool opEquals(T : typeof(this))(T) { return false; } }
2 changes: 1 addition & 1 deletion test/runnable/imports/link12144a.d
Expand Up @@ -9,7 +9,7 @@ struct S8 { bool opEquals(T : typeof(this))(T) { return false; } }
struct S9 { bool opEquals(T : typeof(this))(T) { return false; } }

struct S10 { bool opEquals(T : typeof(this))(T) { return false; } }
struct S11 { bool opEquals(T : typeof(this))(T) { return false; }
struct S11 { bool opEquals(T : typeof(this))(T) const { return false; }
int opCmp(T : typeof(this))(T) const { return 0; } }
struct S12 { bool opEquals(T : typeof(this))(T) { return false; } }
struct S13 { bool opEquals(T : typeof(this))(T) { return false; } }
Expand Down

0 comments on commit bfa8d60

Please sign in to comment.