This commit is contained in:
Andreas Rumpf 2020-07-20 07:50:19 +02:00 • committed by GitHub
commit 71dd5f85b9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 194 additions and 6 deletions

View file

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

View file

@ -2209,7 +2209,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
of mCharToStr: genDollar(p, e, d, "#nimCharToStr($1)")
of mFloatToStr: genDollar(p, e, d, "#nimFloatToStr($1)")
of mCStrToStr: genDollar(p, e, d, "#cstrToNimstr($1)")
of mStrToStr, mUnown: expr(p, e[1], d)
of mStrToStr, mUnown, mIsolate: expr(p, e[1], d)
of mEnumToStr:
if optTinyRtti in p.config.globalOptions:
genEnumToStr(p, e, d)

View file

@ -0,0 +1,117 @@
#
#
# The Nim Compiler
# (c) Copyright 2020 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Implementation of the check that `recover` needs, see
## https://github.com/nim-lang/RFCs/issues/244 for more details.
import
ast, types, renderer, idents, intsets, options, msgs
proc canAlias(arg, ret: PType; marker: var IntSet): bool
proc canAliasN(arg: PType; n: PNode; marker: var IntSet): bool =
case n.kind
of nkRecList:
for i in 0..<n.len:
result = canAliasN(arg, n[i], marker)
if result: return
of nkRecCase:
assert(n[0].kind == nkSym)
result = canAliasN(arg, n[0], marker)
if result: return
for i in 1..<n.len:
case n[i].kind
of nkOfBranch, nkElse:
result = canAliasN(arg, lastSon(n[i]), marker)
if result: return
else: discard
of nkSym:
result = canAlias(arg, n.sym.typ, marker)
else: discard
proc canAlias(arg, ret: PType; marker: var IntSet): bool =
if containsOrIncl(marker, ret.id):
return false
if ret.kind in {tyPtr, tyPointer}:
# unsafe so we don't care:
return false
if compareTypes(arg, ret, dcEqIgnoreDistinct):
return true
case ret.kind
of tyObject:
if isFinal(ret):
result = canAliasN(arg, ret.n, marker)
if not result and ret.len > 0 and ret[0] != nil:
result = canAlias(arg, ret[0], marker)
else:
result = true
of tyTuple:
for i in 0..<ret.len:
result = canAlias(arg, ret[i], marker)
if result: break
of tyArray, tySequence, tyDistinct, tyGenericInst,
tyAlias, tyInferred, tySink, tyLent, tyOwned, tyRef:
result = canAlias(arg, ret.lastSon, marker)
of tyProc:
result = ret.callConv == ccClosure
else:
result = false
proc canAlias(arg, ret: PType): bool =
var marker = initIntSet()
result = canAlias(arg, ret, marker)
proc checkIsolate*(n: PNode): bool =
if types.containsTyRef(n.typ):
# XXX Maybe require that 'n.typ' is acyclic. This is not much
# worse than the already exisiting inheritance and closure restrictions.
case n.kind
of nkCharLit..nkNilLit:
result = true
of nkCallKinds:
if n[0].typ.flags * {tfGcSafe, tfNoSideEffect} == {}:
return false
for i in 1..<n.len:
if checkIsolate(n[i]):
discard "fine, it is isolated already"
else:
let argType = n[i].typ
if argType != nil and not isCompileTimeOnly(argType) and containsTyRef(argType):
if argType.canAlias(n.typ):
return false
result = true
of nkIfStmt, nkIfExpr:
for it in n:
result = checkIsolate(it.lastSon)
if not result: break
of nkCaseStmt, nkObjConstr:
for i in 1..<n.len:
result = checkIsolate(n[i].lastSon)
if not result: break
of nkBracket, nkTupleConstr, nkPar:
for it in n:
result = checkIsolate(it)
if not result: break
of nkHiddenStdConv, nkHiddenSubConv, nkCast, nkConv:
result = checkIsolate(n[1])
of nkObjUpConv, nkObjDownConv, nkDotExpr:
result = checkIsolate(n[0])
of nkStmtList, nkStmtListExpr:
if n.len > 0:
result = checkIsolate(n[^1])
else:
result = false
else:
# unanalysable expression:
result = false
else:
# no ref, no cry:
result = true

View file

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

View file

@ -16,7 +16,8 @@ import
procfind, lookups, pragmas, passes, semdata, semtypinst, sigmatch,
intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity,
lowerings, plugins/active, rod, lineinfos, strtabs, int128
lowerings, plugins/active, rod, lineinfos, strtabs, int128,
isolation_check
from modulegraphs import ModuleGraph, PPassContext, onUse, onDef, onDefResolveForward

View file

@ -558,6 +558,9 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
let constructed = result[1].typ.base
if constructed.requiresInit:
message(c.config, n.info, warnUnsafeDefault, typeToString(constructed))
of mIsolate:
if not checkIsolate(n[1]):
localError(c.config, n.info, "expression cannot be isolated: " & $n[1])
result = n
else:
result = n

View file

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