From 9172d2687021039135a601871591ace506e28ff5 Mon Sep 17 00:00:00 2001 From: Araq Date: Thu, 13 Jun 2024 16:18:30 +0200 Subject: [PATCH] fixes #22479; WIP [backport] --- compiler/injectdestructors.nim | 12 ++++---- compiler/liftdestructors.nim | 52 ++++++++++++++++++---------------- compiler/sighashes.nim | 13 ++++++++- 3 files changed, 45 insertions(+), 32 deletions(-) diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 85d7a65d27..3433c58c4c 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -251,11 +251,11 @@ proc genOp(c: var Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode c.genOp(op, dest) proc genDestroy(c: var Con; dest: PNode): PNode = - let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink}) + let t = dest.typ.skipTypes({tyAlias, tySink}) result = c.genOp(t, attachedDestructor, dest, nil) proc canBeMoved(c: Con; t: PType): bool {.inline.} = - let t = t.skipTypes({tyGenericInst, tyAlias, tySink}) + let t = t.skipTypes({tyAlias, tySink}) if optOwnedRefs in c.graph.config.globalOptions: result = t.kind != tyRef and getAttachedOp(c.graph, t, attachedSink) != nil else: @@ -281,7 +281,7 @@ proc genSink(c: var Con; s: var Scope; dest, ri: PNode; flags: set[MoveOrCopyFla # optimize sink call into a bitwise memcopy result = newTree(nkFastAsgn, dest, ri) else: - let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink}) + let t = dest.typ.skipTypes({tyAlias, tySink}) if getAttachedOp(c.graph, t, attachedSink) != nil: result = c.genOp(t, attachedSink, dest, ri) result.add ri @@ -335,7 +335,7 @@ proc genMarkCyclic(c: var Con; result, dest: PNode) = result.add callCodegenProc(c.graph, "nimMarkCyclic", dest.info, xenv) proc genCopyNoCheck(c: var Con; dest, ri: PNode; a: TTypeAttachedOp): PNode = - let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink}) + let t = dest.typ.skipTypes({tyAlias, tySink}) result = c.genOp(t, a, dest, ri) assert ri.typ != nil @@ -391,7 +391,7 @@ It is best to factor out piece of object that needs custom destructor into separ result.add newTree(nkFastAsgn, le, tmp) proc genWasMoved(c: var Con, n: PNode): PNode = - let typ = n.typ.skipTypes({tyGenericInst, tyAlias, tySink}) + let typ = n.typ.skipTypes({tyAlias, tySink}) let op = getAttachedOp(c.graph, n.typ, attachedWasMoved) if op != nil: if sfError in op.flags: @@ -449,7 +449,7 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode = let nTyp = n.typ.skipTypes(tyUserTypeClasses) let tmp = c.getTemp(s, nTyp, n.info) if hasDestructor(c, nTyp): - let typ = nTyp.skipTypes({tyGenericInst, tyAlias, tySink}) + let typ = nTyp.skipTypes({tyAlias, tySink}) let op = getAttachedOp(c.graph, typ, attachedDup) if op != nil and tfHasOwned notin typ.flags: if sfError in op.flags: diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 0bbaf3b33e..192a914b01 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -38,7 +38,7 @@ template assignment*(t: PType): PSym = getAttachedOp(c.g, t, attachedAsgn) template dup*(t: PType): PSym = getAttachedOp(c.g, t, attachedDup) template asink*(t: PType): PSym = getAttachedOp(c.g, t, attachedSink) -proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) +proc fillBody(c: var TLiftCtx; orig: PType; body, x, y: PNode) proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo; idgen: IdGenerator; isDistinct = false): PSym @@ -363,7 +363,7 @@ proc instantiateGeneric(c: var TLiftCtx; op: PSym; t, typeInst: PType): PSym = "cannot generate destructor for generic type: " & typeToString(t)) result = nil -proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode; +proc considerAsgnOrSink(c: var TLiftCtx; orig, t: PType; body, x, y: PNode; field: var PSym): bool = if optSeqDestructors in c.g.config.globalOptions: var op = field @@ -403,7 +403,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode; onUse(c.info, op) # We also now do generic instantiations in the destructor lifting pass: if op.ast.isGenericRoutine: - op = instantiateGeneric(c, op, t, t.typeInst) + op = instantiateGeneric(c, op, t, orig) field = op #echo "trying to use ", op.ast #echo "for ", op.name.s, " " @@ -422,8 +422,8 @@ proc addDestructorCall(c: var TLiftCtx; orig: PType; body, x: PNode) = if op != nil and sfOverridden in op.flags: if op.ast.isGenericRoutine: # patch generic destructor: - op = instantiateGeneric(c, op, t, t.typeInst) - setAttachedOp(c.g, c.idgen.module, t, attachedDestructor, op) + op = instantiateGeneric(c, op, t, orig) + setAttachedOp(c.g, c.idgen.module, orig, attachedDestructor, op) if op == nil and (useNoGc(c, t) or requiresDestructor(c, t)): op = produceSym(c.g, c.c, t, attachedDestructor, c.info, c.idgen) @@ -438,7 +438,7 @@ proc addDestructorCall(c: var TLiftCtx; orig: PType; body, x: PNode) = internalError(c.g.config, c.info, "type-bound operator could not be resolved") -proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool = +proc considerUserDefinedOp(c: var TLiftCtx; orig, t: PType; body, x, y: PNode): bool = case c.kind of attachedDestructor: var op = t.destructor @@ -446,8 +446,8 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool = if op.ast.isGenericRoutine: # patch generic destructor: - op = instantiateGeneric(c, op, t, t.typeInst) - setAttachedOp(c.g, c.idgen.module, t, attachedDestructor, op) + op = instantiateGeneric(c, op, t, orig) + setAttachedOp(c.g, c.idgen.module, orig, attachedDestructor, op) #markUsed(c.g.config, c.info, op, c.g.usageSym) onUse(c.info, op) @@ -461,10 +461,10 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool = if op != nil and sfOverridden in op.flags: if op.ast.isGenericRoutine: # patch generic =trace: - op = instantiateGeneric(c, op, t, t.typeInst) + op = instantiateGeneric(c, op, t, orig) setAttachedOp(c.g, c.idgen.module, t, c.kind, op) - result = considerAsgnOrSink(c, t, body, x, y, op) + result = considerAsgnOrSink(c, orig, t, body, x, y, op) if op != nil: setAttachedOp(c.g, c.idgen.module, t, c.kind, op) @@ -484,7 +484,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool = if op.ast.isGenericRoutine: # patch generic destructor: - op = instantiateGeneric(c, op, t, t.typeInst) + op = instantiateGeneric(c, op, t, orig) setAttachedOp(c.g, c.idgen.module, t, attachedWasMoved, op) #markUsed(c.g.config, c.info, op, c.g.usageSym) @@ -500,7 +500,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool = if op.ast.isGenericRoutine: # patch generic destructor: - op = instantiateGeneric(c, op, t, t.typeInst) + op = instantiateGeneric(c, op, t, orig) setAttachedOp(c.g, c.idgen.module, t, attachedDup, op) #markUsed(c.g.config, c.info, op, c.g.usageSym) @@ -948,7 +948,8 @@ proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = of attachedTrace: discard of attachedWasMoved: body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x) -proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) = +proc fillBody(c: var TLiftCtx; orig: PType; body, x, y: PNode) = + let t = orig.skipTypes({tyGenericInst, tyAlias}) case t.kind of tyNone, tyEmpty, tyVoid: discard of tyPointer, tySet, tyBool, tyChar, tyEnum, tyInt..tyUInt64, tyCstring, @@ -994,7 +995,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) = elif optSeqDestructors in c.g.config.globalOptions: # note that tfHasAsgn is propagated so we need the check on # 'selectedGC' here to determine if we have the new runtime. - discard considerUserDefinedOp(c, t, body, x, y) + discard considerUserDefinedOp(c, orig, t, body, x, y) elif tfHasAsgn in t.flags: if c.kind in {attachedAsgn, attachedSink, attachedDeepCopy}: body.add newSeqCall(c, x, y) @@ -1005,11 +1006,11 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) = if useNoGc(c, t): useSeqOrStrOp(c, t, body, x, y) elif tfHasAsgn in t.flags: - discard considerUserDefinedOp(c, t, body, x, y) + discard considerUserDefinedOp(c, orig, t, body, x, y) else: defaultOp(c, t, body, x, y) of tyObject: - if not considerUserDefinedOp(c, t, body, x, y): + if not considerUserDefinedOp(c, orig, t, body, x, y): if t.sym != nil and sfImportc in t.sym.flags: case c.kind of {attachedAsgn, attachedSink, attachedDup}: @@ -1030,7 +1031,7 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) = else: fillBodyObjT(c, t, body, x, y) of tyDistinct: - if not considerUserDefinedOp(c, t, body, x, y): + if not considerUserDefinedOp(c, orig, t, body, x, y): fillBody(c, t.elementType, body, x, y) of tyTuple: fillBodyTup(c, t, body, x, y) @@ -1046,10 +1047,9 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) = tyTypeDesc, tyGenericInvocation, tyForward, tyStatic: #internalError(c.g.config, c.info, "assignment requested for type: " & typeToString(t)) discard - of tyOrdinal, tyRange, tyInferred, - tyGenericInst, tyAlias, tySink: + of tyOrdinal, tyRange, tyInferred, tySink: fillBody(c, skipModifier(t), body, x, y) - of tyConcept, tyIterable: raiseAssert "unreachable" + of tyConcept, tyIterable, tyAlias, tyGenericInst: raiseAssert "unreachable" proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; info: TLineInfo; @@ -1247,13 +1247,13 @@ proc patchBody(g: ModuleGraph; c: PContext; n: PNode; info: TLineInfo; idgen: Id n[0] = newSymNode(op) for x in n: patchBody(g, c, x, info, idgen) -proc inst(g: ModuleGraph; c: PContext; t: PType; kind: TTypeAttachedOp; idgen: IdGenerator; +proc inst(g: ModuleGraph; c: PContext; orig, t: PType; kind: TTypeAttachedOp; idgen: IdGenerator; info: TLineInfo) = let op = getAttachedOp(g, t, kind) if op != nil and op.ast != nil and op.ast.isGenericRoutine: if t.typeInst != nil: var a = TLiftCtx(info: info, g: g, kind: kind, c: c, idgen: idgen) - let opInst = instantiateGeneric(a, op, t, t.typeInst) + let opInst = instantiateGeneric(a, op, t, orig) if opInst.ast != nil: patchBody(g, c, opInst.ast, info, a.idgen) setAttachedOp(g, idgen.module, t, kind, opInst) @@ -1271,11 +1271,13 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf if orig == nil or {tfCheckedForDestructor, tfHasMeta} * orig.flags != {}: return incl orig.flags, tfCheckedForDestructor - let skipped = orig.skipTypes({tyGenericInst, tyAlias, tySink}) + let skipped = orig.skipTypes({tyAlias, tySink}) if isEmptyContainer(skipped) or skipped.kind == tyStatic: return let h = sighashes.hashType(skipped, g.config, {CoType, CoConsiderOwned, CoDistinct}) var canon = g.canonTypes.getOrDefault(h) + + #echo "NOW FOR ", typeToString(skipped), " ", canon == nil if canon == nil: g.canonTypes[h] = skipped canon = skipped @@ -1295,7 +1297,7 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf # bug #15122: We need to produce all prototypes before entering the # mind boggling recursion. Hacks like these imply we should rewrite # this module. - var generics: array[attachedWasMoved..attachedTrace, bool] = default(array[attachedWasMoved..attachedTrace, bool]) + var generics = default(array[attachedWasMoved..attachedTrace, bool]) for k in attachedWasMoved..lastAttached: generics[k] = getAttachedOp(g, canon, k) != nil if not generics[k]: @@ -1307,7 +1309,7 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf if not generics[k]: discard produceSym(g, c, canon, k, info, idgen) else: - inst(g, c, canon, k, idgen, info) + inst(g, c, canon, canon, k, idgen, info) if canon != orig: setAttachedOp(g, idgen.module, orig, k, getAttachedOp(g, canon, k)) diff --git a/compiler/sighashes.nim b/compiler/sighashes.nim index 1b75f6be6b..5c88df661f 100644 --- a/compiler/sighashes.nim +++ b/compiler/sighashes.nim @@ -97,6 +97,17 @@ proc hashTree(c: var MD5Context, n: PNode; flags: set[ConsiderFlag]; conf: Confi else: for i in 0..