Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixes #20681; add efSkipFieldVisibilityCheck to skip check #20639

Merged
merged 10 commits into from
Oct 28, 2022
3 changes: 2 additions & 1 deletion compiler/semdata.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
3 changes: 2 additions & 1 deletion compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 6 additions & 2 deletions compiler/semobjconstr.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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

Expand Down
26 changes: 12 additions & 14 deletions compiler/semtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down
9 changes: 3 additions & 6 deletions tests/objects/tdefaultfieldscheck.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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'
'''
"""

Expand Down
2 changes: 1 addition & 1 deletion tests/objects/tdefaultrangetypescheck.nim
Original file line number Diff line number Diff line change
@@ -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
"""

Expand Down
46 changes: 24 additions & 22 deletions tests/objects/tobject_default_value.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ discard """
targets: "c cpp js"
"""

import times
import std/[times, tables]

type
Guess = object
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -379,20 +391,19 @@ 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)
doAssert x.def.id == 1
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
Expand All @@ -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()