summary refs log tree commit diff stats
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2024-09-22 14:51:19 +0300
committerGitHub <noreply@github.com>2024-09-22 13:51:19 +0200
commita1777200c1a52b5a71d641309349618df2550b33 (patch)
treeef3b674e42820e87bef5ef4405a780f5ded775f1
parentd51d88700b2fb3bd228d5e8f7385e2e4a2e2880c (diff)
downloadNim-a1777200c1a52b5a71d641309349618df2550b33.tar.gz
fix `inTypeofContext` leaking after `compiles` raises exception [backport:2.0] (#24152)
fixes #24150, refs #22022

An exception is raised in the `semExprWithType` call, which means `dec
c.inTypeofContext` is never called, but `compiles` allows compilation to
continue. This means `c.inTypeofContext` is left perpetually nonzero,
which prevents `compileTime` evaluation for the rest of the program.

To fix this, `defer:` is used for the `dec c.inTypeofContext` call, as
is done for
[`instCounter`](https://github.com/nim-lang/Nim/blob/d51d88700b2fb3bd228d5e8f7385e2e4a2e2880c/compiler/seminst.nim#L374)
in other parts of the compiler.
-rw-r--r--compiler/semmagic.nim2
-rw-r--r--compiler/semtypes.nim4
-rw-r--r--tests/vm/tgenericcompiletimeproc.nim7
3 files changed, 10 insertions, 3 deletions
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 360d23477..a12e933e7 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -50,8 +50,8 @@ proc semTypeOf(c: PContext; n: PNode): PNode =
       m = mode.intVal
   result = newNodeI(nkTypeOfExpr, n.info)
   inc c.inTypeofContext
+  defer: dec c.inTypeofContext # compiles can raise an exception
   let typExpr = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {})
-  dec c.inTypeofContext
   result.add typExpr
   if typExpr.typ.kind == tyFromExpr:
     typExpr.typ.flags.incl tfNonConstExpr
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 6302a4590..450b81dbf 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -1866,8 +1866,8 @@ proc semStaticType(c: PContext, childNode: PNode, prev: PType): PType =
 proc semTypeOf(c: PContext; n: PNode; prev: PType): PType =
   openScope(c)
   inc c.inTypeofContext
+  defer: dec c.inTypeofContext # compiles can raise an exception
   let t = semExprWithType(c, n, {efInTypeof})
-  dec c.inTypeofContext
   closeScope(c)
   fixupTypeOf(c, prev, t)
   result = t.typ
@@ -1884,8 +1884,8 @@ proc semTypeOf2(c: PContext; n: PNode; prev: PType): PType =
     else:
       m = mode.intVal
   inc c.inTypeofContext
+  defer: dec c.inTypeofContext # compiles can raise an exception
   let t = semExprWithType(c, n[1], if m == 1: {efInTypeof} else: {})
-  dec c.inTypeofContext
   closeScope(c)
   fixupTypeOf(c, prev, t)
   result = t.typ
diff --git a/tests/vm/tgenericcompiletimeproc.nim b/tests/vm/tgenericcompiletimeproc.nim
index cb4dbb2d8..08099ebbe 100644
--- a/tests/vm/tgenericcompiletimeproc.nim
+++ b/tests/vm/tgenericcompiletimeproc.nim
@@ -27,3 +27,10 @@ block:
   proc p(x: int): int = x
 
   type Foo = typeof(p(fail(123)))
+
+block: # issue #24150, related regression
+  proc w(T: type): T {.compileTime.} = default(ptr T)[]
+  template y(v: auto): auto = typeof(v) is int
+  discard compiles(y(w int))
+  proc s(): int {.compileTime.} = discard
+  discard s()