From 72b68229e76a14cb11203b8b0c615cc7feec8272 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Mon, 24 Oct 2022 11:32:08 +0800 Subject: [PATCH 1/7] don't sem const objectConstr defaults --- compiler/semobjconstr.nim | 2 + tests/objects/tobject_default_value.nim | 81 ++++++++++++++----------- 2 files changed, 47 insertions(+), 36 deletions(-) diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim index 1463ba8332434..0ac63a7c0b643 100644 --- a/compiler/semobjconstr.nim +++ b/compiler/semobjconstr.nim @@ -380,6 +380,8 @@ proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) = assert false, "Must not enter here." proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode = + if nfUseDefaultField in n.flags: + return n var t = semTypeNode(c, n[0], nil) result = newNodeIT(nkObjConstr, n.info, t) result.add newNodeIT(nkType, n.info, t) #This will contain the default values to be added in transf diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index efbce3658ae16..39b118ee58c55 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 @@ -206,21 +206,32 @@ template main {.dirty.} = when nimvm: discard "fixme" else: - when defined(gcArc) or defined(gcOrc): - block: #seq - var x = newSeq[Object](10) - let y = x[0] - doAssert y.value == 12 - doAssert y.time == 1.2 - doAssert y.scale == 1 - - block: - var x: seq[Object] - setLen(x, 5) - let y = x[^1] - doAssert y.value == 12 - doAssert y.time == 1.2 - doAssert y.scale == 1 + block: #seq + var x = newSeq[Object](10) + let y = x[0] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + block: + var x: seq[Object] + setLen(x, 5) + let y = x[^1] + doAssert y.value == 12 + 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) @@ -379,7 +390,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 +398,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 @@ -409,21 +419,20 @@ template main {.dirty.} = doAssert z.id == 77 -proc main1 = - var my = @[1, 2, 3, 4, 5] - my.setLen(0) - my.setLen(5) - doAssert my == @[0, 0, 0, 0, 0] + block: + type TokenData = object + campaignMemberships: Table = Table[string, string]() + + let x = default(TokenData) + doAssert x.campaignMemberships.len == 0 + + block: + type TokenData = object + campaignMemberships: Table = newTable[string, string]() -proc main2 = - var my = "hello" - my.setLen(0) - my.setLen(5) - doAssert $(@my) == """@['\x00', '\x00', '\x00', '\x00', '\x00']""" + let x = default(TokenData) + doAssert x.campaignMemberships.len == 0 -when defined(gcArc) or defined(gcOrc): - main1() - main2() static: main() main() From cd94ab8d4629cad8de76887760fbe67e4eddd52b Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Mon, 24 Oct 2022 11:37:15 +0800 Subject: [PATCH 2/7] fixes --- tests/objects/tobject_default_value.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 39b118ee58c55..1abbe55bab796 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -421,14 +421,14 @@ template main {.dirty.} = block: type TokenData = object - campaignMemberships: Table = Table[string, string]() + campaignMemberships = Table[string, string]() let x = default(TokenData) doAssert x.campaignMemberships.len == 0 block: type TokenData = object - campaignMemberships: Table = newTable[string, string]() + campaignMemberships = newTable[string, string]() let x = default(TokenData) doAssert x.campaignMemberships.len == 0 From 2f9019d936abea7f0c513d53b6ca1cd22d041d46 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Tue, 25 Oct 2022 20:42:32 +0800 Subject: [PATCH 3/7] add `efSkipFieldVisibilityCheck`; fixes nkBracket types --- compiler/semdata.nim | 3 ++- compiler/semexprs.nim | 5 ++++- compiler/semobjconstr.nim | 10 ++++++---- tests/objects/tobject_default_value.nim | 11 ++++++----- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 337b5f867e1b9..d1ffab5ebc886 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 08fc4f98f14f0..a5bebe56eae61 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -3075,7 +3075,10 @@ 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) + if n.typ != nil and n.typ.skipTypes(abstractRange).kind == tySequence: + result.typ = n.typ # keeps tySequence type for [] 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 0ac63a7c0b643..e516849139596 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, @@ -380,8 +381,6 @@ proc defaultConstructionError(c: PContext, t: PType, info: TLineInfo) = assert false, "Must not enter here." proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode = - if nfUseDefaultField in n.flags: - return n var t = semTypeNode(c, n[0], nil) result = newNodeIT(nkObjConstr, n.info, t) result.add newNodeIT(nkType, n.info, t) #This will contain the default values to be added in transf @@ -417,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/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 1abbe55bab796..bd76e2854ce85 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -426,12 +426,13 @@ template main {.dirty.} = let x = default(TokenData) doAssert x.campaignMemberships.len == 0 - block: - type TokenData = object - campaignMemberships = newTable[string, string]() + when false: # todo fixme + block: + type TokenData = object + campaignMemberships = newTable[string, string]() - let x = default(TokenData) - doAssert x.campaignMemberships.len == 0 + let x = default(TokenData) + doAssert x.campaignMemberships.len == 0 static: main() From 25716e2be22ef04d61680fd53841d220c62d9839 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Fri, 28 Oct 2022 18:50:15 +0800 Subject: [PATCH 4/7] fixes #20681 --- compiler/semexprs.nim | 2 -- tests/objects/tobject_default_value.nim | 19 +++++-------------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index a5bebe56eae61..39649fa271222 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -3077,8 +3077,6 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType of nkCurly: result = semSetConstr(c, n, expectedType) of nkBracket: result = semArrayConstr(c, n, flags, expectedType) - if n.typ != nil and n.typ.skipTypes(abstractRange).kind == tySequence: - result.typ = n.typ # keeps tySequence type for [] 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/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index bd76e2854ce85..0bb6aa9b3a278 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -418,21 +418,12 @@ template main {.dirty.} = var z {.noinit.}: Pure = Pure(id: 77) doAssert z.id == 77 + block: # bug #20681 + type A = object + d: DateTime = DateTime() - block: - type TokenData = object - campaignMemberships = Table[string, string]() - - let x = default(TokenData) - doAssert x.campaignMemberships.len == 0 - - when false: # todo fixme - block: - type TokenData = object - campaignMemberships = newTable[string, string]() - - let x = default(TokenData) - doAssert x.campaignMemberships.len == 0 + let x = default(A) + doAssert $x == "(d: Uninitialized DateTime)" static: main() From 848b5205072d9fefdb4ec19bccd56a9bf52dc6b3 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+ringabout@users.noreply.github.com> Date: Fri, 28 Oct 2022 19:42:45 +0800 Subject: [PATCH 5/7] fixes tests --- tests/objects/tobject_default_value.nim | 53 +++++++++++++------------ 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/tests/objects/tobject_default_value.nim b/tests/objects/tobject_default_value.nim index 0bb6aa9b3a278..643bba832cb1d 100644 --- a/tests/objects/tobject_default_value.nim +++ b/tests/objects/tobject_default_value.nim @@ -206,32 +206,33 @@ template main {.dirty.} = when nimvm: discard "fixme" else: - block: #seq - var x = newSeq[Object](10) - let y = x[0] - doAssert y.value == 12 - doAssert y.time == 1.2 - doAssert y.scale == 1 - - block: - var x: seq[Object] - setLen(x, 5) - let y = x[^1] - doAssert y.value == 12 - 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']""" + when defined(gcArc) or defined(gcOrc): + block: #seq + var x = newSeq[Object](10) + let y = x[0] + doAssert y.value == 12 + doAssert y.time == 1.2 + doAssert y.scale == 1 + + block: + var x: seq[Object] + setLen(x, 5) + let y = x[^1] + doAssert y.value == 12 + 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) From 344c80c13dea062d4fd72351e9b2c6acd5debc87 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Fri, 28 Oct 2022 21:32:15 +0800 Subject: [PATCH 6/7] suggestion from @metagn --- compiler/semtypes.nim | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 5dfcbac52c3c1..5461b7983a9d9 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) From 2d645ac1070b3a3be56e0431f379ff014c435032 Mon Sep 17 00:00:00 2001 From: xflywind <43030857+xflywind@users.noreply.github.com> Date: Fri, 28 Oct 2022 22:20:54 +0800 Subject: [PATCH 7/7] fixes tests --- tests/objects/tdefaultfieldscheck.nim | 9 +++------ tests/objects/tdefaultrangetypescheck.nim | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/objects/tdefaultfieldscheck.nim b/tests/objects/tdefaultfieldscheck.nim index 9c648ed2b7c16..d6feb29883c2e 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 but expected 'int' -tdefaultfieldscheck.nim(18, 20) Error: type mismatch: got but expected 'string' -tdefaultfieldscheck.nim(20, 16) Error: type mismatch: got but expected 'int' -tdefaultfieldscheck.nim(17, 5) Error: type mismatch: got but expected 'int' -tdefaultfieldscheck.nim(18, 5) Error: type mismatch: got but expected 'string' -tdefaultfieldscheck.nim(20, 5) Error: type mismatch: got but expected 'int' +tdefaultfieldscheck.nim(14, 17) Error: type mismatch: got but expected 'int' +tdefaultfieldscheck.nim(15, 20) Error: type mismatch: got but expected 'string' +tdefaultfieldscheck.nim(17, 16) Error: type mismatch: got but expected 'int' ''' """ diff --git a/tests/objects/tdefaultrangetypescheck.nim b/tests/objects/tdefaultrangetypescheck.nim index 50eeac492efa9..71e7ac59ba2d4 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 """