From e50441ab33d1b287a89ad4e2d795c80b7f8077c0 Mon Sep 17 00:00:00 2001 From: zah Date: Thu, 26 Mar 2020 10:26:19 +0200 Subject: [PATCH] Fix typeSym.getImpl for ref types (#13752) * Fix typeSym.getImpl for ref types * Fix a codegen issue affecting the test suite of nim-beacon-chain * Fix tests/stdlib/tjsonmacro To understand the fix better it may help to take a look at the history of the replaced code. The nil check that is removed in this commit was introduced in another fix that failed to identify the root cause of the issue - namely that we allow an object type to exist for which no ast is present: https://github.com/nim-lang/Nim/pull/9601/files The original intention of the code is more obvious here: https://github.com/nim-lang/Nim/pull/9538/files --- compiler/ccgexprs.nim | 2 +- compiler/semstmts.nim | 2 +- compiler/vmdeps.nim | 8 ++-- tests/macros/tmacrotypes.nim | 84 +++++++++++++++++++++++++++++++++++- 4 files changed, 88 insertions(+), 8 deletions(-) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index e1561ae12b..fcedcf001e 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2950,7 +2950,7 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope = else: internalError(p.config, n.info, "node has no type") else: - ty = skipTypes(n.typ, abstractInstOwned).kind + ty = skipTypes(n.typ, abstractInstOwned + {tyStatic}).kind case ty of tySet: var cs: TBitSet diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 6b01e241ba..5232c5706c 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1279,12 +1279,12 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = incl st.flags, tfRefsAnonObj let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"), getCurrOwner(c), s.info) + obj.ast = a if sfPure in s.flags: obj.flags.incl sfPure obj.typ = st.lastSon st.lastSon.sym = obj - proc checkForMetaFields(c: PContext; n: PNode) = proc checkMeta(c: PContext; n: PNode; t: PType) = if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags: diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 79d49698a3..7cfba046ab 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -159,10 +159,10 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; of tyObject: if inst: result = newNodeX(nkObjectTy) - if t.sym.ast != nil: - result.add t.sym.ast[2][0].copyTree # copy object pragmas - else: - result.add newNodeI(nkEmpty, info) + var objectDef = t.sym.ast[2] + if objectDef.kind == nkRefTy: + objectDef = objectDef[0] + result.add objectDef[0].copyTree # copy object pragmas if t[0] == nil: result.add newNodeI(nkEmpty, info) else: # handle parent object diff --git a/tests/macros/tmacrotypes.nim b/tests/macros/tmacrotypes.nim index 8cf93a5932..cfc4ef7fb7 100644 --- a/tests/macros/tmacrotypes.nim +++ b/tests/macros/tmacrotypes.nim @@ -4,11 +4,40 @@ void; ntyVoid; void; void int; ntyInt; int; int proc (); ntyProc; proc[void]; proc () voidProc; ntyProc; proc[void]; proc () +listing fields for ObjType +a: string +b: int +listing fields for ObjRef +skipping ref type +a: string +b: int +listing fields for RefType +skipping ref type +a: int +b: float +listing fields for typeof(a) +skipping ref type +a: string +b: int +listing fields for typeof(b) +skipping ref type +a: string +b: int +listing fields for typeof(c) +skipping ref type +a: int +b: float +listing fields for typeof(x) +a: string +b: int +listing fields for typeof(x) +a: int +b: float typeDesc[range[1 .. 5]]; ntyTypeDesc; typeDesc[range[1, 5]]; typeDesc[range[1 .. 5]] typeDesc[range]; ntyTypeDesc; typeDesc[range[T]]; typeDesc[range]''' """ -import macros +import macros, typetraits macro checkType(ex: typed): untyped = echo ex.getTypeInst.repr, "; ", ex.typeKind, "; ", ex.getType.repr, "; ", ex.getTypeImpl.repr @@ -17,7 +46,6 @@ macro checkProcType(fn: typed): untyped = let fn_sym = if fn.kind == nnkProcDef: fn[0] else: fn echo fn_sym, "; ", fn_sym.typeKind, "; ", fn_sym.getType.repr, "; ", fn_sym.getTypeImpl.repr - proc voidProc = echo "hello" proc intProc(a: int, b: float): int {.checkProcType.} = 10 @@ -26,6 +54,58 @@ checkType(intProc(10, 20.0)) checkType(voidProc) checkProcType(voidProc) +macro listFields(T: typed) = + echo "listing fields for ", repr(T) + let inputExprType = getType(T) + + var objType = inputExprType[1] + if objType.kind == nnkBracketExpr and objType.len > 1: + if ((objType[0].kind == nnkRefTy) or + (objType[0].kind == nnkSym and eqIdent(objType[0], "ref"))): + echo "skipping ref type" + objType = objType[1] + + let typeAst = objType.getImpl + + var objectDef = typeAst[2] + if objectDef.kind == nnkRefTy: + objectDef = objectDef[0] + + let recList = objectDef[2] + for rec in recList: + echo $rec[0], ": ", $rec[1] + +type + ObjType* = object of RootObj + a: string + b: int + + ObjRef = ref ObjType + + RefType* = ref object of RootObj + a: int + b: float + +listFields ObjType +listFields ObjRef +listFields RefType + +let + a = new ObjType + b = new ObjRef + c = new RefType + +listFields typeOf(a) +listFields typeOf(b) +listFields typeOf(c) + +proc genericProc(x: object) = + listFields typeOf(x) + +genericProc a[] +genericProc b[] +genericProc c[] + # bug #10548 block: var c {.compileTime.} = 0