Cosmetic compiler cleanup (#12718)
* Cleanup compiler code base
* Unify add calls
* Unify len invocations
* Unify range operators
* Fix oversight
* Remove {.procvar.} pragma
* initCandidate -> newCandidate where reasonable
* Unify safeLen calls
This commit is contained in:
parent
b662842bd0
commit
7e747d11c6
109 changed files with 6115 additions and 6254 deletions
|
|
@ -91,7 +91,7 @@ proc isLocalVar(a: PEffects, s: PSym): bool =
|
|||
proc getLockLevel(t: PType): TLockLevel =
|
||||
var t = t
|
||||
# tyGenericInst(TLock {tyGenericBody}, tyStatic, tyObject):
|
||||
if t.kind == tyGenericInst and t.len == 3: t = t.sons[1]
|
||||
if t.kind == tyGenericInst and t.len == 3: t = t[1]
|
||||
if t.kind == tyStatic and t.n != nil and t.n.kind in {nkCharLit..nkInt64Lit}:
|
||||
result = t.n.intVal.TLockLevel
|
||||
|
||||
|
|
@ -131,21 +131,21 @@ proc guardGlobal(a: PEffects; n: PNode; guard: PSym) =
|
|||
# 'guard*' are checks which are concerned with 'guard' annotations
|
||||
# (var x{.guard: y.}: int)
|
||||
proc guardDotAccess(a: PEffects; n: PNode) =
|
||||
let ri = n.sons[1]
|
||||
let ri = n[1]
|
||||
if ri.kind != nkSym or ri.sym.kind != skField: return
|
||||
var g = ri.sym.guard
|
||||
if g.isNil or a.isTopLevel: return
|
||||
# fixup guard:
|
||||
if g.kind == skUnknown:
|
||||
var field: PSym = nil
|
||||
var ty = n.sons[0].typ.skipTypes(abstractPtrs)
|
||||
var ty = n[0].typ.skipTypes(abstractPtrs)
|
||||
if ty.kind == tyTuple and not ty.n.isNil:
|
||||
field = lookupInRecord(ty.n, g.name)
|
||||
else:
|
||||
while ty != nil and ty.kind == tyObject:
|
||||
field = lookupInRecord(ty.n, g.name)
|
||||
if field != nil: break
|
||||
ty = ty.sons[0]
|
||||
ty = ty[0]
|
||||
if ty == nil: break
|
||||
ty = ty.skipTypes(skipPtrs)
|
||||
if field == nil:
|
||||
|
|
@ -156,8 +156,8 @@ proc guardDotAccess(a: PEffects; n: PNode) =
|
|||
# XXX unfortunately this is not correct for generic instantiations!
|
||||
if g.kind == skField:
|
||||
let dot = newNodeI(nkDotExpr, n.info, 2)
|
||||
dot.sons[0] = n.sons[0]
|
||||
dot.sons[1] = newSymNode(g)
|
||||
dot[0] = n[0]
|
||||
dot[1] = newSymNode(g)
|
||||
dot.typ = g.typ
|
||||
for L in a.locked:
|
||||
#if a.guards.sameSubexprs(dot, L): return
|
||||
|
|
@ -305,7 +305,7 @@ proc createTag(g: ModuleGraph; n: PNode): PNode =
|
|||
proc addEffect(a: PEffects, e: PNode, useLineInfo=true) =
|
||||
assert e.kind != nkRaiseStmt
|
||||
var aa = a.exc
|
||||
for i in a.bottom ..< aa.len:
|
||||
for i in a.bottom..<aa.len:
|
||||
if sameType(a.graph.excType(aa[i]), a.graph.excType(e)):
|
||||
if not useLineInfo or a.config.cmd == cmdDoc: return
|
||||
elif aa[i].info == e.info: return
|
||||
|
|
@ -313,7 +313,7 @@ proc addEffect(a: PEffects, e: PNode, useLineInfo=true) =
|
|||
|
||||
proc addTag(a: PEffects, e: PNode, useLineInfo=true) =
|
||||
var aa = a.tags
|
||||
for i in 0 ..< aa.len:
|
||||
for i in 0..<aa.len:
|
||||
if sameType(aa[i].typ.skipTypes(skipPtrs), e.typ.skipTypes(skipPtrs)):
|
||||
if not useLineInfo or a.config.cmd == cmdDoc: return
|
||||
elif aa[i].info == e.info: return
|
||||
|
|
@ -344,7 +344,7 @@ proc catches(tracked: PEffects, e: PType) =
|
|||
while i < L:
|
||||
# r supertype of e?
|
||||
if safeInheritanceDiff(tracked.graph.excType(tracked.exc[i]), e) <= 0:
|
||||
tracked.exc.sons[i] = tracked.exc.sons[L-1]
|
||||
tracked.exc[i] = tracked.exc[L-1]
|
||||
dec L
|
||||
else:
|
||||
inc i
|
||||
|
|
@ -366,7 +366,7 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
|
|||
var inter: TIntersection = @[]
|
||||
|
||||
inc tracked.inTryStmt
|
||||
track(tracked, n.sons[0])
|
||||
track(tracked, n[0])
|
||||
dec tracked.inTryStmt
|
||||
for i in oldState..<tracked.init.len:
|
||||
addToIntersection(inter, tracked.init[i])
|
||||
|
|
@ -375,35 +375,33 @@ proc trackTryStmt(tracked: PEffects, n: PNode) =
|
|||
var hasFinally = false
|
||||
|
||||
# Collect the exceptions caught by the except branches
|
||||
for i in 1 ..< n.len:
|
||||
let b = n.sons[i]
|
||||
let blen = len(b)
|
||||
for i in 1..<n.len:
|
||||
let b = n[i]
|
||||
if b.kind == nkExceptBranch:
|
||||
inc branches
|
||||
if blen == 1:
|
||||
if b.len == 1:
|
||||
catchesAll(tracked)
|
||||
else:
|
||||
for j in 0 .. blen - 2:
|
||||
if b.sons[j].isInfixAs():
|
||||
assert(b.sons[j][1].kind == nkType)
|
||||
catches(tracked, b.sons[j][1].typ)
|
||||
for j in 0..<b.len - 1:
|
||||
if b[j].isInfixAs():
|
||||
assert(b[j][1].kind == nkType)
|
||||
catches(tracked, b[j][1].typ)
|
||||
else:
|
||||
assert(b.sons[j].kind == nkType)
|
||||
catches(tracked, b.sons[j].typ)
|
||||
assert(b[j].kind == nkType)
|
||||
catches(tracked, b[j].typ)
|
||||
else:
|
||||
assert b.kind == nkFinally
|
||||
# Add any other exception raised in the except bodies
|
||||
for i in 1 ..< n.len:
|
||||
let b = n.sons[i]
|
||||
let blen = len(b)
|
||||
for i in 1..<n.len:
|
||||
let b = n[i]
|
||||
if b.kind == nkExceptBranch:
|
||||
setLen(tracked.init, oldState)
|
||||
track(tracked, b.sons[blen-1])
|
||||
track(tracked, b[^1])
|
||||
for i in oldState..<tracked.init.len:
|
||||
addToIntersection(inter, tracked.init[i])
|
||||
else:
|
||||
setLen(tracked.init, oldState)
|
||||
track(tracked, b.sons[blen-1])
|
||||
track(tracked, b[^1])
|
||||
hasFinally = true
|
||||
|
||||
tracked.bottom = oldBottom
|
||||
|
|
@ -427,8 +425,8 @@ proc isForwardedProc(n: PNode): bool =
|
|||
result = n.kind == nkSym and sfForward in n.sym.flags
|
||||
|
||||
proc trackPragmaStmt(tracked: PEffects, n: PNode) =
|
||||
for i in 0 ..< len(n):
|
||||
var it = n.sons[i]
|
||||
for i in 0..<n.len:
|
||||
var it = n[i]
|
||||
if whichPragma(it) == wEffects:
|
||||
# list the computed effects up to here:
|
||||
listEffects(tracked)
|
||||
|
|
@ -459,7 +457,7 @@ proc mergeLockLevels(tracked: PEffects, n: PNode, lockLevel: TLockLevel) =
|
|||
tracked.maxLockLevel = max(tracked.maxLockLevel, lockLevel)
|
||||
|
||||
proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) =
|
||||
let pragma = s.ast.sons[pragmasPos]
|
||||
let pragma = s.ast[pragmasPos]
|
||||
let spec = effectSpec(pragma, wRaises)
|
||||
mergeEffects(tracked, spec, n)
|
||||
|
||||
|
|
@ -531,8 +529,8 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType; caller: PNode)
|
|||
let op = a.typ
|
||||
# assume indirect calls are taken here:
|
||||
if op != nil and op.kind == tyProc and n.skipConv.kind != nkNilLit and not isTrival(caller):
|
||||
internalAssert tracked.config, op.n.sons[0].kind == nkEffectList
|
||||
var effectList = op.n.sons[0]
|
||||
internalAssert tracked.config, op.n[0].kind == nkEffectList
|
||||
var effectList = op.n[0]
|
||||
var s = n.skipConv
|
||||
if s.kind == nkCast and s[1].typ.kind == tyProc:
|
||||
s = s[1]
|
||||
|
|
@ -553,8 +551,8 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType; caller: PNode)
|
|||
elif tfNoSideEffect notin op.flags and not isOwnedProcVar(a, tracked.owner):
|
||||
markSideEffect(tracked, a)
|
||||
else:
|
||||
mergeEffects(tracked, effectList.sons[exceptionEffects], n)
|
||||
mergeTags(tracked, effectList.sons[tagEffects], n)
|
||||
mergeEffects(tracked, effectList[exceptionEffects], n)
|
||||
mergeTags(tracked, effectList[tagEffects], n)
|
||||
if notGcSafe(op):
|
||||
if warnGcUnsafe in tracked.config.notes: warnAboutGcUnsafe(n, tracked.config)
|
||||
markGcUnsafe(tracked, a)
|
||||
|
|
@ -582,23 +580,23 @@ proc breaksBlock(n: PNode): bool =
|
|||
it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags
|
||||
|
||||
proc trackCase(tracked: PEffects, n: PNode) =
|
||||
track(tracked, n.sons[0])
|
||||
track(tracked, n[0])
|
||||
let oldState = tracked.init.len
|
||||
let oldFacts = tracked.guards.s.len
|
||||
let stringCase = skipTypes(n.sons[0].typ,
|
||||
let stringCase = skipTypes(n[0].typ,
|
||||
abstractVarRange-{tyTypeDesc}).kind in {tyFloat..tyFloat128, tyString}
|
||||
let interesting = not stringCase and interestingCaseExpr(n.sons[0]) and
|
||||
let interesting = not stringCase and interestingCaseExpr(n[0]) and
|
||||
warnProveField in tracked.config.notes
|
||||
var inter: TIntersection = @[]
|
||||
var toCover = 0
|
||||
for i in 1..<n.len:
|
||||
let branch = n.sons[i]
|
||||
let branch = n[i]
|
||||
setLen(tracked.init, oldState)
|
||||
if interesting:
|
||||
setLen(tracked.guards.s, oldFacts)
|
||||
addCaseBranchFacts(tracked.guards, n, i)
|
||||
for i in 0 ..< branch.len:
|
||||
track(tracked, branch.sons[i])
|
||||
for i in 0..<branch.len:
|
||||
track(tracked, branch[i])
|
||||
if not breaksBlock(branch.lastSon): inc toCover
|
||||
for i in oldState..<tracked.init.len:
|
||||
addToIntersection(inter, tracked.init[i])
|
||||
|
|
@ -611,28 +609,28 @@ proc trackCase(tracked: PEffects, n: PNode) =
|
|||
setLen(tracked.guards.s, oldFacts)
|
||||
|
||||
proc trackIf(tracked: PEffects, n: PNode) =
|
||||
track(tracked, n.sons[0].sons[0])
|
||||
track(tracked, n[0][0])
|
||||
let oldFacts = tracked.guards.s.len
|
||||
addFact(tracked.guards, n.sons[0].sons[0])
|
||||
addFact(tracked.guards, n[0][0])
|
||||
let oldState = tracked.init.len
|
||||
|
||||
var inter: TIntersection = @[]
|
||||
var toCover = 0
|
||||
track(tracked, n.sons[0].sons[1])
|
||||
if not breaksBlock(n.sons[0].sons[1]): inc toCover
|
||||
track(tracked, n[0][1])
|
||||
if not breaksBlock(n[0][1]): inc toCover
|
||||
for i in oldState..<tracked.init.len:
|
||||
addToIntersection(inter, tracked.init[i])
|
||||
|
||||
for i in 1..<n.len:
|
||||
let branch = n.sons[i]
|
||||
let branch = n[i]
|
||||
setLen(tracked.guards.s, oldFacts)
|
||||
for j in 0..i-1:
|
||||
addFactNeg(tracked.guards, n.sons[j].sons[0])
|
||||
addFactNeg(tracked.guards, n[j][0])
|
||||
if branch.len > 1:
|
||||
addFact(tracked.guards, branch.sons[0])
|
||||
addFact(tracked.guards, branch[0])
|
||||
setLen(tracked.init, oldState)
|
||||
for i in 0 ..< branch.len:
|
||||
track(tracked, branch.sons[i])
|
||||
for i in 0..<branch.len:
|
||||
track(tracked, branch[i])
|
||||
if not breaksBlock(branch.lastSon): inc toCover
|
||||
for i in oldState..<tracked.init.len:
|
||||
addToIntersection(inter, tracked.init[i])
|
||||
|
|
@ -647,14 +645,14 @@ proc trackBlock(tracked: PEffects, n: PNode) =
|
|||
if n.kind in {nkStmtList, nkStmtListExpr}:
|
||||
var oldState = -1
|
||||
for i in 0..<n.len:
|
||||
if hasSubnodeWith(n.sons[i], nkBreakStmt):
|
||||
if hasSubnodeWith(n[i], nkBreakStmt):
|
||||
# block:
|
||||
# x = def
|
||||
# if ...: ... break # some nested break
|
||||
# y = def
|
||||
# --> 'y' not defined after block!
|
||||
if oldState < 0: oldState = tracked.init.len
|
||||
track(tracked, n.sons[i])
|
||||
track(tracked, n[i])
|
||||
if oldState > 0: setLen(tracked.init, oldState)
|
||||
else:
|
||||
track(tracked, n)
|
||||
|
|
@ -664,10 +662,10 @@ proc isTrue*(n: PNode): bool =
|
|||
n.kind == nkIntLit and n.intVal != 0
|
||||
|
||||
proc paramType(op: PType, i: int): PType =
|
||||
if op != nil and i < op.len: result = op.sons[i]
|
||||
if op != nil and i < op.len: result = op[i]
|
||||
|
||||
proc cstringCheck(tracked: PEffects; n: PNode) =
|
||||
if n.sons[0].typ.kind == tyCString and (let a = skipConv(n[1]);
|
||||
if n[0].typ.kind == tyCString and (let a = skipConv(n[1]);
|
||||
a.typ.kind == tyString and a.kind notin {nkStrLit..nkTripleStrLit}):
|
||||
message(tracked.config, n.info, warnUnsafeCode, renderTree(n))
|
||||
|
||||
|
|
@ -696,11 +694,11 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
tracked.owner.flags.incl sfInjectDestructors
|
||||
of nkRaiseStmt:
|
||||
if n[0].kind != nkEmpty:
|
||||
n.sons[0].info = n.info
|
||||
#throws(tracked.exc, n.sons[0])
|
||||
addEffect(tracked, n.sons[0], useLineInfo=false)
|
||||
for i in 0 ..< safeLen(n):
|
||||
track(tracked, n.sons[i])
|
||||
n[0].info = n.info
|
||||
#throws(tracked.exc, n[0])
|
||||
addEffect(tracked, n[0], useLineInfo=false)
|
||||
for i in 0..<n.safeLen:
|
||||
track(tracked, n[i])
|
||||
createTypeBoundOps(tracked, n[0].typ, n.info)
|
||||
else:
|
||||
# A `raise` with no arguments means we're going to re-raise the exception
|
||||
|
|
@ -709,7 +707,7 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
addEffect(tracked, createRaise(tracked.graph, n))
|
||||
of nkCallKinds:
|
||||
# p's effects are ours too:
|
||||
var a = n.sons[0]
|
||||
var a = n[0]
|
||||
let op = a.typ
|
||||
if n.typ != nil:
|
||||
if tracked.owner.kind != skMacro and n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
|
|
@ -722,7 +720,7 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
# calling getAst(templateOrMacro()). Currently, templates and macros
|
||||
# are indistinguishable from normal procs (both have tyProc type) and
|
||||
# we can detect them only by checking for attached nkEffectList.
|
||||
if op != nil and op.kind == tyProc and op.n.sons[0].kind == nkEffectList:
|
||||
if op != nil and op.kind == tyProc and op.n[0].kind == nkEffectList:
|
||||
if a.kind == nkSym:
|
||||
if a.sym == tracked.owner: tracked.isRecursive = true
|
||||
# even for recursive calls we need to check the lock levels (!):
|
||||
|
|
@ -730,7 +728,7 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
if sfSideEffect in a.sym.flags: markSideEffect(tracked, a)
|
||||
else:
|
||||
mergeLockLevels(tracked, n, op.lockLevel)
|
||||
var effectList = op.n.sons[0]
|
||||
var effectList = op.n[0]
|
||||
if a.kind == nkSym and a.sym.kind == skMethod:
|
||||
propagateEffects(tracked, n, a.sym)
|
||||
elif isNoEffectList(effectList):
|
||||
|
|
@ -740,14 +738,14 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
assumeTheWorst(tracked, n, op)
|
||||
gcsafeAndSideeffectCheck()
|
||||
else:
|
||||
mergeEffects(tracked, effectList.sons[exceptionEffects], n)
|
||||
mergeTags(tracked, effectList.sons[tagEffects], n)
|
||||
mergeEffects(tracked, effectList[exceptionEffects], n)
|
||||
mergeTags(tracked, effectList[tagEffects], n)
|
||||
gcsafeAndSideeffectCheck()
|
||||
if a.kind != nkSym or a.sym.magic != mNBindSym:
|
||||
for i in 1 ..< n.len: trackOperand(tracked, n.sons[i], paramType(op, i), a)
|
||||
for i in 1..<n.len: trackOperand(tracked, n[i], paramType(op, i), a)
|
||||
if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:
|
||||
# may not look like an assignment, but it is:
|
||||
let arg = n.sons[1]
|
||||
let arg = n[1]
|
||||
initVarViaNew(tracked, arg)
|
||||
if arg.typ.len != 0 and {tfNeedsInit} * arg.typ.lastSon.flags != {}:
|
||||
if a.sym.magic == mNewSeq and n[2].kind in {nkCharLit..nkUInt64Lit} and
|
||||
|
|
@ -760,24 +758,24 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
if n[1].typ.len > 0:
|
||||
createTypeBoundOps(tracked, n[1].typ.lastSon, n.info)
|
||||
createTypeBoundOps(tracked, n[1].typ, n.info)
|
||||
for i in 0 ..< safeLen(n):
|
||||
track(tracked, n.sons[i])
|
||||
for i in 0..<n.safeLen:
|
||||
track(tracked, n[i])
|
||||
of nkDotExpr:
|
||||
guardDotAccess(tracked, n)
|
||||
for i in 0 ..< n.len: track(tracked, n.sons[i])
|
||||
for i in 0..<n.len: track(tracked, n[i])
|
||||
of nkCheckedFieldExpr:
|
||||
track(tracked, n.sons[0])
|
||||
track(tracked, n[0])
|
||||
if warnProveField in tracked.config.notes:
|
||||
checkFieldAccess(tracked.guards, n, tracked.config)
|
||||
of nkTryStmt: trackTryStmt(tracked, n)
|
||||
of nkPragma: trackPragmaStmt(tracked, n)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
track(tracked, n.sons[1])
|
||||
initVar(tracked, n.sons[0], volatileCheck=true)
|
||||
invalidateFacts(tracked.guards, n.sons[0])
|
||||
track(tracked, n.sons[0])
|
||||
addAsgnFact(tracked.guards, n.sons[0], n.sons[1])
|
||||
notNilCheck(tracked, n.sons[1], n.sons[0].typ)
|
||||
track(tracked, n[1])
|
||||
initVar(tracked, n[0], volatileCheck=true)
|
||||
invalidateFacts(tracked.guards, n[0])
|
||||
track(tracked, n[0])
|
||||
addAsgnFact(tracked.guards, n[0], n[1])
|
||||
notNilCheck(tracked, n[1], n[0].typ)
|
||||
when false: cstringCheck(tracked, n)
|
||||
if tracked.owner.kind != skMacro:
|
||||
createTypeBoundOps(tracked, n[0].typ, n.info)
|
||||
|
|
@ -788,17 +786,17 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
if tracked.owner.kind != skMacro:
|
||||
if child.kind == nkVarTuple:
|
||||
createTypeBoundOps(tracked, child[^1].typ, child.info)
|
||||
for i in 0..child.len-3:
|
||||
for i in 0..<child.len-2:
|
||||
createTypeBoundOps(tracked, child[i].typ, child.info)
|
||||
else:
|
||||
createTypeBoundOps(tracked, child[0].typ, child.info)
|
||||
if child.kind == nkIdentDefs and last.kind != nkEmpty:
|
||||
for i in 0 .. child.len-3:
|
||||
initVar(tracked, child.sons[i], volatileCheck=false)
|
||||
addAsgnFact(tracked.guards, child.sons[i], last)
|
||||
notNilCheck(tracked, last, child.sons[i].typ)
|
||||
for i in 0..<child.len-2:
|
||||
initVar(tracked, child[i], volatileCheck=false)
|
||||
addAsgnFact(tracked.guards, child[i], last)
|
||||
notNilCheck(tracked, last, child[i].typ)
|
||||
elif child.kind == nkVarTuple and last.kind != nkEmpty:
|
||||
for i in 0 .. child.len-2:
|
||||
for i in 0..<child.len-1:
|
||||
if child[i].kind == nkEmpty or
|
||||
child[i].kind == nkSym and child[i].sym.name.s == "_":
|
||||
continue
|
||||
|
|
@ -814,24 +812,24 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
track(tracked, last)
|
||||
of nkCaseStmt: trackCase(tracked, n)
|
||||
of nkWhen, nkIfStmt, nkIfExpr: trackIf(tracked, n)
|
||||
of nkBlockStmt, nkBlockExpr: trackBlock(tracked, n.sons[1])
|
||||
of nkBlockStmt, nkBlockExpr: trackBlock(tracked, n[1])
|
||||
of nkWhileStmt:
|
||||
track(tracked, n.sons[0])
|
||||
track(tracked, n[0])
|
||||
# 'while true' loop?
|
||||
if isTrue(n.sons[0]):
|
||||
trackBlock(tracked, n.sons[1])
|
||||
if isTrue(n[0]):
|
||||
trackBlock(tracked, n[1])
|
||||
else:
|
||||
# loop may never execute:
|
||||
let oldState = tracked.init.len
|
||||
let oldFacts = tracked.guards.s.len
|
||||
addFact(tracked.guards, n.sons[0])
|
||||
track(tracked, n.sons[1])
|
||||
addFact(tracked.guards, n[0])
|
||||
track(tracked, n[1])
|
||||
setLen(tracked.init, oldState)
|
||||
setLen(tracked.guards.s, oldFacts)
|
||||
of nkForStmt, nkParForStmt:
|
||||
# we are very conservative here and assume the loop is never executed:
|
||||
let oldState = tracked.init.len
|
||||
for i in 0 .. n.len-3:
|
||||
for i in 0..<n.len-2:
|
||||
let it = n[i]
|
||||
track(tracked, it)
|
||||
if tracked.owner.kind != skMacro:
|
||||
|
|
@ -840,8 +838,8 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
createTypeBoundOps(tracked, x.typ, x.info)
|
||||
else:
|
||||
createTypeBoundOps(tracked, it.typ, it.info)
|
||||
let iterCall = n[n.len-2]
|
||||
let loopBody = n[n.len-1]
|
||||
let iterCall = n[^2]
|
||||
let loopBody = n[^1]
|
||||
if tracked.owner.kind != skMacro and iterCall.safeLen > 1:
|
||||
# XXX this is a bit hacky:
|
||||
if iterCall[1].typ != nil and iterCall[1].typ.skipTypes(abstractVar).kind notin {tyVarargs, tyOpenArray}:
|
||||
|
|
@ -850,26 +848,26 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
track(tracked, loopBody)
|
||||
setLen(tracked.init, oldState)
|
||||
of nkObjConstr:
|
||||
when false: track(tracked, n.sons[0])
|
||||
when false: track(tracked, n[0])
|
||||
let oldFacts = tracked.guards.s.len
|
||||
for i in 1 ..< n.len:
|
||||
let x = n.sons[i]
|
||||
for i in 1..<n.len:
|
||||
let x = n[i]
|
||||
track(tracked, x)
|
||||
if x.sons[0].kind == nkSym and sfDiscriminant in x.sons[0].sym.flags:
|
||||
if x[0].kind == nkSym and sfDiscriminant in x[0].sym.flags:
|
||||
addDiscriminantFact(tracked.guards, x)
|
||||
setLen(tracked.guards.s, oldFacts)
|
||||
if tracked.owner.kind != skMacro:
|
||||
createTypeBoundOps(tracked, n.typ, n.info)
|
||||
of nkPragmaBlock:
|
||||
let pragmaList = n.sons[0]
|
||||
let pragmaList = n[0]
|
||||
let oldLocked = tracked.locked.len
|
||||
let oldLockLevel = tracked.currLockLevel
|
||||
var enforcedGcSafety = false
|
||||
var enforceNoSideEffects = false
|
||||
for i in 0 ..< pragmaList.len:
|
||||
let pragma = whichPragma(pragmaList.sons[i])
|
||||
for i in 0..<pragmaList.len:
|
||||
let pragma = whichPragma(pragmaList[i])
|
||||
if pragma == wLocks:
|
||||
lockLocations(tracked, pragmaList.sons[i])
|
||||
lockLocations(tracked, pragmaList[i])
|
||||
elif pragma == wGcSafe:
|
||||
enforcedGcSafety = true
|
||||
elif pragma == wNoSideEffect:
|
||||
|
|
@ -885,15 +883,15 @@ proc track(tracked: PEffects, n: PNode) =
|
|||
nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef:
|
||||
discard
|
||||
of nkCast, nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
if n.len == 2: track(tracked, n.sons[1])
|
||||
if n.len == 2: track(tracked, n[1])
|
||||
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
|
||||
if n.len == 1: track(tracked, n.sons[0])
|
||||
if n.len == 1: track(tracked, n[0])
|
||||
of nkBracket:
|
||||
for i in 0 ..< safeLen(n): track(tracked, n.sons[i])
|
||||
for i in 0..<n.safeLen: track(tracked, n[i])
|
||||
if tracked.owner.kind != skMacro:
|
||||
createTypeBoundOps(tracked, n.typ, n.info)
|
||||
else:
|
||||
for i in 0 ..< safeLen(n): track(tracked, n.sons[i])
|
||||
for i in 0..<n.safeLen: track(tracked, n[i])
|
||||
|
||||
proc subtypeRelation(g: ModuleGraph; spec, real: PNode): bool =
|
||||
result = safeInheritanceDiff(g.excType(real), spec.typ) <= 0
|
||||
|
|
@ -905,7 +903,7 @@ proc checkRaisesSpec(g: ModuleGraph; spec, real: PNode, msg: string, hints: bool
|
|||
var used = initIntSet()
|
||||
for r in items(real):
|
||||
block search:
|
||||
for s in 0 ..< spec.len:
|
||||
for s in 0..<spec.len:
|
||||
if effectPredicate(g, spec[s], r):
|
||||
used.incl(s)
|
||||
break search
|
||||
|
|
@ -915,23 +913,23 @@ proc checkRaisesSpec(g: ModuleGraph; spec, real: PNode, msg: string, hints: bool
|
|||
popInfoContext(g.config)
|
||||
# hint about unnecessarily listed exception types:
|
||||
if hints:
|
||||
for s in 0 ..< spec.len:
|
||||
for s in 0..<spec.len:
|
||||
if not used.contains(s):
|
||||
message(g.config, spec[s].info, hintXDeclaredButNotUsed, renderTree(spec[s]))
|
||||
|
||||
proc checkMethodEffects*(g: ModuleGraph; disp, branch: PSym) =
|
||||
## checks for consistent effects for multi methods.
|
||||
let actual = branch.typ.n.sons[0]
|
||||
let actual = branch.typ.n[0]
|
||||
if actual.len != effectListLen: return
|
||||
|
||||
let p = disp.ast.sons[pragmasPos]
|
||||
let p = disp.ast[pragmasPos]
|
||||
let raisesSpec = effectSpec(p, wRaises)
|
||||
if not isNil(raisesSpec):
|
||||
checkRaisesSpec(g, raisesSpec, actual.sons[exceptionEffects],
|
||||
checkRaisesSpec(g, raisesSpec, actual[exceptionEffects],
|
||||
"can raise an unlisted exception: ", hints=off, subtypeRelation)
|
||||
let tagsSpec = effectSpec(p, wTags)
|
||||
if not isNil(tagsSpec):
|
||||
checkRaisesSpec(g, tagsSpec, actual.sons[tagEffects],
|
||||
checkRaisesSpec(g, tagsSpec, actual[tagEffects],
|
||||
"can have an unlisted effect: ", hints=off, subtypeRelation)
|
||||
if sfThread in disp.flags and notGcSafe(branch.typ):
|
||||
localError(g.config, branch.info, "base method is GC-safe, but '$1' is not" %
|
||||
|
|
@ -963,14 +961,14 @@ proc setEffectsForProcType*(g: ModuleGraph; t: PType, n: PNode) =
|
|||
|
||||
proc initEffects(g: ModuleGraph; effects: PNode; s: PSym; t: var TEffects; c: PContext) =
|
||||
newSeq(effects.sons, effectListLen)
|
||||
effects.sons[exceptionEffects] = newNodeI(nkArgList, s.info)
|
||||
effects.sons[tagEffects] = newNodeI(nkArgList, s.info)
|
||||
effects.sons[usesEffects] = g.emptyNode
|
||||
effects.sons[writeEffects] = g.emptyNode
|
||||
effects.sons[pragmasEffects] = g.emptyNode
|
||||
effects[exceptionEffects] = newNodeI(nkArgList, s.info)
|
||||
effects[tagEffects] = newNodeI(nkArgList, s.info)
|
||||
effects[usesEffects] = g.emptyNode
|
||||
effects[writeEffects] = g.emptyNode
|
||||
effects[pragmasEffects] = g.emptyNode
|
||||
|
||||
t.exc = effects.sons[exceptionEffects]
|
||||
t.tags = effects.sons[tagEffects]
|
||||
t.exc = effects[exceptionEffects]
|
||||
t.tags = effects[tagEffects]
|
||||
t.owner = s
|
||||
t.ownerModule = s.getModule
|
||||
t.init = @[]
|
||||
|
|
@ -983,7 +981,7 @@ proc initEffects(g: ModuleGraph; effects: PNode; s: PSym; t: var TEffects; c: PC
|
|||
|
||||
proc trackProc*(c: PContext; s: PSym, body: PNode) =
|
||||
let g = c.graph
|
||||
var effects = s.typ.n.sons[0]
|
||||
var effects = s.typ.n[0]
|
||||
if effects.kind != nkEffectList: return
|
||||
# effects already computed?
|
||||
if sfForward in s.flags: return
|
||||
|
|
@ -995,32 +993,32 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
|
|||
|
||||
if s.kind != skMacro:
|
||||
let params = s.typ.n
|
||||
for i in 1 ..< params.len:
|
||||
for i in 1..<params.len:
|
||||
let param = params[i].sym
|
||||
if isSinkTypeForParam(param.typ):
|
||||
createTypeBoundOps(t.graph, t.c, param.typ, param.info)
|
||||
|
||||
if not isEmptyType(s.typ.sons[0]) and
|
||||
({tfNeedsInit, tfNotNil} * s.typ.sons[0].flags != {} or
|
||||
s.typ.sons[0].skipTypes(abstractInst).kind == tyVar) and
|
||||
if not isEmptyType(s.typ[0]) and
|
||||
({tfNeedsInit, tfNotNil} * s.typ[0].flags != {} or
|
||||
s.typ[0].skipTypes(abstractInst).kind == tyVar) and
|
||||
s.kind in {skProc, skFunc, skConverter, skMethod}:
|
||||
var res = s.ast.sons[resultPos].sym # get result symbol
|
||||
var res = s.ast[resultPos].sym # get result symbol
|
||||
if res.id notin t.init:
|
||||
message(g.config, body.info, warnProveInit, "result")
|
||||
let p = s.ast.sons[pragmasPos]
|
||||
let p = s.ast[pragmasPos]
|
||||
let raisesSpec = effectSpec(p, wRaises)
|
||||
if not isNil(raisesSpec):
|
||||
checkRaisesSpec(g, raisesSpec, t.exc, "can raise an unlisted exception: ",
|
||||
hints=on, subtypeRelation)
|
||||
# after the check, use the formal spec:
|
||||
effects.sons[exceptionEffects] = raisesSpec
|
||||
effects[exceptionEffects] = raisesSpec
|
||||
|
||||
let tagsSpec = effectSpec(p, wTags)
|
||||
if not isNil(tagsSpec):
|
||||
checkRaisesSpec(g, tagsSpec, t.tags, "can have an unlisted effect: ",
|
||||
hints=off, subtypeRelation)
|
||||
# after the check, use the formal spec:
|
||||
effects.sons[tagEffects] = tagsSpec
|
||||
effects[tagEffects] = tagsSpec
|
||||
|
||||
if sfThread in s.flags and t.gcUnsafe:
|
||||
if optThreads in g.config.globalOptions and optThreadAnalysis in g.config.globalOptions:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue