From b338603d76e33dee12226495bbfde99133b98c43 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Wed, 8 Jun 2022 13:00:44 +0100 Subject: [PATCH 1/9] Make `new` on an associative array allocate the AA Impl Fixes https://issues.dlang.org/show_bug.cgi?id=10535. --- compiler/src/dmd/e2ir.d | 10 +++++++++ compiler/src/dmd/expressionsem.d | 35 +++++++++++++++++++------------- compiler/src/dmd/parse.d | 9 +++----- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/compiler/src/dmd/e2ir.d b/compiler/src/dmd/e2ir.d index c81f12411e7c..8ba03958db2d 100644 --- a/compiler/src/dmd/e2ir.d +++ b/compiler/src/dmd/e2ir.d @@ -1301,6 +1301,16 @@ elem* toElem(Expression e, IRState *irs) } e = el_combine(ezprefix, e); } + else if (auto taa = t.isTypeAArray()) + { + Symbol *s = aaGetSymbol(taa, "New", 0); + elem *ti = getTypeInfo(ne.loc, taa, irs); + // aaNew(ti) + elem *ep = el_params(ti, null); + e = el_bin(OPcall, TYnptr, el_var(s), ep); + elem_setLoc(e, ne.loc); + return e; + } else { ne.error("internal compiler error: cannot new type `%s`\n", t.toChars()); diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index b3633eba9d7d..ca97cd89f0a9 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -3463,8 +3463,17 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor if (!exp.arguments && exp.newtype.isTypeSArray()) { auto ts = exp.newtype.isTypeSArray(); - edim = ts.dim; - exp.newtype = ts.next; + // check `new Value[Key]` + ts.dim = ts.dim.expressionSemantic(sc); + if (ts.dim.op == EXP.type) + { + exp.newtype = new TypeAArray(ts.next, ts.dim.isTypeExp().type); + } + else + { + edim = ts.dim; + exp.newtype = ts.next; + } } ClassDeclaration cdthis = null; @@ -3518,18 +3527,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor { return setError(); } - //https://issues.dlang.org/show_bug.cgi?id=20547 - //exp.arguments are the "parameters" to [], not to a real function - //so the errors that come from preFunctionParameters are misleading - if (originalNewtype.ty == Tsarray) - { - if (preFunctionParameters(sc, exp.arguments, false)) - { - exp.error("cannot create a `%s` with `new`", originalNewtype.toChars()); - return setError(); - } - } - else if (preFunctionParameters(sc, exp.arguments)) + if (preFunctionParameters(sc, exp.arguments)) { return setError(); } @@ -3885,6 +3883,15 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor exp.type = exp.type.pointerTo(); } + else if (tb.ty == Taarray) + { + // e.g. `new Alias(args)` + if (nargs) + { + exp.error("`new` cannot take arguments for an associative array"); + return setError(); + } + } else { exp.error("cannot create a `%s` with `new`", exp.type.toChars()); diff --git a/compiler/src/dmd/parse.d b/compiler/src/dmd/parse.d index 4e3fd533c18e..7fa2d074131f 100644 --- a/compiler/src/dmd/parse.d +++ b/compiler/src/dmd/parse.d @@ -9312,13 +9312,10 @@ LagainStc: { AST.TypeAArray taa = cast(AST.TypeAArray)t; AST.Type index = taa.index; + // `new Type[expr]` is a static array auto edim = AST.typeToExpression(index); - if (!edim) - { - error("cannot create a `%s` with `new`", t.toChars); - return new AST.NullExp(loc); - } - t = new AST.TypeSArray(taa.next, edim); + if (edim) + t = new AST.TypeSArray(taa.next, edim); } else if (token.value == TOK.leftParenthesis && t.ty != Tsarray) { From 14bea2e293ae03cec4ce8d6d498b22e2e5974a45 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Wed, 29 Jun 2022 17:32:11 +0100 Subject: [PATCH 2/9] Add test --- test/runnable/newaa.d | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 test/runnable/newaa.d diff --git a/test/runnable/newaa.d b/test/runnable/newaa.d new file mode 100644 index 000000000000..0e9bedfad3a1 --- /dev/null +++ b/test/runnable/newaa.d @@ -0,0 +1,18 @@ +void main() +{ + alias AA = int[string]; + // aa is not ref + void test(AA aa) + { + aa[""] = 0; + } + auto aa = new AA(); + auto ab = new int[string]; + auto ac = new typeof(aa); + test(aa); + test(ab); + test(ac); + assert(aa.length); + assert(ab.length); + assert(ac.length); +} From ba394c8198dccd4a183c6cd7e78bc47a72bf831b Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Wed, 29 Jun 2022 17:38:37 +0100 Subject: [PATCH 3/9] Update getTypeInfo call --- compiler/src/dmd/e2ir.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dmd/e2ir.d b/compiler/src/dmd/e2ir.d index 8ba03958db2d..30290413c8c4 100644 --- a/compiler/src/dmd/e2ir.d +++ b/compiler/src/dmd/e2ir.d @@ -1304,7 +1304,7 @@ elem* toElem(Expression e, IRState *irs) else if (auto taa = t.isTypeAArray()) { Symbol *s = aaGetSymbol(taa, "New", 0); - elem *ti = getTypeInfo(ne.loc, taa, irs); + elem *ti = getTypeInfo(ne, t, irs); // aaNew(ti) elem *ep = el_params(ti, null); e = el_bin(OPcall, TYnptr, el_var(s), ep); From e8cdd13a92487ad6ef206a9ca2e8c030a6c56e68 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Thu, 30 Jun 2022 16:17:00 +0100 Subject: [PATCH 4/9] Fix 2 fail_compilation tests --- compiler/test/fail_compilation/fail20547.d | 5 ++--- compiler/test/fail_compilation/misc_parser_err_cov1.d | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/test/fail_compilation/fail20547.d b/compiler/test/fail_compilation/fail20547.d index c14977d0f124..d99e370cf362 100644 --- a/compiler/test/fail_compilation/fail20547.d +++ b/compiler/test/fail_compilation/fail20547.d @@ -1,11 +1,10 @@ /* TEST_OUTPUT: --- -fail_compilation/fail20547.d(12): Error: cannot create a `string[string]` with `new` -fail_compilation/fail20547.d(14): Error: cannot create a `string[string]` with `new` +fail_compilation/fail20547.d(14): Error: cannot implicitly convert expression `new string[string]` of type `string[string]` to `int[string]` --- */ - +#line 9 void main() { //https://issues.dlang.org/show_bug.cgi?id=11790 diff --git a/compiler/test/fail_compilation/misc_parser_err_cov1.d b/compiler/test/fail_compilation/misc_parser_err_cov1.d index 22cf39241f88..b50a616ac974 100644 --- a/compiler/test/fail_compilation/misc_parser_err_cov1.d +++ b/compiler/test/fail_compilation/misc_parser_err_cov1.d @@ -10,7 +10,6 @@ fail_compilation/misc_parser_err_cov1.d(31): Error: expression expected, not `)` fail_compilation/misc_parser_err_cov1.d(32): Error: `type identifier : specialization` expected following `is` fail_compilation/misc_parser_err_cov1.d(33): Error: semicolon expected following auto declaration, not `auto` fail_compilation/misc_parser_err_cov1.d(33): Error: found `+` when expecting `(` following `mixin` -fail_compilation/misc_parser_err_cov1.d(34): Error: cannot create a `char[float]` with `new` fail_compilation/misc_parser_err_cov1.d(35): Error: `key:value` expected for associative array literal fail_compilation/misc_parser_err_cov1.d(36): Error: basic type expected, not `;` fail_compilation/misc_parser_err_cov1.d(36): Error: `{ members }` expected for anonymous class @@ -44,7 +43,7 @@ void main() auto tt = __traits( Date: Sat, 23 Jul 2022 13:54:24 +0100 Subject: [PATCH 5/9] Add changelog --- changelog/new-aa.dd | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 changelog/new-aa.dd diff --git a/changelog/new-aa.dd b/changelog/new-aa.dd new file mode 100644 index 000000000000..b48e9f12dfba --- /dev/null +++ b/changelog/new-aa.dd @@ -0,0 +1,16 @@ +`new` can now allocate an associative array + +This allows two associative array references to point to the same +associative array instance before any keys have been inserted. + +--- +int[string] a = new int[string]; +auto b = a; +... +a["seven"] = 7; +assert(b["seven"] == 7); +--- + +Note: Calling `new` is not needed before inserting keys on a null +associative array reference - the instance will be allocated if it +doesn't exist. From 7ac9c77a118b670a94eacc239ba483eeba07814e Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 24 Jul 2022 13:04:22 +0100 Subject: [PATCH 6/9] detab, make nested fn static --- test/runnable/newaa.d | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/test/runnable/newaa.d b/test/runnable/newaa.d index 0e9bedfad3a1..50da03b12548 100644 --- a/test/runnable/newaa.d +++ b/test/runnable/newaa.d @@ -1,18 +1,18 @@ void main() { - alias AA = int[string]; - // aa is not ref - void test(AA aa) - { - aa[""] = 0; - } - auto aa = new AA(); - auto ab = new int[string]; - auto ac = new typeof(aa); - test(aa); - test(ab); - test(ac); - assert(aa.length); - assert(ab.length); - assert(ac.length); + alias AA = int[string]; + // aa is not ref + static void test(AA aa) + { + aa[""] = 0; + } + auto aa = new AA(); + auto ab = new int[string]; + auto ac = new typeof(aa); + test(aa); + test(ab); + test(ac); + assert(aa.length); + assert(ab.length); + assert(ac.length); } From 27509b82504f369ca3086c5848b050f782ae7c5d Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 24 Jul 2022 13:04:37 +0100 Subject: [PATCH 7/9] test 2 refs pointing to same new AA --- test/runnable/newaa.d | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/runnable/newaa.d b/test/runnable/newaa.d index 50da03b12548..94e79d5896a8 100644 --- a/test/runnable/newaa.d +++ b/test/runnable/newaa.d @@ -15,4 +15,9 @@ void main() assert(aa.length); assert(ab.length); assert(ac.length); + + int[string] a = new int[string]; + auto b = a; + a["seven"] = 7; + assert(b["seven"] == 7); } From 1390a3cc1667bda39a77a7aafd98f14fd270c1e4 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 24 Jul 2022 13:13:36 +0100 Subject: [PATCH 8/9] Test `new AA(arg)` fails --- compiler/test/fail_compilation/fail20547.d | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/test/fail_compilation/fail20547.d b/compiler/test/fail_compilation/fail20547.d index d99e370cf362..8611db4482b9 100644 --- a/compiler/test/fail_compilation/fail20547.d +++ b/compiler/test/fail_compilation/fail20547.d @@ -2,6 +2,8 @@ TEST_OUTPUT: --- fail_compilation/fail20547.d(14): Error: cannot implicitly convert expression `new string[string]` of type `string[string]` to `int[string]` +fail_compilation/fail20547.d(15): Error: function expected before `()`, not `new int[int]` of type `int[int]` +fail_compilation/fail20547.d(17): Error: `new` cannot take arguments for an associative array --- */ #line 9 @@ -11,4 +13,7 @@ void main() string[string] crash = new string[string]; //https://issues.dlang.org/show_bug.cgi?id=20547 int[string] c = new typeof(crash); + auto d = new int[int](5); + alias AA = char[string]; + auto e = new AA(5); } From 8498f4d261ce365ecea06509b4625bb769f70ca3 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 24 Jul 2022 13:15:37 +0100 Subject: [PATCH 9/9] Rename fail test --- compiler/test/fail_compilation/fail20547.d | 19 ------------------- compiler/test/fail_compilation/newaa.d | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 19 deletions(-) delete mode 100644 compiler/test/fail_compilation/fail20547.d create mode 100644 compiler/test/fail_compilation/newaa.d diff --git a/compiler/test/fail_compilation/fail20547.d b/compiler/test/fail_compilation/fail20547.d deleted file mode 100644 index 8611db4482b9..000000000000 --- a/compiler/test/fail_compilation/fail20547.d +++ /dev/null @@ -1,19 +0,0 @@ -/* -TEST_OUTPUT: ---- -fail_compilation/fail20547.d(14): Error: cannot implicitly convert expression `new string[string]` of type `string[string]` to `int[string]` -fail_compilation/fail20547.d(15): Error: function expected before `()`, not `new int[int]` of type `int[int]` -fail_compilation/fail20547.d(17): Error: `new` cannot take arguments for an associative array ---- -*/ -#line 9 -void main() -{ - //https://issues.dlang.org/show_bug.cgi?id=11790 - string[string] crash = new string[string]; - //https://issues.dlang.org/show_bug.cgi?id=20547 - int[string] c = new typeof(crash); - auto d = new int[int](5); - alias AA = char[string]; - auto e = new AA(5); -} diff --git a/compiler/test/fail_compilation/newaa.d b/compiler/test/fail_compilation/newaa.d new file mode 100644 index 000000000000..ebc23fb352e7 --- /dev/null +++ b/compiler/test/fail_compilation/newaa.d @@ -0,0 +1,19 @@ +/* +TEST_OUTPUT: +--- +fail_compilation/newaa.d(14): Error: cannot implicitly convert expression `new string[string]` of type `string[string]` to `int[string]` +fail_compilation/newaa.d(15): Error: function expected before `()`, not `new int[int]` of type `int[int]` +fail_compilation/newaa.d(17): Error: `new` cannot take arguments for an associative array +--- +*/ +#line 9 +void main() +{ + //https://issues.dlang.org/show_bug.cgi?id=11790 + string[string] crash = new string[string]; + //https://issues.dlang.org/show_bug.cgi?id=20547 + int[string] c = new typeof(crash); + auto d = new int[int](5); + alias AA = char[string]; + auto e = new AA(5); +}