From e6e1e9574de8c090cb9de7a809064037e2af39f7 Mon Sep 17 00:00:00 2001 From: flywind <43030857+xflywind@users.noreply.github.com> Date: Wed, 18 Nov 2020 15:28:05 +0800 Subject: combine PR#16009 and PR#16012 (#16024) * fix #15623 * add testcase for #15623 * add testcase * combine #16009 * support casting nil to NilableTypes in VM --- compiler/semfold.nim | 2 +- compiler/vmgen.nim | 5 +++++ tests/misc/tcast.nim | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) 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" -- cgit 1.4.1-2-gfad0