[Issue 18146] A case expression of final switch allows to pass wrong enum value
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Thu May 31 14:10:55 UTC 2018
https://issues.dlang.org/show_bug.cgi?id=18146
ARAI Kohei <kohei-coco at jcom.home.ne.jp> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|RESOLVED |REOPENED
Resolution|FIXED |---
--- Comment #3 from ARAI Kohei <kohei-coco at jcom.home.ne.jp> ---
Title:
A problem and an its temporary solution about case statements allows to pass
through the wrong enum value.
Overview & background:
I encountered a problem of final switch statement: when an argument of enum
type passed to final switch statement, rarely, wrong case statements allows to
path through the processing flow. The simplified code is shown below.
--- graphic/bezier.d ---
module graphic.bezier;
import numeric.sekitk.qvm; // linear algebraic types and operations
enum BezierOrder: ubyte{Line= 1u, Quadratic, Cubic}
class Bezier(BezierOrder TYP){
enum ubyte N= cast(ubyte)TYP+1u;
this() @safe pure nothrow{. . .}
// some methods are defined here
// this method generates two parallel curves of “this”
typeof(this)[2] offsetCurve(in double width) @safe const
in{
// “in” contract is implemented here
}
do{
typeof(return) curves;
final switch(TYP){
case BezierOrder.Line:
static assert(N == 2u); // compile-time error is generated here
// implementation for straight Bezier lines
break;
case BezierOrder.Quadratic:
static assert(N == 3u);
// implementation for quadratic Bezier curves
break;
case BezierOrder.Cubic:
static assert(N == 4u);
// implementation for cubic Bezier curves
}
return curves;
}
private:
Vector2[N] node;
}
--- test.d ---
void main(){
import std.math: PI_2;
import numeric.sekitk.qvm;
import graphic.bezier;
import graphic.shapes; // unitArc(in double angle) is defined here
Bezier!(BezierType.Cubic) arc= unitArc(PI_2);
Bezier!(BezierType.Cubic) side= arc.offsetCurve(31.0); // the error can
occur
}
---
This problem have ever been occurred another my project, then, I reported it as
this page (Issue 18146). However, I turned the status of the report to
“resolved”, because the problem had not occurred after the immediately update.
Despite it, recently, I've encountered the same problem in another my project.
So, I was wrong. Therefore, I tried to find the solution, and fortunately, a
temporary solution has found. The solution and its evidence are shown below.
Trial-1:
In order to avoid the problem, I tried to use static if statements instead of a
final switch statement.
At first, the equality expressions are used for the comparison between the
template argument (lhs value) and case argument (rhs value), the same error
occurred.
---
static if(TYP == BezierOrder.Line){
static assert(N == 2u); // compile-time error is generated here
// implementation for straight Bezier lines
}
else static if(TYP == BezierOrder.Quadratic){
static assert(N == 3u);
// implementation for quadratic Bezier curves
}
else static if(TYP == BezierOrder.Cubic){
static assert(N == 4u);
// implementation for cubic Bezier curves
}
else static assert(false); // unreachable
---
Trial-2:
Next, the identity expressions are used, the correct result is obtained. So,
this is the temporary solution.
---
static if(TYP is BezierOrder.Line){
static assert(N == 2u); // error is NOT generated here
// implementation for Bezier line segments
}
else static if(TYP is BezierOrder.Quadratic){
static assert(N == 3u);
// implementation for quadratic Bezier curves
}
else static if(TYP is BezierOrder.Cubic){
static assert(N == 4u);
// implementation for cubic Bezier curves
}
else static assert(false); // unreachable
---
Conclusion:
According to Trial 1 and Trial 2, the following result and thinkings are
obtained.
(1) In order to avoid the error, the usage of static if statements with
identity expression seems to be effective.
(2) Probably, a final switch statement uses some equality expression internally
for comparison; this is just my guess, I've never read the source codes of DMD.
(3) If (2) is correct, in the implementation of final switch statements with
enum type argument should use identity expressions instead of equality
expressions.
P.S.
When I reported [Issue 18146], I was required to submit a self-contained codes.
However, I couldn't verify the request: I was busy, I don't have any GitHub
account, and my English ability is so poor. If necessary, please tell me how
to submit my codes. I can open my codes for implementation of dlang.
--
More information about the Digitalmars-d-bugs
mailing list