mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-07 13:33:22 +00:00
* ORC: track escaping parameters properly * fixes #18240
This commit is contained in:
@@ -77,6 +77,7 @@ type
|
||||
config: ConfigRef
|
||||
graph: ModuleGraph
|
||||
c: PContext
|
||||
escapingParams: IntSet
|
||||
PEffects = var TEffects
|
||||
|
||||
proc `<`(a, b: TLockLevel): bool {.borrow.}
|
||||
@@ -900,6 +901,25 @@ proc castBlock(tracked: PEffects, pragma: PNode, bc: var PragmaBlockContext) =
|
||||
localError(tracked.config, pragma.info,
|
||||
"invalid pragma block: " & $pragma)
|
||||
|
||||
proc trackInnerProc(tracked: PEffects, n: PNode) =
|
||||
case n.kind
|
||||
of nkSym:
|
||||
let s = n.sym
|
||||
if s.kind == skParam and s.owner == tracked.owner:
|
||||
tracked.escapingParams.incl s.id
|
||||
of nkNone..pred(nkSym), succ(nkSym)..nkNilLit:
|
||||
discard
|
||||
of nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef, nkLambda, nkFuncDef, nkDo:
|
||||
if n[0].kind == nkSym and n[0].sym.ast != nil:
|
||||
trackInnerProc(tracked, getBody(tracked.graph, n[0].sym))
|
||||
of nkTypeSection, nkMacroDef, nkTemplateDef, nkError,
|
||||
nkConstSection, nkConstDef, nkIncludeStmt, nkImportStmt,
|
||||
nkExportStmt, nkPragma, nkCommentStmt, nkBreakState,
|
||||
nkTypeOfExpr, nkMixinStmt, nkBindStmt:
|
||||
discard
|
||||
else:
|
||||
for ch in n: trackInnerProc(tracked, ch)
|
||||
|
||||
proc track(tracked: PEffects, n: PNode) =
|
||||
case n.kind
|
||||
of nkSym:
|
||||
@@ -1095,8 +1115,10 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
track(tracked, n.lastSon)
|
||||
unapplyBlockContext(tracked, bc)
|
||||
|
||||
of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
|
||||
nkMacroDef, nkTemplateDef, nkLambda, nkDo, nkFuncDef:
|
||||
of nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef, nkLambda, nkFuncDef, nkDo:
|
||||
if n[0].kind == nkSym and n[0].sym.ast != nil:
|
||||
trackInnerProc(tracked, getBody(tracked.graph, n[0].sym))
|
||||
of nkTypeSection, nkMacroDef, nkTemplateDef:
|
||||
discard
|
||||
of nkCast:
|
||||
if n.len == 2:
|
||||
@@ -1259,15 +1281,6 @@ proc hasRealBody(s: PSym): bool =
|
||||
## which is not a real implementation, refs #14314
|
||||
result = {sfForward, sfImportc} * s.flags == {}
|
||||
|
||||
proc maybeWrappedInClosure(tracked: PEffects; t: PType): bool {.inline.} =
|
||||
## The spec does say when to produce destructors. However, the spec
|
||||
## was written in mind with the idea that "lambda lifting" already
|
||||
## happened. Not true in our implementation, so we need to workaround
|
||||
## here:
|
||||
result = tracked.isInnerProc and
|
||||
sfSystemModule notin tracked.c.module.flags and
|
||||
tfCheckedForDestructor notin t.flags and containsGarbageCollectedRef(t)
|
||||
|
||||
proc trackProc*(c: PContext; s: PSym, body: PNode) =
|
||||
let g = c.graph
|
||||
var effects = s.typ.n[0]
|
||||
@@ -1287,7 +1300,7 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
|
||||
let typ = param.typ
|
||||
if isSinkTypeForParam(typ) or
|
||||
(t.config.selectedGC in {gcArc, gcOrc} and
|
||||
(isClosure(typ.skipTypes(abstractInst)) or maybeWrappedInClosure(t, typ))):
|
||||
(isClosure(typ.skipTypes(abstractInst)) or param.id in t.escapingParams)):
|
||||
createTypeBoundOps(t, typ, param.info)
|
||||
when false:
|
||||
if typ.kind == tyOut and param.id notin t.init:
|
||||
|
||||
@@ -32,3 +32,35 @@ when true:
|
||||
waitFor hello(Flags())
|
||||
echo "success"
|
||||
|
||||
# bug #18240
|
||||
import tables
|
||||
|
||||
type
|
||||
TopicHandler* = proc(topic: string,
|
||||
data: seq[byte]): Future[void] {.gcsafe, raises: [Defect].}
|
||||
|
||||
PeerID* = object
|
||||
data*: seq[byte]
|
||||
|
||||
PeerInfo* = ref object of RootObj
|
||||
peerId*: PeerID
|
||||
|
||||
Connection* = ref object of RootObj
|
||||
peerInfo*: PeerInfo
|
||||
|
||||
PubSubPeer* = ref object of RootObj
|
||||
codec*: string
|
||||
|
||||
PubSub* = ref object of RootObj
|
||||
topics*: Table[string, seq[TopicHandler]]
|
||||
peers*: Table[PeerID, PubSubPeer]
|
||||
|
||||
proc getOrCreatePeer*(myParam: PubSub, peerId: PeerID, protos: seq[string]): PubSubPeer =
|
||||
myParam.peers.withValue(peerId, peer):
|
||||
return peer[]
|
||||
|
||||
method handleConn*(myParam: PubSub,
|
||||
conn: Connection,
|
||||
proto: string) {.base, async.} =
|
||||
myParam.peers.withValue(conn.peerInfo.peerId, peer):
|
||||
let peerB = peer[]
|
||||
|
||||
Reference in New Issue
Block a user