fixes #20139; hash types based on its path relative to its package path (#21274) [backport:1.6]

* fixes #20139; hash types based on its path relative its project

* add a test case

* fixes procs

* better implementation and test case

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
This commit is contained in:
ringabout
2023-03-02 16:16:28 +08:00
committed by GitHub
parent 50baf21eac
commit 38d299dfc0
13 changed files with 143 additions and 74 deletions

View File

@@ -1704,7 +1704,7 @@ proc genNewFinalize(p: BProc, e: PNode) =
proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo; result: var Rope) =
if optTinyRtti in p.config.globalOptions:
let token = $genDisplayElem(MD5Digest(hashType(dest)))
let token = $genDisplayElem(MD5Digest(hashType(dest, p.config)))
appcg(p.module, result, "#isObjDisplayCheck($#.m_type, $#, $#)", [a, getObjDepth(dest), token])
else:
# unfortunately 'genTypeInfoV1' sets tfObjHasKids as a side effect, so we
@@ -2779,7 +2779,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
rdMType(p, a, nilCheck, r)
if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(dest)
let token = $genDisplayElem(MD5Digest(hashType(dest)))
let token = $genDisplayElem(MD5Digest(hashType(dest, p.config)))
if nilCheck != "":
linefmt(p, cpsStmts, "if ($1 && !#isObjDisplayCheck($2, $3, $4)){ #raiseObjectConversionError(); ",
[nilCheck, r, checkFor, token])

View File

@@ -1081,7 +1081,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(typeNode.typ)
appcg(p.module, orExpr, "#isObjDisplayCheck(#nimBorrowCurrentException()->$1, $2, $3)", [memberName, checkFor, $genDisplayElem(MD5Digest(hashType(typeNode.typ)))])
appcg(p.module, orExpr, "#isObjDisplayCheck(#nimBorrowCurrentException()->$1, $2, $3)", [memberName, checkFor, $genDisplayElem(MD5Digest(hashType(typeNode.typ, p.config)))])
else:
let checkFor = genTypeInfoV1(p.module, typeNode.typ, typeNode.info)
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
@@ -1300,7 +1300,7 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(t[i][j].typ)
appcg(p.module, orExpr, "#isObjDisplayCheck(#nimBorrowCurrentException()->$1, $2, $3)", [memberName, checkFor, $genDisplayElem(MD5Digest(hashType(t[i][j].typ)))])
appcg(p.module, orExpr, "#isObjDisplayCheck(#nimBorrowCurrentException()->$1, $2, $3)", [memberName, checkFor, $genDisplayElem(MD5Digest(hashType(t[i][j].typ, p.config)))])
else:
let checkFor = genTypeInfoV1(p.module, t[i][j].typ, t[i][j].info)
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])
@@ -1445,7 +1445,7 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(t[i][j].typ)
appcg(p.module, orExpr, "#isObjDisplayCheck(#nimBorrowCurrentException()->$1, $2, $3)", [memberName, checkFor, $genDisplayElem(MD5Digest(hashType(t[i][j].typ)))])
appcg(p.module, orExpr, "#isObjDisplayCheck(#nimBorrowCurrentException()->$1, $2, $3)", [memberName, checkFor, $genDisplayElem(MD5Digest(hashType(t[i][j].typ, p.config)))])
else:
let checkFor = genTypeInfoV1(p.module, t[i][j].typ, t[i][j].info)
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor])

View File

@@ -43,14 +43,14 @@ proc fillBackendName(m: BModule; s: PSym) =
result.add rope s.itemId.item
if m.hcrOn:
result.add "_"
result.add(idOrSig(s, m.module.name.s.mangle, m.sigConflicts))
result.add(idOrSig(s, m.module.name.s.mangle, m.sigConflicts, m.config))
s.loc.r = result
writeMangledName(m.ndi, s, m.config)
proc fillParamName(m: BModule; s: PSym) =
if s.loc.r == "":
var res = s.name.s.mangle
res.add idOrSig(s, res, m.sigConflicts)
res.add idOrSig(s, res, m.sigConflicts, m.config)
# Take into account if HCR is on because of the following scenario:
# if a module gets imported and it has some more importc symbols in it,
# some param names might receive the "_0" suffix to distinguish from what
@@ -302,7 +302,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
else: result = ""
if result != "" and typ.isImportedType():
let sig = hashType typ
let sig = hashType(typ, m.config)
if cacheGetType(m.typeCache, sig) == "":
m.typeCache[sig] = result
@@ -362,10 +362,10 @@ proc getTypeDescWeak(m: BModule; t: PType; check: var IntSet; kind: TSymKind): R
if isImportedCppType(etB) and t.kind == tyGenericInst:
result = getTypeDescAux(m, t, check, kind)
else:
result = getTypeForward(m, t, hashType(t))
result = getTypeForward(m, t, hashType(t, m.config))
pushType(m, t)
of tySequence:
let sig = hashType(t)
let sig = hashType(t, m.config)
if optSeqDestructors in m.config.globalOptions:
if skipTypes(etB[0], typedescInst).kind == tyEmpty:
internalError(m.config, "cannot map the empty seq type to a C type")
@@ -398,7 +398,7 @@ proc getSeqPayloadType(m: BModule; t: PType): Rope =
#result = getTypeForward(m, t, hashType(t)) & "_Content"
proc seqV2ContentType(m: BModule; t: PType; check: var IntSet) =
let sig = hashType(t)
let sig = hashType(t, m.config)
let result = cacheGetType(m.typeCache, sig)
if result == "":
discard getTypeDescAux(m, t, check, skVar)
@@ -664,7 +664,7 @@ proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
else: result.elemType
proc getOpenArrayDesc(m: BModule, t: PType, check: var IntSet; kind: TSymKind): Rope =
let sig = hashType(t)
let sig = hashType(t, m.config)
if kind == skParam:
result = getTypeDescWeak(m, t[0], check, kind) & "*"
else:
@@ -688,7 +688,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
# C type generation into an analysis and a code generation phase somehow.
if t.sym != nil: useHeader(m, t.sym)
if t != origTyp and origTyp.sym != nil: useHeader(m, origTyp.sym)
let sig = hashType(origTyp)
let sig = hashType(origTyp, m.config)
defer: # defer is the simplest in this case
if isImportedType(t) and not m.typeABICache.containsOrIncl(sig):
@@ -717,7 +717,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
result = getTypeDescAux(m, et, check, kind) & star
else:
# no restriction! We have a forward declaration for structs
let name = getTypeForward(m, et, hashType et)
let name = getTypeForward(m, et, hashType(et, m.config))
result = name & star
m.typeCache[sig] = result
of tySequence:
@@ -726,7 +726,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
m.typeCache[sig] = result
else:
# no restriction! We have a forward declaration for structs
let name = getTypeForward(m, et, hashType et)
let name = getTypeForward(m, et, hashType(et, m.config))
result = name & seqStar(m) & star
m.typeCache[sig] = result
pushType(m, et)
@@ -893,7 +893,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
# Don't use the imported name as it may be scoped: 'Foo::SomeKind'
result = rope("tySet_")
t.lastSon.typeName(result)
result.add $t.lastSon.hashType
result.add $t.lastSon.hashType(m.config)
m.typeCache[sig] = result
if not isImportedType(t):
let s = int(getSize(m.config, t))
@@ -1066,7 +1066,7 @@ proc discriminatorTableName(m: BModule, objtype: PType, d: PSym): Rope =
objtype = objtype[0].skipTypes(abstractPtrs)
if objtype.sym == nil:
internalError(m.config, d.info, "anonymous obj with discriminator")
result = "NimDT_$1_$2" % [rope($hashType(objtype)), rope(d.name.s.mangle)]
result = "NimDT_$1_$2" % [rope($hashType(objtype, m.config)), rope(d.name.s.mangle)]
proc rope(arg: Int128): Rope = rope($arg)
@@ -1285,7 +1285,7 @@ proc genTypeInfo2Name(m: BModule; t: PType): Rope =
result.add m.name.s & "."
result.add it.sym.name.s
else:
result = $hashType(it)
result = $hashType(it, m.config)
result = makeCString(result)
proc isTrivialProc(g: ModuleGraph; s: PSym): bool {.inline.} = getBody(g, s).len == 0
@@ -1329,14 +1329,14 @@ proc genDisplayElem(d: MD5Digest): uint32 =
result += uint32(d[i])
result = result shl 8
proc genDisplay(t: PType, depth: int): Rope =
proc genDisplay(m: BModule, t: PType, depth: int): Rope =
result = Rope"{"
var x = t
var seqs = newSeq[string](depth+1)
var i = 0
while x != nil:
x = skipTypes(x, skipPtrs)
seqs[i] = $genDisplayElem(MD5Digest(hashType(x)))
seqs[i] = $genDisplayElem(MD5Digest(hashType(x, m.config)))
x = x[0]
inc i
@@ -1376,7 +1376,7 @@ proc genTypeInfoV2OldImpl(m: BModule; t, origType: PType, name: Rope; info: TLin
[name, getTypeDesc(m, t), rope(objDepth), rope(flags)])
if objDepth >= 0:
let objDisplay = genDisplay(t, objDepth)
let objDisplay = genDisplay(m, t, objDepth)
let objDisplayStore = getTempName(m)
m.s[cfsVars].addf("static $1 $2[$3] = $4;$n", [getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), skVar), objDisplayStore, rope(objDepth+1), objDisplay])
addf(typeEntry, "$1.display = $2;$n", [name, rope(objDisplayStore)])
@@ -1408,7 +1408,7 @@ proc genTypeInfoV2Impl(m: BModule; t, origType: PType, name: Rope; info: TLineIn
[getTypeDesc(m, t), rope(objDepth)])
if objDepth >= 0:
let objDisplay = genDisplay(t, objDepth)
let objDisplay = genDisplay(m, t, objDepth)
let objDisplayStore = getTempName(m)
m.s[cfsVars].addf("static NIM_CONST $1 $2[$3] = $4;$n", [getTypeDesc(m, getSysType(m.g.graph, unknownLineInfo, tyUInt32), skVar), objDisplayStore, rope(objDepth+1), objDisplay])
addf(typeEntry, ", .display = $1", [rope(objDisplayStore)])
@@ -1435,7 +1435,7 @@ proc genTypeInfoV2(m: BModule, t: PType; info: TLineInfo): Rope =
let prefixTI = if m.hcrOn: "(" else: "(&"
let sig = hashType(origType)
let sig = hashType(origType, m.config)
result = m.typeInfoMarkerV2.getOrDefault(sig)
if result != "":
return prefixTI.rope & result & ")".rope
@@ -1509,7 +1509,7 @@ proc genTypeInfoV1(m: BModule, t: PType; info: TLineInfo): Rope =
let prefixTI = if m.hcrOn: "(" else: "(&"
let sig = hashType(origType)
let sig = hashType(origType, m.config)
result = m.typeInfoMarker.getOrDefault(sig)
if result != "":
return prefixTI.rope & result & ")".rope

View File

@@ -1630,7 +1630,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
hcrModuleMeta.addf("\t\"\"};$n", [])
hcrModuleMeta.addf("$nN_LIB_EXPORT N_NIMCALL(void**, HcrGetImportedModules)() { return (void**)hcr_module_list; }$n", [])
hcrModuleMeta.addf("$nN_LIB_EXPORT N_NIMCALL(char*, HcrGetSigHash)() { return \"$1\"; }$n$n",
[($sigHash(m.module)).rope])
[($sigHash(m.module, m.config)).rope])
if sfMainModule in m.module.flags:
g.mainModProcs.add(hcrModuleMeta)
g.mainModProcs.addf("static void* hcr_handle;$N", [])

View File

@@ -217,7 +217,7 @@ proc genOp(c: var Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode
var op = getAttachedOp(c.graph, t, kind)
if op == nil or op.ast.isGenericRoutine:
# give up and find the canonical type instead:
let h = sighashes.hashType(t, {CoType, CoConsiderOwned, CoDistinct})
let h = sighashes.hashType(t, c.graph.config, {CoType, CoConsiderOwned, CoDistinct})
let canon = c.graph.canonTypes.getOrDefault(h)
if canon != nil:
op = getAttachedOp(c.graph, canon, kind)

View File

@@ -262,7 +262,7 @@ proc mangleName(m: BModule, s: PSym): Rope =
if m.config.hcrOn:
# When hot reloading is enabled, we must ensure that the names
# of functions and types will be preserved across rebuilds:
result.add(idOrSig(s, m.module.name.s, m.sigConflicts))
result.add(idOrSig(s, m.module.name.s, m.sigConflicts, m.config))
else:
result.add("_")
result.add(rope(s.id))
@@ -2813,7 +2813,7 @@ proc genModule(p: PProc, n: PNode) =
if p.config.hcrOn and n.kind == nkStmtList:
let moduleSym = p.module.module
var moduleLoadedVar = rope(moduleSym.name.s) & "_loaded" &
idOrSig(moduleSym, moduleSym.name.s, p.module.sigConflicts)
idOrSig(moduleSym, moduleSym.name.s, p.module.sigConflicts, p.config)
lineF(p, "var $1;$n", [moduleLoadedVar])
var inGuardedBlock = false

View File

@@ -553,7 +553,7 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
# operation here:
var t = t
if t.assignment == nil or t.destructor == nil:
let h = sighashes.hashType(t, {CoType, CoConsiderOwned, CoDistinct})
let h = sighashes.hashType(t,c.g.config, {CoType, CoConsiderOwned, CoDistinct})
let canon = c.g.canonTypes.getOrDefault(h)
if canon != nil: t = canon
@@ -1113,7 +1113,7 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf
let skipped = orig.skipTypes({tyGenericInst, tyAlias, tySink})
if isEmptyContainer(skipped) or skipped.kind == tyStatic: return
let h = sighashes.hashType(skipped, {CoType, CoConsiderOwned, CoDistinct})
let h = sighashes.hashType(skipped, g.config, {CoType, CoConsiderOwned, CoDistinct})
var canon = g.canonTypes.getOrDefault(h)
if canon == nil:
g.canonTypes[h] = skipped

View File

@@ -10,7 +10,7 @@
## Path handling utilities for Nim. Strictly typed code in order
## to avoid the never ending time sink in getting path handling right.
import os, pathnorm
import os, pathnorm, strutils
when defined(nimPreviewSlimSystem):
import std/[syncio, assertions]
@@ -102,3 +102,52 @@ when true:
proc addFileExt*(x: RelativeFile; ext: string): RelativeFile {.borrow.}
proc writeFile*(x: AbsoluteFile; content: string) {.borrow.}
proc skipHomeDir(x: string): int =
when defined(windows):
if x.continuesWith("Users/", len("C:/")):
result = 3
else:
result = 0
else:
if x.startsWith("/home/") or x.startsWith("/Users/"):
result = 3
elif x.startsWith("/mnt/") and x.continuesWith("/Users/", len("/mnt/c")):
result = 5
else:
result = 0
proc relevantPart(s: string; afterSlashX: int): string =
result = newStringOfCap(s.len - 8)
var slashes = afterSlashX
for i in 0..<s.len:
if slashes == 0:
result.add s[i]
elif s[i] == '/':
dec slashes
template canonSlashes(x: string): string =
when defined(windows):
x.replace('\\', '/')
else:
x
proc customPathImpl(x: string): string =
# Idea: Encode a "protocol" via "//protocol/path" which is not ambiguous
# as path canonicalization would have removed the double slashes.
# /mnt/X/Users/Y
# X:\\Users\Y
# /home/Y
# -->
# //user/
if not isAbsolute(x):
result = customPathImpl(canonSlashes(getCurrentDir() / x))
else:
let slashes = skipHomeDir(x)
if slashes > 0:
result = "//user/" & relevantPart(x, slashes)
else:
result = x
proc customPath*(x: string): string =
customPathImpl canonSlashes x

View File

@@ -9,10 +9,12 @@
## Computes hash values for routine (proc, method etc) signatures.
import ast, tables, ropes, md5, modulegraphs
import ast, tables, ropes, md5, modulegraphs, options, msgs, packages, pathutils
from hashes import Hash
import types
import std/os
when defined(nimPreviewSlimSystem):
import std/assertions
@@ -42,8 +44,7 @@ type
CoDistinct
CoHashTypeInsideNode
proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag])
proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]; conf: ConfigRef)
proc hashSym(c: var MD5Context, s: PSym) =
if sfAnon in s.flags or s.kind == skGenericParam:
c &= ":anon"
@@ -54,20 +55,21 @@ proc hashSym(c: var MD5Context, s: PSym) =
c &= "."
it = it.owner
proc hashTypeSym(c: var MD5Context, s: PSym) =
proc hashTypeSym(c: var MD5Context, s: PSym; conf: ConfigRef) =
if sfAnon in s.flags or s.kind == skGenericParam:
c &= ":anon"
else:
var it = s
c &= customPath(conf.toFullPath(s.info))
while it != nil:
if sfFromGeneric in it.flags and it.kind in routineKinds and
it.typ != nil:
hashType c, it.typ, {CoProc}
hashType c, it.typ, {CoProc}, conf
c &= it.name.s
c &= "."
it = it.owner
proc hashTree(c: var MD5Context, n: PNode; flags: set[ConsiderFlag]) =
proc hashTree(c: var MD5Context, n: PNode; flags: set[ConsiderFlag]; conf: ConfigRef) =
if n == nil:
c &= "\255"
return
@@ -82,7 +84,7 @@ proc hashTree(c: var MD5Context, n: PNode; flags: set[ConsiderFlag]) =
of nkSym:
hashSym(c, n.sym)
if CoHashTypeInsideNode in flags and n.sym.typ != nil:
hashType(c, n.sym.typ, flags)
hashType(c, n.sym.typ, flags, conf)
of nkCharLit..nkUInt64Lit:
let v = n.intVal
lowlevel v
@@ -92,9 +94,9 @@ proc hashTree(c: var MD5Context, n: PNode; flags: set[ConsiderFlag]) =
of nkStrLit..nkTripleStrLit:
c &= n.strVal
else:
for i in 0..<n.len: hashTree(c, n[i], flags)
for i in 0..<n.len: hashTree(c, n[i], flags, conf)
proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]; conf: ConfigRef) =
if t == nil:
c &= "\254"
return
@@ -102,14 +104,14 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
case t.kind
of tyGenericInvocation:
for i in 0..<t.len:
c.hashType t[i], flags
c.hashType t[i], flags, conf
of tyDistinct:
if CoDistinct in flags:
if t.sym != nil: c.hashSym(t.sym)
if t.sym == nil or tfFromGeneric in t.flags:
c.hashType t.lastSon, flags
c.hashType t.lastSon, flags, conf
elif CoType in flags or t.sym == nil:
c.hashType t.lastSon, flags
c.hashType t.lastSon, flags, conf
else:
c.hashSym(t.sym)
of tyGenericInst:
@@ -119,15 +121,15 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
# value for each instantiation, so we hash the generic parameters here:
let normalizedType = t.skipGenericAlias
for i in 0..<normalizedType.len - 1:
c.hashType t[i], flags
c.hashType t[i], flags, conf
else:
c.hashType t.lastSon, flags
c.hashType t.lastSon, flags, conf
of tyAlias, tySink, tyUserTypeClasses, tyInferred:
c.hashType t.lastSon, flags
c.hashType t.lastSon, flags, conf
of tyOwned:
if CoConsiderOwned in flags:
c &= char(t.kind)
c.hashType t.lastSon, flags
c.hashType t.lastSon, flags, conf
of tyBool, tyChar, tyInt..tyUInt64:
# no canonicalization for integral types, so that e.g. ``pid_t`` is
# produced instead of ``NI``:
@@ -141,7 +143,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
t.typeInst = nil
assert inst.kind == tyGenericInst
for i in 0..<inst.len - 1:
c.hashType inst[i], flags
c.hashType inst[i], flags, conf
t.typeInst = inst
return
c &= char(t.kind)
@@ -153,7 +155,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
# The user has set a specific name for this type
c &= t.sym.loc.r
elif CoOwnerSig in flags:
c.hashTypeSym(t.sym)
c.hashTypeSym(t.sym, conf)
else:
c.hashSym(t.sym)
@@ -172,7 +174,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
# xxx instead, use a hash table to indicate we've already visited a type, which
# would also be more efficient.
symWithFlags.flags.excl {sfAnon, sfGenSym}
hashTree(c, t.n, flags + {CoHashTypeInsideNode})
hashTree(c, t.n, flags + {CoHashTypeInsideNode}, conf)
symWithFlags.flags = oldFlags
else:
# The object has no fields: we _must_ add something here in order to
@@ -182,15 +184,15 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
else:
c &= t.id
if t.len > 0 and t[0] != nil:
hashType c, t[0], flags
hashType c, t[0], flags, conf
of tyRef, tyPtr, tyGenericBody, tyVar:
c &= char(t.kind)
if t.sons.len > 0:
c.hashType t.lastSon, flags
c.hashType t.lastSon, flags, conf
if tfVarIsPtr in t.flags: c &= ".varisptr"
of tyFromExpr:
c &= char(t.kind)
c.hashTree(t.n, {})
c.hashTree(t.n, {}, conf)
of tyTuple:
c &= char(t.kind)
if t.n != nil and CoType notin flags:
@@ -199,19 +201,19 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
assert(t.n[i].kind == nkSym)
c &= t.n[i].sym.name.s
c &= ':'
c.hashType(t[i], flags+{CoIgnoreRange})
c.hashType(t[i], flags+{CoIgnoreRange}, conf)
c &= ','
else:
for i in 0..<t.len: c.hashType t[i], flags+{CoIgnoreRange}
for i in 0..<t.len: c.hashType t[i], flags+{CoIgnoreRange}, conf
of tyRange:
if CoIgnoreRange notin flags:
c &= char(t.kind)
c.hashTree(t.n, {})
c.hashType(t[0], flags)
c.hashTree(t.n, {}, conf)
c.hashType(t[0], flags, conf)
of tyStatic:
c &= char(t.kind)
c.hashTree(t.n, {})
c.hashType(t[0], flags)
c.hashTree(t.n, {}, conf)
c.hashType(t[0], flags, conf)
of tyProc:
c &= char(t.kind)
c &= (if tfIterator in t.flags: "iterator " else: "proc ")
@@ -221,11 +223,11 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
let param = params[i].sym
c &= param.name.s
c &= ':'
c.hashType(param.typ, flags)
c.hashType(param.typ, flags, conf)
c &= ','
c.hashType(t[0], flags)
c.hashType(t[0], flags, conf)
else:
for i in 0..<t.len: c.hashType(t[i], flags)
for i in 0..<t.len: c.hashType(t[i], flags, conf)
c &= char(t.callConv)
# purity of functions doesn't have to affect the mangling (which is in fact
# problematic for HCR - someone could have cached a pointer to another
@@ -237,10 +239,10 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
if tfVarargs in t.flags: c &= ".varargs"
of tyArray:
c &= char(t.kind)
for i in 0..<t.len: c.hashType(t[i], flags-{CoIgnoreRange})
for i in 0..<t.len: c.hashType(t[i], flags-{CoIgnoreRange}, conf)
else:
c &= char(t.kind)
for i in 0..<t.len: c.hashType(t[i], flags)
for i in 0..<t.len: c.hashType(t[i], flags, conf)
if tfNotNil in t.flags and CoType notin flags: c &= "not nil"
when defined(debugSigHashes):
@@ -257,19 +259,19 @@ when defined(debugSigHashes):
# select hash, type from sighashes where hash in
# (select hash from sighashes group by hash having count(*) > 1) order by hash;
proc hashType*(t: PType; flags: set[ConsiderFlag] = {CoType}): SigHash =
proc hashType*(t: PType; conf: ConfigRef; flags: set[ConsiderFlag] = {CoType}): SigHash =
var c: MD5Context
md5Init c
hashType c, t, flags+{CoOwnerSig}
hashType c, t, flags+{CoOwnerSig}, conf
md5Final c, result.MD5Digest
when defined(debugSigHashes):
db.exec(sql"INSERT OR IGNORE INTO sighashes(type, hash) VALUES (?, ?)",
typeToString(t), $result)
proc hashProc*(s: PSym): SigHash =
proc hashProc*(s: PSym; conf: ConfigRef): SigHash =
var c: MD5Context
md5Init c
hashType c, s.typ, {CoProc}
hashType c, s.typ, {CoProc}, conf
var m = s
while m.kind != skModule: m = m.owner
@@ -315,9 +317,9 @@ proc hashOwner*(s: PSym): SigHash =
md5Final c, result.MD5Digest
proc sigHash*(s: PSym): SigHash =
proc sigHash*(s: PSym; conf: ConfigRef): SigHash =
if s.kind in routineKinds and s.typ != nil:
result = hashProc(s)
result = hashProc(s, conf)
else:
result = hashNonProc(s)
@@ -378,7 +380,7 @@ proc symBodyDigest*(graph: ModuleGraph, sym: PSym): SigHash =
var c: MD5Context
md5Init(c)
c.hashType(sym.typ, {CoProc})
c.hashType(sym.typ, {CoProc}, graph.config)
c &= char(sym.kind)
c.md5Final(result.MD5Digest)
graph.symBodyHashes[sym.id] = result # protect from recursion in the body
@@ -391,12 +393,12 @@ proc symBodyDigest*(graph: ModuleGraph, sym: PSym): SigHash =
graph.symBodyHashes[sym.id] = result
proc idOrSig*(s: PSym, currentModule: string,
sigCollisions: var CountTable[SigHash]): Rope =
sigCollisions: var CountTable[SigHash]; conf: ConfigRef): Rope =
if s.kind in routineKinds and s.typ != nil:
# signatures for exported routines are reliable enough to
# produce a unique name and this means produced C++ is more stable regarding
# Nim changes:
let sig = hashProc(s)
let sig = hashProc(s, conf)
result = rope($sig)
#let m = if s.typ.callConv != ccInline: findPendingModule(m, s) else: m
let counter = sigCollisions.getOrDefault(sig)

View File

@@ -1855,7 +1855,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
if regs[rb].node.kind != nkSym:
stackTrace(c, tos, pc, "node is not a symbol")
else:
regs[ra].node.strVal = $sigHash(regs[rb].node.sym)
regs[ra].node.strVal = $sigHash(regs[rb].node.sym, c.config)
of opcSlurp:
decodeB(rkNode)
createStr regs[ra]

View File

@@ -0,0 +1,4 @@
type MyObj* = object
field1*: int
s*: string
ch*: char

View File

@@ -0,0 +1,4 @@
type MyObj* = object
s*: string
field1*: int
ch*: char

10
tests/ccgbugs/t20139.nim Normal file
View File

@@ -0,0 +1,10 @@
discard """
joinable: false
"""
# bug #20139
import m1/defs as md1
import m2/defs as md2
doAssert $(md1.MyObj(field1: 1)) == """(field1: 1, s: "", ch: '\x00')"""
doAssert $(md2.MyObj(field1: 1)) == """(s: "", field1: 1, ch: '\x00')"""