mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 22:10:33 +00:00
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:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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}:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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: """
|
||||
|
||||
@@ -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"
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user