diff --git a/compiler/vm.nim b/compiler/vm.nim index 73255395fe16a..1355dd1efd440 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1873,7 +1873,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc], c.idgen) else: stackTrace(c, tos, pc, "node has no type") - else: + of 3: # getTypeImpl opcode: ensureKind(rkNode) if regs[rb].kind == rkNode and regs[rb].node.typ != nil: @@ -1882,6 +1882,15 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc], c.idgen) else: stackTrace(c, tos, pc, "node has no type") + else: + # getTypeInstSkipAlias opcode: + ensureKind(rkNode) + if regs[rb].kind == rkNode and regs[rb].node.typ != nil: + regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.typ, c.debug[pc], c.idgen, skipAlias = true) + elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil: + regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc], c.idgen, skipAlias = true) + else: + stackTrace(c, tos, pc, "node has no type") of opcNGetSize: decodeBImm(rkInt) let n = regs[rb].node diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 2a088ac9645b4..72eec34eadb65 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -42,7 +42,7 @@ proc atomicTypeX(s: PSym; info: TLineInfo): PNode = result.info = info proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator; - inst=false; allowRecursionX=false): PNode + inst=false; allowRecursionX=false; skipAlias = false): PNode proc mapTypeToBracketX(cache: IdentCache; name: string; m: TMagic; t: PType; info: TLineInfo; idgen: IdGenerator; @@ -70,7 +70,7 @@ proc objectNode(cache: IdentCache; n: PNode; idgen: IdGenerator): PNode = proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator; - inst=false; allowRecursionX=false): PNode = + inst=false; allowRecursionX=false; skipAlias = false): PNode = var allowRecursion = allowRecursionX template atomicType(name, m): untyped = atomicTypeX(cache, name, m, t, info, idgen) template atomicType(s): untyped = atomicTypeX(s, info) @@ -91,7 +91,8 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; id template newIdentDefs(s): untyped = newIdentDefs(s, s.typ) - if inst and not allowRecursion and t.sym != nil: + if inst and not allowRecursion and t.sym != nil and + not (skipAlias and t.kind == tyAlias): # getTypeInst behavior: return symbol return atomicType(t.sym) @@ -124,7 +125,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; if t.base != nil: result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t) result.add atomicType("typeDesc", mTypeDesc) - result.add mapTypeToAst(t.base, info) + result.add mapTypeToAstX(cache, t.base, info, idgen, inst, skipAlias = skipAlias) else: result = atomicType("typeDesc", mTypeDesc) of tyGenericInvocation: @@ -153,7 +154,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; else: result = mapTypeToAst(t.typeBodyImpl, info) of tyAlias: - result = mapTypeToAstX(cache, t.skipModifier, info, idgen, inst, allowRecursion) + result = mapTypeToAstX(cache, t.skipModifier, info, idgen, inst, allowRecursion, skipAlias = skipAlias) of tyOrdinal: result = mapTypeToAst(t.skipModifier, info) of tyDistinct: @@ -325,8 +326,9 @@ proc opMapTypeToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGene # the "Inst" version includes generic parameters in the resulting type tree # and also tries to look like the corresponding Nim type declaration -proc opMapTypeInstToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator): PNode = - result = mapTypeToAstX(cache, t, info, idgen, inst=true, allowRecursionX=false) +proc opMapTypeInstToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator; skipAlias = false): PNode = + # skipAlias: skips aliases and typedesc + result = mapTypeToAstX(cache, t, info, idgen, inst=true, allowRecursionX=false, skipAlias = skipAlias) # the "Impl" version includes generic parameters in the resulting type tree # and also tries to look like the corresponding Nim type implementation diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index e8612000a3de4..851cfa401dc1a 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1337,7 +1337,8 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}, m: TMag of "getType": 0 of "typeKind": 1 of "getTypeInst": 2 - else: 3 # "getTypeImpl" + of "getTypeImpl": 3 # "getTypeImpl" + else: 4 # getTypeInstSkipAlias c.gABC(n, opcNGetType, dest, tmp, rc) c.freeTemp(tmp) #genUnaryABC(c, n, dest, opcNGetType) diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 8a44fbc833759..605df443ecb5b 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -1575,11 +1575,14 @@ proc extractTypeImpl(n: NimNode): NimNode = result = n[2] else: error("Invalid node to retrieve type implementation of: " & $n.kind) + +proc getTypeInstSkipAlias(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.} + proc customPragmaNode(n: NimNode): NimNode = result = nil expectKind(n, {nnkSym, nnkDotExpr, nnkBracketExpr, nnkTypeOfExpr, nnkType, nnkCheckedFieldExpr}) - let - typ = n.getTypeInst() + + let typ = n.getTypeInstSkipAlias() if typ.kind == nnkBracketExpr and typ.len > 1 and typ[1].kind == nnkProcTy: return typ[1][1] diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim index 11a6df813d671..3d6032e605137 100644 --- a/tests/pragmas/tcustom_pragma.nim +++ b/tests/pragmas/tcustom_pragma.nim @@ -538,3 +538,14 @@ block: # https://forum.nim-lang.org/t/12522, backticks type Test = object field {.`mypragma`.}: int doAssert Test().field.hasCustomPragma(mypragma) + + +block: + template p {.pragma.} + + func foo[T0](v: T0): bool = + type T = T0 + T.hasCustomPragma(p) + + type X {.p.} = object + doAssert foo(X())