better effect inference

This commit is contained in:
Araq 2014-11-02 14:35:13 +01:00
commit c4d05ca130
2 changed files with 18 additions and 9 deletions

View file

@ -181,6 +181,10 @@ proc initVarViaNew(a: PEffects, n: PNode) =
# are initialized: # are initialized:
initVar(a, n) initVar(a, n)
proc warnAboutGcUnsafe(n: PNode) =
#assert false
message(n.info, warnGcUnsafe, renderTree(n))
proc useVar(a: PEffects, n: PNode) = proc useVar(a: PEffects, n: PNode) =
let s = n.sym let s = n.sym
if isLocalVar(a, s): if isLocalVar(a, s):
@ -195,7 +199,7 @@ proc useVar(a: PEffects, n: PNode) =
if s.guard != nil: guardGlobal(a, n, s.guard) if s.guard != nil: guardGlobal(a, n, s.guard)
if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem) and if (tfHasGCedMem in s.typ.flags or s.typ.isGCedMem) and
tfGcSafe notin s.typ.flags: tfGcSafe notin s.typ.flags:
if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
a.gcUnsafe = true a.gcUnsafe = true
type type
@ -431,7 +435,7 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) =
mergeTags(tracked, tagSpec, n) mergeTags(tracked, tagSpec, n)
if notGcSafe(s.typ) and sfImportc notin s.flags: if notGcSafe(s.typ) and sfImportc notin s.flags:
if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
tracked.gcUnsafe = true tracked.gcUnsafe = true
mergeLockLevels(tracked, n, s.getLockLevel) mergeLockLevels(tracked, n, s.getLockLevel)
@ -462,8 +466,13 @@ proc assumeTheWorst(tracked: PEffects; n: PNode; op: PType) =
# message(n.info, warnUser, "had to assume the worst here") # message(n.info, warnUser, "had to assume the worst here")
mergeLockLevels(tracked, n, lockLevel) mergeLockLevels(tracked, n, lockLevel)
proc isOwnedProcVar(n: PNode; owner: PSym): bool =
# XXX prove the soundness of this effect system rule
result = n.kind == nkSym and n.sym.kind == skParam and owner == n.sym.owner
proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) = proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
let op = skipConvAndClosure(n).typ let a = skipConvAndClosure(n)
let op = a.typ
if op != nil and op.kind == tyProc and n.kind != nkNilLit: if op != nil and op.kind == tyProc and n.kind != nkNilLit:
internalAssert op.n.sons[0].kind == nkEffectList internalAssert op.n.sons[0].kind == nkEffectList
var effectList = op.n.sons[0] var effectList = op.n.sons[0]
@ -475,18 +484,18 @@ proc trackOperand(tracked: PEffects, n: PNode, paramType: PType) =
# we have no explicit effects but it's a forward declaration and so it's # we have no explicit effects but it's a forward declaration and so it's
# stated there are no additional effects, so simply propagate them: # stated there are no additional effects, so simply propagate them:
propagateEffects(tracked, n, n.sym) propagateEffects(tracked, n, n.sym)
else: elif not isOwnedProcVar(a, tracked.owner):
# we have no explicit effects so assume the worst: # we have no explicit effects so assume the worst:
assumeTheWorst(tracked, n, op) assumeTheWorst(tracked, n, op)
# assume GcUnsafe unless in its type; 'forward' does not matter: # assume GcUnsafe unless in its type; 'forward' does not matter:
if notGcSafe(op): if notGcSafe(op) and not isOwnedProcVar(a, tracked.owner):
if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
tracked.gcUnsafe = true tracked.gcUnsafe = true
else: else:
mergeEffects(tracked, effectList.sons[exceptionEffects], n) mergeEffects(tracked, effectList.sons[exceptionEffects], n)
mergeTags(tracked, effectList.sons[tagEffects], n) mergeTags(tracked, effectList.sons[tagEffects], n)
if notGcSafe(op): if notGcSafe(op):
if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n)) if warnGcUnsafe in gNotes: warnAboutGcUnsafe(n)
tracked.gcUnsafe = true tracked.gcUnsafe = true
notNilCheck(tracked, n, paramType) notNilCheck(tracked, n, paramType)
@ -633,7 +642,7 @@ proc track(tracked: PEffects, n: PNode) =
if notGcSafe(op) and not importedFromC(a): if notGcSafe(op) and not importedFromC(a):
# and it's not a recursive call: # and it's not a recursive call:
if not (a.kind == nkSym and a.sym == tracked.owner): if not (a.kind == nkSym and a.sym == tracked.owner):
message(n.info, warnGcUnsafe, renderTree(n)) warnAboutGcUnsafe(n)
tracked.gcUnsafe = true tracked.gcUnsafe = true
for i in 1 .. <len(n): trackOperand(tracked, n.sons[i], paramType(op, i)) for i in 1 .. <len(n): trackOperand(tracked, n.sons[i], paramType(op, i))
if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}: if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:

View file

@ -1,5 +1,5 @@
discard """ discard """
line: 2169 line: 2170
file: "system.nim" file: "system.nim"
errormsg: "can raise an unlisted exception: ref IOError" errormsg: "can raise an unlisted exception: ref IOError"
""" """