Compare commits

..

7 Commits

Author SHA1 Message Date
ringabout
fbec8cd8d6 Merge branch 'devel' into pr_when_typ 2026-05-18 20:08:23 +08:00
ringabout
f4cd77c318 fixes 2026-05-06 22:48:37 +08:00
ringabout
5059bb40e5 Merge remote-tracking branch 'origin/devel' into pr_when_typ 2026-05-06 22:02:10 +08:00
ringabout
790df938d7 oops 2026-04-17 19:10:26 +08:00
ringabout
7867200135 normalizeTypedescMacroResult 2026-04-17 19:09:38 +08:00
ringabout
d05e936732 Merge branch 'devel' into pr_when_typ 2026-04-17 16:41:51 +08:00
ringabout
2a8e4dd977 fixes #25407; SIGSEGV when compiling when with typedesc 2026-02-25 20:45:09 +08:00
5 changed files with 42 additions and 75 deletions

View File

@@ -341,9 +341,9 @@ proc genCppParamsForCtor(p: BProc; call: PNode; didGenTemp: var bool): Snippet =
call[i][0]
else:
call[i]
if not param.typ.isCompileTimeOnly and (param.kind != nkBracketExpr or param.typ.kind in
if param.kind != nkBracketExpr or param.typ.kind in
{tyRef, tyPtr, tyUncheckedArray, tyArray, tyOpenArray,
tyVarargs, tySequence, tyString, tyCstring, tyTuple}):
tyVarargs, tySequence, tyString, tyCstring, tyTuple}:
let tempLoc = initLocExprSingleUse(p, param)
didGenTemp = didGenTemp or tempLoc.k == locTemp
genOtherArg(p, call, i, typ, res, argBuilder)

View File

@@ -454,6 +454,26 @@ proc resetSemFlag(n: PNode) =
for i in 0..<n.safeLen:
resetSemFlag(n[i])
proc normalizeTypedescMacroResult(c: PContext, n: PNode): PNode =
result = n
if result.kind == nkStmtList:
result.transitionSonsKind(nkStmtListType)
const maxTypedescMacroNormalizationPasses = 32
# Resolve surviving compile-time branches so later passes don't walk
# unevaluated type AST for a typedesc expression.
for _ in 0..<maxTypedescMacroNormalizationPasses:
if result.kind == nkWhenStmt:
result = semWhen(c, result, false)
if result.kind == nkStmtList:
result.transitionSonsKind(nkStmtListType)
elif result.kind == nkStmtListType and result.len > 0 and result[^1].kind == nkWhenStmt:
result[^1] = semWhen(c, result[^1], false)
if result[^1].kind == nkStmtList:
result[^1].transitionSonsKind(nkStmtListType)
else:
break
proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
s: PSym, flags: TExprFlags; expectedType: PType = nil): PNode =
## Semantically check the output of a macro.
@@ -484,7 +504,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
# More restrictive version.
result = semExprWithType(c, result, flags, expectedType)
of tyTypeDesc:
if result.kind == nkStmtList: result.transitionSonsKind(nkStmtListType)
result = normalizeTypedescMacroResult(c, result)
var typ = semTypeNode(c, result, nil)
if typ == nil:
localError(c.config, result.info, "expression has no type: " &
@@ -492,7 +512,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
result = newSymNode(errorSym(c, result))
else:
result.typ = makeTypeDesc(c, typ)
#result = symNodeFromType(c, typ, n.info)
#result = symNodeFromType(c, typ, n.info)
else:
if s.ast[genericParamsPos] != nil and retType.isMetaType:
# The return type may depend on the Macro arguments

View File

@@ -90,20 +90,11 @@ proc getCurrOwner(c: PTransf): PSym =
if c.transCon != nil: result = c.transCon.owner
else: result = c.module
proc freshOwnedSym(c: PTransf; s, owner: PSym): PNode =
# We need to copy the symbol here because we might need to change its owner and
# we don't want to mess with the original symbol which might be used in other places.
# This can happen for example for iterators which are transformed multiple times when
# they are used in different contexts.
var fresh = copySym(s, c.idgen)
incl(fresh.flagsImpl, sfFromGeneric)
setOwner(fresh, owner)
result = newSymNode(fresh)
proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PNode =
let r = newSym(skTemp, getIdent(c.graph.cache, genPrefix), c.idgen, getCurrOwner(c), info)
r.typ = typ #skipTypes(typ, {tyGenericInst, tyAlias, tySink})
incl(r.flagsImpl, sfFromGeneric)
let owner = getCurrOwner(c)
result = newSymNode(r)
proc transform(c: PTransf, n: PNode, noConstFold = false): PNode
@@ -194,39 +185,11 @@ proc transformSym(c: PTransf, n: PNode): PNode =
result = transformSymAux(c, n)
proc freshVar(c: PTransf; v: PSym): PNode =
result = freshOwnedSym(c, v, getCurrOwner(c))
proc introduceNewRoutineHeaderSyms(c: PTransf; n: PNode; oldOwner, newOwner: PSym) =
# We need to introduce new symbols for the parameters and result of a routine when
# we copy it for inlining or closure generation.
# Otherwise, we would have multiple nodes referring to the same parameter symbols which
# can lead to problems when we need to change the owner of these symbols.
case n.kind
of nkSym:
if n.sym.owner == oldOwner:
c.transCon.mapping[n.sym.itemId] = freshOwnedSym(c, n.sym, newOwner)
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
discard
else:
for i in 0..<n.len:
introduceNewRoutineHeaderSyms(c, n[i], oldOwner, newOwner)
proc copyRoutineTypeHeader(c: PTransf; oldProc, newProc: PSym) =
# We need to copy the routine type header to ensure that
# modifications to the newProc do not affect the oldProc.
if oldProc.typ != nil and oldProc.typ.kind == tyProc and oldProc.typ.n != nil:
newProc.typ = copyType(oldProc.typ, c.idgen, newProc)
newProc.typ.n = newNodeI(oldProc.typ.n.kind, oldProc.typ.n.info)
if oldProc.typ.n.len > 0:
newProc.typ.n.add copyNode(oldProc.typ.n[0])
for i in 1..<oldProc.typ.n.len:
let oldParam = oldProc.typ.n[i].sym
var newParam = getOrDefault(c.transCon.mapping, oldParam.itemId)
if newParam == nil:
newParam = freshOwnedSym(c, oldParam, newProc)
c.transCon.mapping[oldParam.itemId] = newParam
doAssert newParam.kind == nkSym
newProc.typ.addParam newParam.sym
let owner = getCurrOwner(c)
var newVar = copySym(v, c.idgen)
incl(newVar.flagsImpl, sfFromGeneric)
setOwner(newVar, owner)
result = newSymNode(newVar)
proc transformVarSection(c: PTransf, v: PNode): PNode =
result = newTransNode(v)
@@ -375,13 +338,8 @@ proc introduceNewLocalVars(c: PTransf, n: PNode): PNode =
return n
of nkLambdaKinds, nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef: # todo optimize nosideeffects?
result = newTransNode(n)
let oldProc = n[namePos].sym
let x = freshOwnedSym(c, oldProc, oldProc.owner)
c.transCon.mapping[oldProc.itemId] = x
introduceNewRoutineHeaderSyms(c, n[paramsPos], oldProc, x.sym)
if resultPos < n.len and n[resultPos] != nil:
introduceNewRoutineHeaderSyms(c, n[resultPos], oldProc, x.sym)
copyRoutineTypeHeader(c, oldProc, x.sym)
let x = newSymNode(copySym(n[namePos].sym, c.idgen))
c.transCon.mapping[n[namePos].sym.itemId] = x
result[namePos] = x # we have to copy proc definitions for iters
for i in 1..<n.len:
result[i] = introduceNewLocalVars(c, n[i])

View File

@@ -465,24 +465,4 @@ block: # bug #25724
else: yield 1
for w in c():
let n = w
(proc() = discard n)()
block:
iterator c(): int =
yield 1
yield 1
for w in c():
proc p(s: int) =
let sap = s
p(0)
block: # bug #25725
iterator c(): int =
when nimvm: yield 0
else: yield 1
for w in c():
let n = w
proc p(s: int) =
let s = s; discard n
p(0)
(proc() = discard n)()

View File

@@ -45,3 +45,12 @@ elif compiles(nonexistent):
else:
output("whenElse")
template test(): typedesc =
when true:
int
else:
bool
const c = default(test())
echo c