correct effect tracking for .borrowed procs [backport] (#18882)

* correct effect tracking for .borrowed procs [backport]

* progress

* fix error message in a test

* correctly fix it

Co-authored-by: narimiran <narimiran@disroot.org>
This commit is contained in:
Andreas Rumpf
2021-09-23 16:47:24 +02:00
committed by GitHub
parent 7d2a4c0880
commit 90a2b5afd8
8 changed files with 20 additions and 12 deletions

View File

@@ -673,7 +673,7 @@ type
mSwap, mIsNil, mArrToSeq,
mNewString, mNewStringOfCap, mParseBiggestFloat,
mMove, mWasMoved, mDestroy, mTrace,
mDefault, mUnown, mIsolate, mAccessEnv, mReset,
mDefault, mUnown, mFinished, mIsolate, mAccessEnv, mReset,
mArray, mOpenArray, mRange, mSet, mSeq, mVarargs,
mRef, mPtr, mVar, mDistinct, mVoid, mTuple,
mOrdinal, mIterableType,

View File

@@ -2335,7 +2335,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
genDollar(p, e, d, "#nimFloatToStr($1)")
of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
of mStrToStr, mUnown: expr(p, e[1], d)
of mIsolate: genCall(p, e, d)
of mIsolate, mFinished: genCall(p, e, d)
of mEnumToStr:
if optTinyRtti in p.config.globalOptions:
genEnumToStr(p, e, d)
@@ -2929,7 +2929,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
if n[genericParamsPos].kind == nkEmpty:
var prc = n[namePos].sym
if useAliveDataFromDce in p.module.flags:
if p.module.alive.contains(prc.itemId.item) and prc.magic in {mNone, mIsolate}:
if p.module.alive.contains(prc.itemId.item) and prc.magic in {mNone, mIsolate, mFinished}:
genProc(p.module, prc)
elif prc.skipGenericOwner.kind == skModule and sfCompileTime notin prc.flags:
if ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or

View File

@@ -657,7 +657,7 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mIntToStr: applyFormat("cstrToNimstr(($1) + \"\")", "cstrToNimstr(($1) + \"\")")
of mInt64ToStr: applyFormat("cstrToNimstr(($1) + \"\")", "cstrToNimstr(($1) + \"\")")
of mCStrToStr: applyFormat("cstrToNimstr($1)", "cstrToNimstr($1)")
of mStrToStr, mUnown, mIsolate: applyFormat("$1", "$1")
of mStrToStr, mUnown, mIsolate, mFinished: applyFormat("$1", "$1")
else:
assert false, $op

View File

@@ -245,9 +245,14 @@ proc listGcUnsafety(s: PSym; onlyWarning: bool; cycleCheck: var IntSet; conf: Co
let msgKind = if onlyWarning: warnGcUnsafe2 else: errGenerated
case u.kind
of skLet, skVar:
message(conf, s.info, msgKind,
("'$#' is not GC-safe as it accesses '$#'" &
" which is a global using GC'ed memory") % [s.name.s, u.name.s])
if u.typ.skipTypes(abstractInst).kind == tyProc:
message(conf, s.info, msgKind,
"'$#' is not GC-safe as it calls '$#'" %
[s.name.s, u.name.s])
else:
message(conf, s.info, msgKind,
("'$#' is not GC-safe as it accesses '$#'" &
" which is a global using GC'ed memory") % [s.name.s, u.name.s])
of routineKinds:
# recursive call *always* produces only a warning so the full error
# message is printed:
@@ -850,7 +855,7 @@ proc trackCall(tracked: PEffects; n: PNode) =
mergeRaises(tracked, effectList[exceptionEffects], n)
mergeTags(tracked, effectList[tagEffects], n)
gcsafeAndSideeffectCheck()
if a.kind != nkSym or a.sym.magic != mNBindSym:
if a.kind != nkSym or a.sym.magic notin {mNBindSym, mFinished}:
for i in 1..<n.len:
trackOperandForIndirectCall(tracked, n[i], op, i, a)
if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}:

View File

@@ -1474,6 +1474,9 @@ proc semBorrow(c: PContext, n: PNode, s: PSym) =
# Carry over the original symbol magic, this is necessary in order to ensure
# the semantic pass is correct
s.magic = b.magic
if b.typ != nil and b.typ.len > 0:
s.typ.n[0] = b.typ.n[0]
s.typ.flags = b.typ.flags
else:
localError(c.config, n.info, errNoSymbolToBorrowFromFound)
@@ -1954,7 +1957,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if not hasProto:
implicitPragmas(c, s, n.info, validPragmas)
if n[pragmasPos].kind != nkEmpty:
if n[pragmasPos].kind != nkEmpty and sfBorrow notin s.flags:
setEffectsForProcType(c.graph, s.typ, n[pragmasPos], s)
s.typ.flags.incl tfEffectSystemWorkaround

View File

@@ -1029,7 +1029,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
c.genAsgnPatch(n[1], d)
c.freeTemp(d)
of mOrd, mChr, mArrToSeq, mUnown: c.gen(n[1], dest)
of mIsolate:
of mIsolate, mFinished:
genCall(c, n, dest)
of mNew, mNewFinalize:
unused(c, n, dest)

View File

@@ -2453,7 +2453,7 @@ when notJSnotNims:
else:
{.error: "Only closure function and iterator are allowed!".}
proc finished*[T: proc](x: T): bool {.noSideEffect, inline.} =
proc finished*[T: proc](x: T): bool {.noSideEffect, inline, magic: "Finished".} =
## It can be used to determine if a first class iterator has finished.
when T is "iterator":
{.emit: """

View File

@@ -1,5 +1,5 @@
discard """
errormsg: "'myproc' is not GC-safe as it accesses 'global_proc' which is a global using GC'ed memory"
errormsg: "'myproc' is not GC-safe as it calls 'global_proc'"
line: 12
cmd: "nim $target --hints:on --threads:on $options $file"
"""