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
This commit is contained in:
zah 2020-03-26 10:26:19 +02:00 • committed by GitHub
commit e50441ab33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 88 additions and 8 deletions

View file

@ -2950,7 +2950,7 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope =
else: else:
internalError(p.config, n.info, "node has no type") internalError(p.config, n.info, "node has no type")
else: else:
ty = skipTypes(n.typ, abstractInstOwned).kind ty = skipTypes(n.typ, abstractInstOwned + {tyStatic}).kind
case ty case ty
of tySet: of tySet:
var cs: TBitSet var cs: TBitSet

View file

@ -1279,12 +1279,12 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
incl st.flags, tfRefsAnonObj incl st.flags, tfRefsAnonObj
let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"), let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"),
getCurrOwner(c), s.info) getCurrOwner(c), s.info)
obj.ast = a
if sfPure in s.flags: if sfPure in s.flags:
obj.flags.incl sfPure obj.flags.incl sfPure
obj.typ = st.lastSon obj.typ = st.lastSon
st.lastSon.sym = obj st.lastSon.sym = obj
proc checkForMetaFields(c: PContext; n: PNode) = proc checkForMetaFields(c: PContext; n: PNode) =
proc checkMeta(c: PContext; n: PNode; t: PType) = proc checkMeta(c: PContext; n: PNode; t: PType) =
if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags: if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags:

View file

@ -159,10 +159,10 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
of tyObject: of tyObject:
if inst: if inst:
result = newNodeX(nkObjectTy) result = newNodeX(nkObjectTy)
if t.sym.ast != nil: var objectDef = t.sym.ast[2]
result.add t.sym.ast[2][0].copyTree # copy object pragmas if objectDef.kind == nkRefTy:
else: objectDef = objectDef[0]
result.add newNodeI(nkEmpty, info) result.add objectDef[0].copyTree # copy object pragmas
if t[0] == nil: if t[0] == nil:
result.add newNodeI(nkEmpty, info) result.add newNodeI(nkEmpty, info)
else: # handle parent object else: # handle parent object

View file

@ -4,11 +4,40 @@ void; ntyVoid; void; void
int; ntyInt; int; int int; ntyInt; int; int
proc (); ntyProc; proc[void]; proc () proc (); ntyProc; proc[void]; proc ()
voidProc; 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[1 .. 5]]; ntyTypeDesc; typeDesc[range[1, 5]]; typeDesc[range[1 .. 5]]
typeDesc[range]; ntyTypeDesc; typeDesc[range[T]]; typeDesc[range]''' typeDesc[range]; ntyTypeDesc; typeDesc[range[T]]; typeDesc[range]'''
""" """
import macros import macros, typetraits
macro checkType(ex: typed): untyped = macro checkType(ex: typed): untyped =
echo ex.getTypeInst.repr, "; ", ex.typeKind, "; ", ex.getType.repr, "; ", ex.getTypeImpl.repr 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 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 echo fn_sym, "; ", fn_sym.typeKind, "; ", fn_sym.getType.repr, "; ", fn_sym.getTypeImpl.repr
proc voidProc = echo "hello" proc voidProc = echo "hello"
proc intProc(a: int, b: float): int {.checkProcType.} = 10 proc intProc(a: int, b: float): int {.checkProcType.} = 10
@ -26,6 +54,58 @@ checkType(intProc(10, 20.0))
checkType(voidProc) checkType(voidProc)
checkProcType(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 # bug #10548
block: block:
var c {.compileTime.} = 0 var c {.compileTime.} = 0