summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semdata.nim3
-rw-r--r--compiler/semexprs.nim3
-rw-r--r--compiler/semobjconstr.nim8
-rw-r--r--compiler/semtypes.nim26
-rw-r--r--tests/objects/tdefaultfieldscheck.nim9
-rw-r--r--tests/objects/tdefaultrangetypescheck.nim2
-rw-r--r--tests/objects/tobject_default_value.nim46
7 files changed, 50 insertions, 47 deletions
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 337b5f867..d1ffab5eb 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -69,7 +69,8 @@ type
     efWantStmt, efAllowStmt, efDetermineType, efExplain,
     efWantValue, efOperand, efNoSemCheck,
     efNoEvaluateGeneric, efInCall, efFromHlo, efNoSem2Check,
-    efNoUndeclared, efIsDotCall, efCannotBeDotCall
+    efNoUndeclared, efIsDotCall, efCannotBeDotCall,
+    efSkipFieldVisibilityCheck
       # Use this if undeclared identifiers should not raise an error during
       # overload resolution.
 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 08fc4f98f..39649fa27 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -3075,7 +3075,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
     of paTupleFields: result = semTupleFieldsConstr(c, n, flags, expectedType)
     of paSingle: result = semExpr(c, n[0], flags, expectedType)
   of nkCurly: result = semSetConstr(c, n, expectedType)
-  of nkBracket: result = semArrayConstr(c, n, flags, expectedType)
+  of nkBracket:
+    result = semArrayConstr(c, n, flags, expectedType)
   of nkObjConstr: result = semObjConstr(c, n, flags, expectedType)
   of nkLambdaKinds: result = semProcAux(c, n, skProc, lambdaPragmas, flags)
   of nkDerefExpr: result = semDeref(c, n)
diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim
index 1463ba833..e51684913 100644
--- a/compiler/semobjconstr.nim
+++ b/compiler/semobjconstr.nim
@@ -76,7 +76,8 @@ proc semConstrField(c: PContext, flags: TExprFlags,
   let assignment = locateFieldInInitExpr(c, field, initExpr)
   if assignment != nil:
     if nfSem in assignment.flags: return assignment[1]
-    if nfUseDefaultField in assignment[1].flags:
+    if nfUseDefaultField in assignment[1].flags or
+       efSkipFieldVisibilityCheck in flags:
       discard
     elif not fieldVisible(c, field):
       localError(c.config, initExpr.info,
@@ -415,7 +416,10 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
   # field (if this is a case object, initialized fields in two different
   # branches will be reported as an error):
   var constrCtx = initConstrContext(t, result)
-  let (initResult, defaults) = semConstructTypeAux(c, constrCtx, flags)
+  let (initResult, defaults) = if nfUseDefaultField in n.flags:
+        semConstructTypeAux(c, constrCtx, flags + {efSkipFieldVisibilityCheck})
+      else:
+        semConstructTypeAux(c, constrCtx, flags)
   result[0].sons.add defaults
   var hasError = false # needed to split error detect/report for better msgs
 
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 5dfcbac52..5461b7983 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -220,6 +220,16 @@ proc isRecursiveType(t: PType, cycleDetector: var IntSet): bool =
   else:
     return false
 
+proc fitDefaultNode(c: PContext, n: PNode): PType =
+  let expectedType = if n[^2].kind != nkEmpty: semTypeNode(c, n[^2], nil) else: nil
+  n[^1] = semConstExpr(c, n[^1], expectedType = expectedType)
+  if n[^2].kind != nkEmpty:
+    if expectedType != nil:
+      n[^1] = fitNodeConsiderViewType(c, expectedType, n[^1], n[^1].info)
+    result = n[^1].typ
+  else:
+    result = n[^1].typ
+
 proc isRecursiveType*(t: PType): bool =
   # handle simple recusive types before typeFinalPass
   var cycleDetector = initIntSet()
@@ -484,13 +494,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
     checkMinSonsLen(a, 3, c.config)
     var hasDefaultField = a[^1].kind != nkEmpty
     if hasDefaultField:
-      a[^1] = semConstExpr(c, a[^1])
-      if a[^2].kind != nkEmpty:
-        typ = semTypeNode(c, a[^2], nil)
-        let def = semExprWithType(c, a[^1], {}, typ)
-        typ = fitNodeConsiderViewType(c, typ, def, def.info).typ
-      else:
-        typ = a[^1].typ
+      typ = fitDefaultNode(c, a)
     elif a[^2].kind != nkEmpty:
       typ = semTypeNode(c, a[^2], nil)
       if c.graph.config.isDefined("nimPreviewRangeDefault") and typ.skipTypes(abstractInst).kind == tyRange:
@@ -824,13 +828,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
     var typ: PType
     var hasDefaultField = n[^1].kind != nkEmpty
     if hasDefaultField:
-      n[^1] = semConstExpr(c, n[^1])
-      if n[^2].kind != nkEmpty:
-        typ = semTypeNode(c, n[^2], nil)
-        let def = semExprWithType(c, n[^1], {}, typ)
-        typ = fitNodeConsiderViewType(c, typ, def, def.info).typ
-      else:
-        typ = n[^1].typ
+      typ = fitDefaultNode(c, n)
       propagateToOwner(rectype, typ)
     elif n[^2].kind == nkEmpty:
       localError(c.config, n.info, errTypeExpected)
diff --git a/tests/objects/tdefaultfieldscheck.nim b/tests/objects/tdefaultfieldscheck.nim
index 9c648ed2b..d6feb2988 100644
--- a/tests/objects/tdefaultfieldscheck.nim
+++ b/tests/objects/tdefaultfieldscheck.nim
@@ -3,12 +3,9 @@ discard """
   errormsg: ""
   nimout:
 '''
-tdefaultfieldscheck.nim(17, 17) Error: type mismatch: got <string> but expected 'int'
-tdefaultfieldscheck.nim(18, 20) Error: type mismatch: got <int literal(12)> but expected 'string'
-tdefaultfieldscheck.nim(20, 16) Error: type mismatch: got <float64> but expected 'int'
-tdefaultfieldscheck.nim(17, 5) Error: type mismatch: got <string> but expected 'int'
-tdefaultfieldscheck.nim(18, 5) Error: type mismatch: got <int literal(12)> but expected 'string'
-tdefaultfieldscheck.nim(20, 5) Error: type mismatch: got <float64> but expected 'int'
+tdefaultfieldscheck.nim(14, 17) Error: type mismatch: got <string> but expected 'int'
+tdefaultfieldscheck.nim(15, 20) Error: type mismatch: got <int literal(12)> but expected 'string'
+tdefaultfieldscheck.nim(17, 16) Error: type mismatch: got <float64> but expected 'int'
 '''
 """
 
diff --git a/tests/objects/tdefaultrangetypescheck.nim b/tests/objects/tdefaultrangetypescheck.nim
index 50eeac492..71e7ac59b 100644
--- a/tests/objects/tdefaultrangetypescheck.nim
+++ b/tests/objects/tdefaultrangetypescheck.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "conversion from int literal(0) to range 1..5(int) is invalid"
+  errormsg: "cannot convert 0 to range 1..5(int)"
   line: 9
 """
 
diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim
index efbce3658..643bba832 100644
--- a/tests/objects/tobject_default_value.nim
+++ b/tests/objects/tobject_default_value.nim
@@ -3,7 +3,7 @@ discard """
   targets: "c cpp js"
 """
 
-import times
+import std/[times, tables]
 
 type
   Guess = object
@@ -222,6 +222,18 @@ template main {.dirty.} =
         doAssert y.time == 1.2
         doAssert y.scale == 1
 
+      block:
+        var my = @[1, 2, 3, 4, 5]
+        my.setLen(0)
+        my.setLen(5)
+        doAssert my == @[0, 0, 0, 0, 0]
+
+      block:
+        var my = "hello"
+        my.setLen(0)
+        my.setLen(5)
+        doAssert $(@my) == """@['\x00', '\x00', '\x00', '\x00', '\x00']"""
+
   block: # array
     var x: array[10, Object] = arrayWith(default(Object), 10)
     let y = x[0]
@@ -379,7 +391,7 @@ template main {.dirty.} =
       doAssert x.id == 1
       doAssert x.obj == default(ObjectBase)
       doAssert x.name == ""
-    
+
     block:
       var x = default(Class)
       doAssert x.def == default(Default)
@@ -387,12 +399,11 @@ template main {.dirty.} =
       doAssert x.def.obj == default(ObjectBase)
       doAssert x.def.name == ""
 
-    when not defined(cpp):
-      block:
-        var x = default(Member)
-        doAssert x.def.id == 777
-        doAssert x.def.obj == default(ObjectBase)
-        doAssert x.def.name == "fine"
+    block:
+      var x = default(Member)
+      doAssert x.def.id == 777
+      doAssert x.def.obj == default(ObjectBase)
+      doAssert x.def.name == "fine"
 
   block:
     var x {.noinit.} = 12
@@ -408,22 +419,13 @@ template main {.dirty.} =
     var z {.noinit.}: Pure = Pure(id: 77)
     doAssert z.id == 77
 
+  block: # bug #20681
+    type A = object
+      d: DateTime = DateTime()
 
-proc main1 =
-  var my = @[1, 2, 3, 4, 5]
-  my.setLen(0)
-  my.setLen(5)
-  doAssert my == @[0, 0, 0, 0, 0]
-
-proc main2 =
-  var my = "hello"
-  my.setLen(0)
-  my.setLen(5)
-  doAssert $(@my) == """@['\x00', '\x00', '\x00', '\x00', '\x00']"""
+    let x = default(A)
+    doAssert $x == "(d: Uninitialized DateTime)"
 
-when defined(gcArc) or defined(gcOrc):
-  main1()
-  main2()
 
 static: main()
 main()