mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-11 16:00:54 +00:00
generate tyFromExpr for when in generics (#24066)
fixes #22342, fixes #22607 Another followup of #22029, `when` expressions in general in generic type bodies now behave like `nkRecWhen` does since #24042, leaving them as `tyFromExpr` if a condition is uncertain. The tests for the issues were originally added but left disabled in #24005.
This commit is contained in:
@@ -2685,6 +2685,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
whenNimvm = exprNode.sym.magic == mNimvm
|
||||
if whenNimvm: n.flags.incl nfLL
|
||||
|
||||
var cannotResolve = false
|
||||
for i in 0..<n.len:
|
||||
var it = n[i]
|
||||
case it.kind
|
||||
@@ -2695,6 +2696,20 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
it[1] = semExpr(c, it[1], flags)
|
||||
typ = commonType(c, typ, it[1].typ)
|
||||
result = n # when nimvm is not elimited until codegen
|
||||
elif c.inGenericContext > 0:
|
||||
let e = semExprWithType(c, it[0])
|
||||
if e.typ.kind == tyFromExpr:
|
||||
it[0] = makeStaticExpr(c, e)
|
||||
cannotResolve = true
|
||||
else:
|
||||
it[0] = forceBool(c, e)
|
||||
let val = getConstExpr(c.module, it[0], c.idgen, c.graph)
|
||||
if val == nil or val.kind != nkIntLit:
|
||||
cannotResolve = true
|
||||
elif not cannotResolve and val.intVal != 0 and result == nil:
|
||||
setResult(it[1])
|
||||
return # we're not in nimvm and we already have a result
|
||||
it[1] = semGenericStmt(c, it[1])
|
||||
else:
|
||||
let e = forceBool(c, semConstExpr(c, it[0]))
|
||||
if e.kind != nkIntLit:
|
||||
@@ -2706,7 +2721,9 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
return # we're not in nimvm and we already have a result
|
||||
of nkElse, nkElseExpr:
|
||||
checkSonsLen(it, 1, c.config)
|
||||
if result == nil or whenNimvm:
|
||||
if cannotResolve:
|
||||
it[0] = semGenericStmt(c, it[0])
|
||||
elif result == nil or whenNimvm:
|
||||
if semCheck:
|
||||
it[0] = semExpr(c, it[0], flags)
|
||||
typ = commonType(c, typ, it[0].typ)
|
||||
@@ -2715,6 +2732,10 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
if result == nil:
|
||||
result = it[0]
|
||||
else: illFormedAst(n, c.config)
|
||||
if cannotResolve:
|
||||
result = n
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
return
|
||||
if result == nil:
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
if whenNimvm:
|
||||
|
||||
@@ -2068,7 +2068,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
of nkWhenStmt:
|
||||
var whenResult = semWhen(c, n, false)
|
||||
if whenResult.kind == nkStmtList: whenResult.transitionSonsKind(nkStmtListType)
|
||||
result = semTypeNode(c, whenResult, prev)
|
||||
if whenResult.kind == nkWhenStmt:
|
||||
result = whenResult.typ
|
||||
else:
|
||||
result = semTypeNode(c, whenResult, prev)
|
||||
of nkBracketExpr:
|
||||
checkMinSonsLen(n, 2, c.config)
|
||||
var head = n[0]
|
||||
|
||||
Reference in New Issue
Block a user