From b79475787889df13bad29345e6238710b892687f Mon Sep 17 00:00:00 2001 From: zerbina <100542850+zerbina@users.noreply.github.com> Date: Mon, 31 Jul 2023 23:27:23 +0200 Subject: [PATCH] semfold: fix range-check folding (#822) ## Summary Fix literals resulting from folding range-check conversions having a type that doesn't match the node kind. This, in turn, fixes a VM code generator issue where the code generated for an access of the result of an integer-literal-converted-to-float-range would cause the VM to crash. ## Details The folding logic directly assigned the destination type to the literal, which led to, for example, integer literals having a `tyFloat` type. This breaks the assumption of only float-literal nodes having a float type, and is what caused the `vmgen` bug (`vmgen` only looks at the node kind). Same as for normal conversion, range-check conversion are now also folded via `foldConv` (but only in case the range check succeeds), fixing the issue. --- compiler/sem/semfold.nim | 4 ++-- tests/lang_types/range/trange.nim | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/compiler/sem/semfold.nim b/compiler/sem/semfold.nim index 153f01b7c23..f9d4eb58bee 100644 --- a/compiler/sem/semfold.nim +++ b/compiler/sem/semfold.nim @@ -761,8 +761,8 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode let a = getConstExpr(m, n[0], idgen, g) if a == nil: return if leValueConv(n[1], a) and leValueConv(a, n[2]): - result = a # a <= x and x <= b - result.typ = n.typ + # a <= x and x <= b + result = foldConv(n, a, idgen, g, check=false) else: result = g.config.newError(n, PAstDiag(kind: adSemInvalidRangeConversion)) diff --git a/tests/lang_types/range/trange.nim b/tests/lang_types/range/trange.nim index 92ab5ea867a..c58125c4b10 100644 --- a/tests/lang_types/range/trange.nim +++ b/tests/lang_types/range/trange.nim @@ -1,4 +1,5 @@ discard """ + targets: "c js vm" output: ''' TSubRange: 5 from 1 to 10 #FF3722 @@ -154,3 +155,11 @@ block: c = d doAssert a == b doAssert c == d + +block int_literal_to_float_range: + type Range = range[0'f..1'f] + + var val = 0'f + # use the value in a comparison in order to make sure that + # the conversion really worked + doAssert val == Range(0) \ No newline at end of file