diff --git a/src/expression.c b/src/expression.c index 50bae1b1ad41..29075ec07edc 100644 --- a/src/expression.c +++ b/src/expression.c @@ -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 || @@ -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) && diff --git a/test/runnable/test42.d b/test/runnable/test42.d index a04b06d2be21..08d64dfc2202 100644 --- a/test/runnable/test42.d +++ b/test/runnable/test42.d @@ -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 } /***************************************************/