From ecf2ce2f54fc86e2f075815235ddd0a3425eb8ef Mon Sep 17 00:00:00 2001 From: Geod24 Date: Mon, 10 Aug 2020 16:24:22 +0900 Subject: [PATCH] Fix 17351 - Manifest constants can't sometimes be passed by `ref` in CTFE As mentioned in the comment, the fix is crude but works well. --- src/dmd/dinterpret.d | 10 +++++++++- test/compilable/test17351.d | 17 +++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 test/compilable/test17351.d diff --git a/src/dmd/dinterpret.d b/src/dmd/dinterpret.d index f34a5d0ec9dc..c1c856e0e564 100644 --- a/src/dmd/dinterpret.d +++ b/src/dmd/dinterpret.d @@ -2131,7 +2131,15 @@ public: return; } - if (goal == ctfeNeedLvalue) + // Note: This is a workaround for + // https://issues.dlang.org/show_bug.cgi?id=17351 + // The aforementioned bug triggers when passing manifest constant by `ref`. + // If there was not a previous reference to them, they are + // not cached and trigger a "cannot be read at compile time". + // This fix is a crude solution to get it to work. A more proper + // approach would be to resolve the forward reference, but that is + // much more involved. + if (goal == ctfeNeedLvalue && e.var.type.isMutable()) { VarDeclaration v = e.var.isVarDeclaration(); if (v && !v.isDataseg() && !v.isCTFE() && !istate) diff --git a/test/compilable/test17351.d b/test/compilable/test17351.d new file mode 100644 index 000000000000..fffe92c4d581 --- /dev/null +++ b/test/compilable/test17351.d @@ -0,0 +1,17 @@ +bool fun(S)(ref S[3] a) { assert(a == [42, 84, 169]); return true; } +bool fun2(S)(ref S a) { return true; } +void main() +{ + static const int[3] sa = [42, 84, 169]; + static const double sa2 = 42.42; + static assert(fun(sa)); + static assert(fun2(sa2)); +} + +int f1(ref const int p) { return p; } +int f2(ref const int[2] p) { return p[0] + p[1]; } +void test2() +{ + static immutable int[2] P = [ 0, 1 ]; + static assert(f2(P) == 1); +}