Skip to content

Commit

Permalink
Additional fix for typing concat expression
Browse files Browse the repository at this point in the history
In a concatenation for array vs. element, check that whether array literal operands can work like polymorphic expression.
  • Loading branch information
9rnsr committed Jun 13, 2015
1 parent 4d5c653 commit 38da94b
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 24 deletions.
75 changes: 51 additions & 24 deletions src/expression.c
Original file line number Diff line number Diff line change
Expand Up @@ -12408,6 +12408,7 @@ Expression *CatExp::semantic(Scope *sc)
Type *tb1next = tb1->nextOf();
Type *tb2next = tb2->nextOf();

// Check for: array ~ array
if (tb1next && tb2next &&
(tb1next->implicitConvTo(tb2next) >= MATCHconst ||
tb2next->implicitConvTo(tb1next) >= MATCHconst ||
Expand All @@ -12430,40 +12431,66 @@ Expression *CatExp::semantic(Scope *sc)
* becoming:
* a ~ cast(int[])[];
*/
goto Lpeer;
}
else if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
e2->implicitConvTo(tb1next) >= MATCHconvert &&
tb2->ty != Tvoid)

// Check for: array ~ element
if ((tb1->ty == Tsarray || tb1->ty == Tarray) && tb2->ty != Tvoid)
{
if (e2->checkPostblit(sc, tb2))
return new ErrorExp();
e2 = e2->implicitCastTo(sc, tb1next);
type = tb1next->arrayOf();
if (tb2->ty == Tarray || tb2->ty == Tsarray)
if (e1->op == TOKarrayliteral && e1->implicitConvTo(tb2->arrayOf()))
{
// Make e2 into [e2]
e2 = new ArrayLiteralExp(e2->loc, e2);
e2->type = type;
if (e2->checkPostblit(sc, tb2))
return new ErrorExp();
e1 = e1->implicitCastTo(sc, tb2->arrayOf());
type = tb2->arrayOf();
goto L2elem;
}
if (e2->implicitConvTo(tb1next) >= MATCHconvert)
{
if (e2->checkPostblit(sc, tb2))
return new ErrorExp();
e2 = e2->implicitCastTo(sc, tb1next);
type = tb1next->arrayOf();
L2elem:
if (tb2->ty == Tarray || tb2->ty == Tsarray)
{
// Make e2 into [e2]
e2 = new ArrayLiteralExp(e2->loc, e2);
e2->type = type;
}
return this;
}
return this;
}
else if ((tb2->ty == Tsarray || tb2->ty == Tarray) &&
e1->implicitConvTo(tb2next) >= MATCHconvert &&
tb1->ty != Tvoid)
// Check for: element ~ array
if ((tb2->ty == Tsarray || tb2->ty == Tarray) && tb1->ty != Tvoid)
{
if (e1->checkPostblit(sc, tb1))
return new ErrorExp();
e1 = e1->implicitCastTo(sc, tb2next);
type = tb2next->arrayOf();
if (tb1->ty == Tarray || tb1->ty == Tsarray)
if (e2->op == TOKarrayliteral &&
e2->implicitConvTo(tb1->arrayOf()))
{
// Make e1 into [e1]
e1 = new ArrayLiteralExp(e1->loc, e1);
e1->type = type;
if (e1->checkPostblit(sc, tb1))
return new ErrorExp();
e2 = e2->implicitCastTo(sc, tb1->arrayOf());
type = tb1->arrayOf();
goto L1elem;
}
if (e1->implicitConvTo(tb2next) >= MATCHconvert)
{
if (e1->checkPostblit(sc, tb1))
return new ErrorExp();
e1 = e1->implicitCastTo(sc, tb2next);
type = tb2next->arrayOf();
L1elem:
if (tb1->ty == Tarray || tb1->ty == Tsarray)
{
// Make e1 into [e1]
e1 = new ArrayLiteralExp(e1->loc, e1);
e1->type = type;
}
return this;
}
return this;
}

Lpeer:
if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
(tb2->ty == Tsarray || tb2->ty == Tarray) &&
(tb1next->mod || tb2next->mod) &&
Expand Down
32 changes: 32 additions & 0 deletions test/runnable/test42.d
Original file line number Diff line number Diff line change
Expand Up @@ -5493,6 +5493,38 @@ void test14682a()

void test14682b()
{
// operands
int[] a1;
int[][] a2;
int[][][] a3;
int[][][][] a4;

// results
int[][] r2a = [[], [] ]; assert(r2a.length == 2 && r2a[0].length == 0 && r2a[1].length == 0);
//int[][][] r3a = [[], [[]] ]; // should work, but doesn't
//int[][][][] r4a = [[], [[[]]]]; // should work, but doesn't
int[][][] r3a; { r3a.length = 2; r3a[0] = []; r3a[1] = [[]] ; }
assert(r3a.length == 2 && r3a[0].length == 0 && r3a[1].length == 1 && r3a[1][0].length == 0);
int[][][][] r4a; { r4a.length = 2; r4a[0] = []; r4a[1] = [[[]]]; }
assert(r4a.length == 2 && r4a[0].length == 0 && r4a[1].length == 1 && r4a[1][0].length == 1 && r4a[1][0][0].length == 0);
// ----
int[][] r2b = [ [] , []]; assert(r2b.length == 2 && r2b[1].length == 0 && r2b[0].length == 0);
//int[][][] r3b = [ [[]] , []]; // should work, but doesn't
//int[][][][] r4b = [[[[]]], []]; // should work, but doesn't
int[][][] r3b; { r3b.length = 2; r3b[0] = [[]] ; r3b[1] = []; }
assert(r3b.length == 2 && r3b[1].length == 0 && r3b[0].length == 1 && r3b[0][0].length == 0);
int[][][][] r4b; { r4b.length = 2; r4b[0] = [[[]]]; r4b[1] = []; }
assert(r4b.length == 2 && r4b[1].length == 0 && r4b[0].length == 1 && r4b[0][0].length == 1 && r4b[0][0][0].length == 0);

// ArrayLiteralExp conforms to the typeof(LHS)->arrayOf().
{ auto x = a1 ~ [[]] ; static assert(is(typeof(x) == typeof(a1)[])); assert(x == r2a); } // fix
{ auto x = a2 ~ [[[]]] ; static assert(is(typeof(x) == typeof(a2)[])); assert(x == r3a); } // fix
{ auto x = a3 ~ [[[[]]]]; static assert(is(typeof(x) == typeof(a3)[])); assert(x == r4a); } // fix

// ArrayLiteralExp conforms to the typeof(RHS)->arrayOf().
{ auto x = [[]] ~ a1; static assert(is(typeof(x) == typeof(a1)[])); assert(x == r2b); } // fix
{ auto x = [[[]]] ~ a2; static assert(is(typeof(x) == typeof(a2)[])); assert(x == r3b); } // fix
{ auto x = [[[[]]]] ~ a3; static assert(is(typeof(x) == typeof(a3)[])); assert(x == r4b); } // fix
}

/***************************************************/
Expand Down

0 comments on commit 38da94b

Please sign in to comment.