summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/sem.nim36
-rw-r--r--compiler/semdata.nim1
-rw-r--r--compiler/semmagic.nim3
-rw-r--r--compiler/semobjconstr.nim15
-rw-r--r--tests/types/t21260.nim13
5 files changed, 38 insertions, 30 deletions
diff --git a/compiler/sem.nim b/compiler/sem.nim
index f5283fa3d..c1bb89fc8 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -550,18 +550,17 @@ proc pickCaseBranchIndex(caseExpr, matched: PNode): int =
   if endsWithElse:
     return caseExpr.len - 1
 
-proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, id: var IntSet): seq[PNode]
-proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, id: var IntSet): PNode
-proc defaultNodeField(c: PContext, a: PNode): PNode
+proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode]
 proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode
+proc defaultNodeField(c: PContext, a: PNode): PNode
 
 const defaultFieldsSkipTypes = {tyGenericInst, tyAlias, tySink}
 
-proc defaultFieldsForTuple(c: PContext, recNode: PNode, id: var IntSet, hasDefault: var bool): seq[PNode] =
+proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool): seq[PNode] =
   case recNode.kind
   of nkRecList:
     for field in recNode:
-      result.add defaultFieldsForTuple(c, field, id, hasDefault)
+      result.add defaultFieldsForTuple(c, field, hasDefault)
   of nkSym:
     let field = recNode.sym
     let recType = recNode.typ.skipTypes(defaultFieldsSkipTypes)
@@ -570,7 +569,7 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, id: var IntSet, hasDefau
       result.add newTree(nkExprColonExpr, recNode, field.ast)
     else:
       if recType.kind in {tyObject, tyArray, tyTuple}:
-        let asgnExpr = defaultNodeField(c, recNode, recNode.typ, id)
+        let asgnExpr = defaultNodeField(c, recNode, recNode.typ)
         if asgnExpr != nil:
           hasDefault = true
           asgnExpr.flags.incl nfUseDefaultField
@@ -589,11 +588,11 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, id: var IntSet, hasDefau
   else:
     doAssert false
 
-proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, id: var IntSet): seq[PNode] =
+proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode): seq[PNode] =
   case recNode.kind
   of nkRecList:
     for field in recNode:
-      result.add defaultFieldsForTheUninitialized(c, field, id)
+      result.add defaultFieldsForTheUninitialized(c, field)
   of nkRecCase:
     let discriminator = recNode[0]
     var selectedBranch: int
@@ -607,14 +606,14 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, id: var IntSe
     selectedBranch = recNode.pickCaseBranchIndex defaultValue
     defaultValue.flags.incl nfUseDefaultField
     result.add newTree(nkExprColonExpr, discriminator, defaultValue)
-    result.add defaultFieldsForTheUninitialized(c, recNode[selectedBranch][^1], id)
+    result.add defaultFieldsForTheUninitialized(c, recNode[selectedBranch][^1])
   of nkSym:
     let field = recNode.sym
     let recType = recNode.typ.skipTypes(defaultFieldsSkipTypes)
     if field.ast != nil: #Try to use default value
       result.add newTree(nkExprColonExpr, recNode, field.ast)
     elif recType.kind in {tyObject, tyArray, tyTuple}:
-      let asgnExpr = defaultNodeField(c, recNode, recType, id)
+      let asgnExpr = defaultNodeField(c, recNode, recType)
       if asgnExpr != nil:
         asgnExpr.typ = recType
         asgnExpr.flags.incl nfUseDefaultField
@@ -622,19 +621,17 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, id: var IntSe
   else:
     doAssert false
 
-proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, id: var IntSet): PNode =
+proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode =
   let aTypSkip = aTyp.skipTypes(defaultFieldsSkipTypes)
   if aTypSkip.kind == tyObject:
-    if id.containsOrIncl(aTypSkip.id):
-      return
-    let child = defaultFieldsForTheUninitialized(c, aTypSkip.n, id)
+    let child = defaultFieldsForTheUninitialized(c, aTypSkip.n)
     if child.len > 0:
       var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTypSkip))
       asgnExpr.typ = aTypSkip
       asgnExpr.sons.add child
       result = semExpr(c, asgnExpr)
   elif aTypSkip.kind == tyArray:
-    let child = defaultNodeField(c, a, aTypSkip[1], id)
+    let child = defaultNodeField(c, a, aTypSkip[1])
 
     if child != nil:
       let node = newNode(nkIntLit)
@@ -647,20 +644,15 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, id: var IntSet): PNode
   elif aTypSkip.kind == tyTuple:
     var hasDefault = false
     if aTypSkip.n != nil:
-      let children = defaultFieldsForTuple(c, aTypSkip.n, id, hasDefault)
+      let children = defaultFieldsForTuple(c, aTypSkip.n, hasDefault)
       if hasDefault and children.len > 0:
         result = newNodeI(nkTupleConstr, a.info)
         result.typ = aTyp
         result.sons.add children
         result = semExpr(c, result)
 
-proc defaultNodeField(c: PContext, a: PNode, aTyp: PType): PNode =
-  var s = initIntSet()
-  defaultNodeField(c, a, aTyp, s)
-
 proc defaultNodeField(c: PContext, a: PNode): PNode =
-  var s = initIntSet()
-  result = defaultNodeField(c, a, a.typ, s)
+  result = defaultNodeField(c, a, a.typ)
 
 include semtempl, semgnrc, semstmts, semexprs
 
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 29c2c139f..5b94cc770 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -75,6 +75,7 @@ type
       # overload resolution.
     efNoDiagnostics,
     efTypeAllowed # typeAllowed will be called after
+    efWantNoDefaults
 
   TExprFlags* = set[TExprFlag]
 
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 7025dc867..751ca8fe7 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -20,9 +20,8 @@ proc addDefaultFieldForNew(c: PContext, n: PNode): PNode =
     var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, result[1].info, typ))
     asgnExpr.typ = typ
     var t = typ.skipTypes({tyGenericInst, tyAlias, tySink})[0]
-    var id = initIntSet()
     while true:
-      asgnExpr.sons.add defaultFieldsForTheUninitialized(c, t.n, id)
+      asgnExpr.sons.add defaultFieldsForTheUninitialized(c, t.n)
       let base = t[0]
       if base == nil:
         break
diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim
index 206602677..15e53a639 100644
--- a/compiler/semobjconstr.nim
+++ b/compiler/semobjconstr.nim
@@ -326,10 +326,13 @@ proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext,
       result.status = initUnknown
       result.defaults.add newTree(nkExprColonExpr, n, field.ast)
     else:
-      let defaultExpr = defaultNodeField(c, n)
-      if defaultExpr != nil:
-        result.status = initUnknown
-        result.defaults.add newTree(nkExprColonExpr, n, defaultExpr)
+      if efWantNoDefaults notin flags: # cannot compute defaults at the typeRightPass
+        let defaultExpr = defaultNodeField(c, n)
+        if defaultExpr != nil:
+          result.status = initUnknown
+          result.defaults.add newTree(nkExprColonExpr, n, defaultExpr)
+        else:
+          result.status = initNone
       else:
         result.status = initNone
   else:
@@ -364,7 +367,7 @@ proc initConstrContext(t: PType, initExpr: PNode): ObjConstrContext =
 proc computeRequiresInit(c: PContext, t: PType): bool =
   assert t.kind == tyObject
   var constrCtx = initConstrContext(t, newNode(nkObjConstr))
-  let initResult = semConstructTypeAux(c, constrCtx, {})
+  let initResult = semConstructTypeAux(c, constrCtx, {efWantNoDefaults})
   constrCtx.missingFields.len > 0
 
 proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) =
@@ -374,7 +377,7 @@ proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) =
     assert objType != nil
   if objType.kind == tyObject:
     var constrCtx = initConstrContext(objType, newNodeI(nkObjConstr, info))
-    let initResult = semConstructTypeAux(c, constrCtx, {})
+    let initResult = semConstructTypeAux(c, constrCtx, {efWantNoDefaults})
     if constrCtx.missingFields.len > 0:
       localError(c.config, info,
         "The $1 type doesn't have a default value. The following fields must be initialized: $2." % [typeToString(t), listSymbolNames(constrCtx.missingFields)])
diff --git a/tests/types/t21260.nim b/tests/types/t21260.nim
new file mode 100644
index 000000000..90d6613c1
--- /dev/null
+++ b/tests/types/t21260.nim
@@ -0,0 +1,13 @@
+discard """
+  errormsg: "illegal recursion in type 'Foo'"
+  line: 8
+"""
+
+type
+  Kind = enum kA, kB
+  Foo = object
+    case k: Kind:
+    of kA:
+      foo: Foo
+    of kB:
+      discard