Bug 3162 – can't fully use compile-time floats as template parameters

Status
RESOLVED
Resolution
FIXED
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2009-07-10T07:32:00Z
Last change time
2015-06-09T01:27:45Z
Keywords
patch, rejects-valid
Assigned to
nobody
Creator
witold.baryluk+d

Attachments

IDFilenameSummaryContent-TypeSize
420bug3162.dSource code which should compiletext/x-dsrc646

Comments

Comment #0 by witold.baryluk+d — 2009-07-10T07:32:46Z
/** Computes square root at compile time */ real ctfe_sqrt(real x) { real root = x / 2.0; for (int ntries = 0; ntries < 10; ntries++) { if (root * root - x == 0) break; root = (root + x / root) / 2.0; } return root; } /** Square root of 2 */ static const double sqrt2 = ctfe_sqrt(2.0); import std.metastrings; pragma(msg, Format!("s=", cast(int)(1000*sqrt2))); // works pragma(msg, Format!("s=", cast(int)(1000*sqrt2), " ", cast(int)(1000*sqrt2), " ")); // doesn't work //pragma(msg, Format!("s=", cast(int)(1000*sqrt2))); // also doesn't work pragma(msg, Format!("s=", cast(int)((1.0+sqrt2/2.0))); // doesn't works Looks that only first occurence of value derived from constant derived using ctfs can be used. It was working in some older releases.
Comment #1 by witold.baryluk+d — 2009-07-10T07:34:37Z
s=1414 /home/baryluk/ProjektyZSempa/D/onpd/onp/../onp/utils/misc.d(187): Error: expression cast(int)(1000 * sqrt2) is not a valid template value argument /home/baryluk/ProjektyZSempa/D/onpd/onp/../onp/utils/misc.d(187): Error: expression cast(int)(1000 * sqrt2) is not a valid template value argument /home/baryluk/ProjektyZSempa/D/onpd/onp/../onp/utils/misc.d(186): Error: expression cast(int)(1000 * (1 + sqrt2 / 2)) is not a valid template value argument ...
Comment #2 by witold.baryluk+d — 2009-07-10T07:48:34Z
Created attachment 420 Source code which should compile Test case
Comment #3 by witold.baryluk+d — 2009-07-10T08:07:07Z
Simpler example /** Square root of 2 */ static const double sqrt2 = ctfe_sqrt(2.0); template X(E ...) { alias E X; } //alias X!(sqrt2/1.0, sqrt2/2.0) X2; // doesn't work //alias X!(sqrt2*sqrt2) X3; // doesn't work static const double sqrt22 = sqrt2*sqrt2; //alias X!(sqrt22) X4; // doesn't work
Comment #4 by witold.baryluk+d — 2009-07-10T08:15:21Z
Additionally if i omit "double" in "static const double", it compiles! It is the same type! I was also testing this ctfe function T i(T)(T x) { return x; } and only with T=float,double,real i got errors.
Comment #5 by clugdbug — 2009-07-13T00:09:29Z
Reduced test case shows it doesn't require CTFE: ----- enum float one = 1 * 1; template X(float E) { int X = 2; } alias X!(one * one) X3; ---- This is really complicated, and took me ages to track down. First problem is in declaration.c, near the end of VarDeclaration::semantic(). It calculates the value of the manifest constant, but discards the result unless it was an int or a string! That's a waste, since it was successfully calculated. In optimize.c expandVar() copys the exprInitializer and semantically analyzes it, but it doesn't change the exprInitializer. So ei->type remains null the next time expandVar is called for that same variable. And since expandVar sets v->scope to NULL, it never gets another chance to evaluate it. So in optimize.c line 92, it bypasses the call to e = ei->copy(), returning NULL from the function. --> it cannot be evaluated at compile time. The final patch is tiny: add floating point variables to the list of values which get saved. // line 1150 declaration.c || e->op==TOKfloat64 e = e->optimize(WANTvalue | WANTinterpret); else e = e->optimize(WANTvalue); - if (e->op == TOKint64 || e->op == TOKstring) + if (e->op == TOKint64 || e->op == TOKstring || e->op==TOKfloat64) { ei->exp = e; // no errors, keep result } However, I think the logic in expandVar() is probably also wrong. The bug can also be fixed by adding this line in optimize.c, line 89: e = e->semantic(v->scope); e = e->implicitCastTo(v->scope, v->type); + ei->type = e->type; v->scope = NULL;
Comment #6 by bugzilla — 2009-09-03T13:40:51Z
Fixed dmd 2.032