mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
* fixes #22613; Default value does not work with object's discriminator fixes #22613 * merge branches * add a test case * fixes status * remove outdated comments * move collectBranchFields into the global scope
This commit is contained in:
@@ -75,7 +75,6 @@ proc locateFieldInInitExpr(c: PContext, field: PSym, initExpr: PNode): PNode =
|
||||
|
||||
proc semConstrField(c: PContext, flags: TExprFlags,
|
||||
field: PSym, initExpr: PNode): PNode =
|
||||
result = nil
|
||||
let assignment = locateFieldInInitExpr(c, field, initExpr)
|
||||
if assignment != nil:
|
||||
if nfSem in assignment.flags: return assignment[1]
|
||||
@@ -93,7 +92,9 @@ proc semConstrField(c: PContext, flags: TExprFlags,
|
||||
assignment[0] = newSymNode(field)
|
||||
assignment[1] = initValue
|
||||
assignment.flags.incl nfSem
|
||||
return initValue
|
||||
result = initValue
|
||||
else:
|
||||
result = nil
|
||||
|
||||
proc branchVals(c: PContext, caseNode: PNode, caseIdx: int,
|
||||
isStmtBranch: bool): IntSet =
|
||||
@@ -192,6 +193,23 @@ proc collectOrAddMissingCaseFields(c: PContext, branchNode: PNode,
|
||||
asgnExpr.typ = recTyp
|
||||
defaults.add newTree(nkExprColonExpr, newSymNode(sym), asgnExpr)
|
||||
|
||||
proc collectBranchFields(c: PContext, n: PNode, discriminatorVal: PNode,
|
||||
constrCtx: var ObjConstrContext, flags: TExprFlags) =
|
||||
# All bets are off. If any of the branches has a mandatory
|
||||
# fields we must produce an error:
|
||||
for i in 1..<n.len:
|
||||
let branchNode = n[i]
|
||||
if branchNode != nil:
|
||||
let oldCheckDefault = constrCtx.checkDefault
|
||||
constrCtx.checkDefault = true
|
||||
let (_, defaults) = semConstructFields(c, branchNode[^1], constrCtx, flags)
|
||||
constrCtx.checkDefault = oldCheckDefault
|
||||
if len(defaults) > 0:
|
||||
localError(c.config, discriminatorVal.info, "branch initialization " &
|
||||
"with a runtime discriminator is not supported " &
|
||||
"for a branch whose fields have default values.")
|
||||
discard collectMissingCaseFields(c, n[i], constrCtx, @[])
|
||||
|
||||
proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext,
|
||||
flags: TExprFlags): tuple[status: InitStatus, defaults: seq[PNode]] =
|
||||
result = (initUnknown, @[])
|
||||
@@ -331,13 +349,27 @@ proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext,
|
||||
discriminator.sym,
|
||||
constrCtx.initExpr)
|
||||
if discriminatorVal == nil:
|
||||
# None of the branches were explicitly selected by the user and no
|
||||
# value was given to the discrimator. We can assume that it will be
|
||||
# initialized to zero and this will select a particular branch as
|
||||
# a result:
|
||||
let defaultValue = newIntLit(c.graph, constrCtx.initExpr.info, 0)
|
||||
let matchedBranch = n.pickCaseBranch defaultValue
|
||||
discard collectMissingCaseFields(c, matchedBranch, constrCtx, @[])
|
||||
if discriminator.sym.ast != nil:
|
||||
# branch is selected by the default field value of discriminator
|
||||
let discriminatorDefaultVal = discriminator.sym.ast
|
||||
result.status = initUnknown
|
||||
result.defaults.add newTree(nkExprColonExpr, n[0], discriminatorDefaultVal)
|
||||
if discriminatorDefaultVal.kind == nkIntLit:
|
||||
let matchedBranch = n.pickCaseBranch discriminatorDefaultVal
|
||||
if matchedBranch != nil:
|
||||
let (_, defaults) = semConstructFields(c, matchedBranch[^1], constrCtx, flags)
|
||||
result.defaults.add defaults
|
||||
collectOrAddMissingCaseFields(c, matchedBranch, constrCtx, result.defaults)
|
||||
else:
|
||||
collectBranchFields(c, n, discriminatorDefaultVal, constrCtx, flags)
|
||||
else:
|
||||
# None of the branches were explicitly selected by the user and no
|
||||
# value was given to the discrimator. We can assume that it will be
|
||||
# initialized to zero and this will select a particular branch as
|
||||
# a result:
|
||||
let defaultValue = newIntLit(c.graph, constrCtx.initExpr.info, 0)
|
||||
let matchedBranch = n.pickCaseBranch defaultValue
|
||||
discard collectMissingCaseFields(c, matchedBranch, constrCtx, @[])
|
||||
else:
|
||||
result.status = initPartial
|
||||
if discriminatorVal.kind == nkIntLit:
|
||||
@@ -349,20 +381,8 @@ proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext,
|
||||
result.defaults.add defaults
|
||||
collectOrAddMissingCaseFields(c, matchedBranch, constrCtx, result.defaults)
|
||||
else:
|
||||
# All bets are off. If any of the branches has a mandatory
|
||||
# fields we must produce an error:
|
||||
for i in 1..<n.len:
|
||||
let branchNode = n[i]
|
||||
if branchNode != nil:
|
||||
let oldCheckDefault = constrCtx.checkDefault
|
||||
constrCtx.checkDefault = true
|
||||
let (_, defaults) = semConstructFields(c, branchNode[^1], constrCtx, flags)
|
||||
constrCtx.checkDefault = oldCheckDefault
|
||||
if len(defaults) > 0:
|
||||
localError(c.config, discriminatorVal.info, "branch initialization " &
|
||||
"with a runtime discriminator is not supported " &
|
||||
"for a branch whose fields have default values.")
|
||||
discard collectMissingCaseFields(c, n[i], constrCtx, @[])
|
||||
collectBranchFields(c, n, discriminatorVal, constrCtx, flags)
|
||||
|
||||
of nkSym:
|
||||
let field = n.sym
|
||||
let e = semConstrField(c, flags, field, constrCtx.initExpr)
|
||||
|
||||
@@ -377,7 +377,7 @@ template main {.dirty.} =
|
||||
Red, Blue, Yellow
|
||||
|
||||
type
|
||||
ObjectVarint3 = object # fixme it doesn't work with static
|
||||
ObjectVarint3 = object
|
||||
case kind: Color = Blue
|
||||
of Red:
|
||||
data1: int = 10
|
||||
@@ -703,5 +703,20 @@ template main {.dirty.} =
|
||||
var foo = new Container
|
||||
doAssert int(foo.thing[0].x) == 1
|
||||
|
||||
block: # bug #22613
|
||||
type
|
||||
K = enum
|
||||
A = "a"
|
||||
B = "b"
|
||||
T = object
|
||||
case kind: K = B
|
||||
of A:
|
||||
a: int
|
||||
of B:
|
||||
b: float
|
||||
|
||||
doAssert T().kind == B
|
||||
|
||||
|
||||
static: main()
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user