summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorflywind <43030857+xflywind@users.noreply.github.com>2020-11-18 15:28:05 +0800
committerGitHub <noreply@github.com>2020-11-18 08:28:05 +0100
commite6e1e9574de8c090cb9de7a809064037e2af39f7 (patch)
tree7abfbfe36aeaa8319a24901357b892e676a0622a
parent0869d2a47777685d221ddde927f0175096c911b0 (diff)
downloadNim-e6e1e9574de8c090cb9de7a809064037e2af39f7.tar.gz
combine PR#16009 and PR#16012 (#16024)
* fix #15623
* add testcase for #15623
* add testcase
* combine #16009
* support casting nil to NilableTypes in VM
-rw-r--r--compiler/semfold.nim2
-rw-r--r--compiler/vmgen.nim5
-rw-r--r--tests/misc/tcast.nim44
3 files changed, 50 insertions, 1 deletions
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 9b21c5fa3..f38359a64 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -674,7 +674,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
   of nkCast:
     var a = getConstExpr(m, n[1], idgen, g)
     if a == nil: return
-    if n.typ != nil and n.typ.kind in NilableTypes:
+    if n.typ != nil and n.typ.kind in NilableTypes and a.kind != nkNilLit:
       # we allow compile-time 'cast' for pointer types:
       result = a
       result.typ = n.typ
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index bcb7faa47..84ff1a91d 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -901,6 +901,11 @@ proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) =
     c.gABx(n, opcSetType, dest, c.genType(dst))
     c.gABC(n, opcCastIntToPtr, dest, tmp)
     c.freeTemp(tmp)
+  elif src.kind == tyNil and dst.kind in NilableTypes:
+    # supports casting nil literals to NilableTypes in VM
+    # see #16024
+    if dest < 0: dest = c.getTemp(n[0].typ)
+    genLit(c, n[1], dest)
   else:
     # todo: support cast from tyInt to tyRef
     globalError(c.config, n.info, "VM does not support 'cast' from " & $src.kind & " to " & $dst.kind)
diff --git a/tests/misc/tcast.nim b/tests/misc/tcast.nim
index 745b9e221..12179cb1c 100644
--- a/tests/misc/tcast.nim
+++ b/tests/misc/tcast.nim
@@ -29,3 +29,47 @@ reject: discard cast[enum](0)
 proc a = echo "hi"
 
 reject: discard cast[ptr](a)
+
+# bug #15623
+block:
+  if false:
+    echo cast[ptr int](nil)[]
+
+block:
+  if false:
+    var x: ref int = nil
+    echo cast[ptr int](x)[]
+
+block:
+  doAssert cast[int](cast[ptr int](nil)) == 0
+
+block:
+  var x: ref int = nil
+  doAssert cast[int](cast[ptr int](x)) == 0
+
+block:
+  block:
+    static:
+      let a = cast[pointer](nil)
+      doAssert a.repr == "nil"
+
+  block:
+    static:
+      doAssert cast[ptr int](nil).repr == "nil"
+
+  block:
+    const str = cast[ptr int](nil)
+    static:
+      doAssert str.repr == "nil"
+
+  block:
+    static:
+      doAssert cast[ptr int](nil).repr == "nil"
+
+  block:
+    static:
+      doAssert cast[RootRef](nil).repr == "nil"
+
+  block:
+    static:
+      doAssert cast[cstring](nil).repr == "nil"