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
commit 38d299dfc0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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) = proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo; result: var Rope) =
if optTinyRtti in p.config.globalOptions: 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]) appcg(p.module, result, "#isObjDisplayCheck($#.m_type, $#, $#)", [a, getObjDepth(dest), token])
else: else:
# unfortunately 'genTypeInfoV1' sets tfObjHasKids as a side effect, so we # 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) rdMType(p, a, nilCheck, r)
if optTinyRtti in p.config.globalOptions: if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(dest) let checkFor = $getObjDepth(dest)
let token = $genDisplayElem(MD5Digest(hashType(dest))) let token = $genDisplayElem(MD5Digest(hashType(dest, p.config)))
if nilCheck != "": if nilCheck != "":
linefmt(p, cpsStmts, "if ($1 && !#isObjDisplayCheck($2, $3, $4)){ #raiseObjectConversionError(); ", linefmt(p, cpsStmts, "if ($1 && !#isObjDisplayCheck($2, $3, $4)){ #raiseObjectConversionError(); ",
[nilCheck, r, checkFor, token]) [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" let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
if optTinyRtti in p.config.globalOptions: if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(typeNode.typ) 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: else:
let checkFor = genTypeInfoV1(p.module, typeNode.typ, typeNode.info) let checkFor = genTypeInfoV1(p.module, typeNode.typ, typeNode.info)
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor]) 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" let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
if optTinyRtti in p.config.globalOptions: if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(t[i][j].typ) 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: else:
let checkFor = genTypeInfoV1(p.module, t[i][j].typ, t[i][j].info) let checkFor = genTypeInfoV1(p.module, t[i][j].typ, t[i][j].info)
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor]) 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" let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
if optTinyRtti in p.config.globalOptions: if optTinyRtti in p.config.globalOptions:
let checkFor = $getObjDepth(t[i][j].typ) 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: else:
let checkFor = genTypeInfoV1(p.module, t[i][j].typ, t[i][j].info) let checkFor = genTypeInfoV1(p.module, t[i][j].typ, t[i][j].info)
appcg(p.module, orExpr, "#isObj(#nimBorrowCurrentException()->$1, $2)", [memberName, checkFor]) 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 result.add rope s.itemId.item
if m.hcrOn: if m.hcrOn:
result.add "_" 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 s.loc.r = result
writeMangledName(m.ndi, s, m.config) writeMangledName(m.ndi, s, m.config)
proc fillParamName(m: BModule; s: PSym) = proc fillParamName(m: BModule; s: PSym) =
if s.loc.r == "": if s.loc.r == "":
var res = s.name.s.mangle 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: # 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, # 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 # 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 = "" else: result = ""
if result != "" and typ.isImportedType(): if result != "" and typ.isImportedType():
let sig = hashType typ let sig = hashType(typ, m.config)
if cacheGetType(m.typeCache, sig) == "": if cacheGetType(m.typeCache, sig) == "":
m.typeCache[sig] = result 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: if isImportedCppType(etB) and t.kind == tyGenericInst:
result = getTypeDescAux(m, t, check, kind) result = getTypeDescAux(m, t, check, kind)
else: else:
result = getTypeForward(m, t, hashType(t)) result = getTypeForward(m, t, hashType(t, m.config))
pushType(m, t) pushType(m, t)
of tySequence: of tySequence:
let sig = hashType(t) let sig = hashType(t, m.config)
if optSeqDestructors in m.config.globalOptions: if optSeqDestructors in m.config.globalOptions:
if skipTypes(etB[0], typedescInst).kind == tyEmpty: if skipTypes(etB[0], typedescInst).kind == tyEmpty:
internalError(m.config, "cannot map the empty seq type to a C type") 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" #result = getTypeForward(m, t, hashType(t)) & "_Content"
proc seqV2ContentType(m: BModule; t: PType; check: var IntSet) = 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) let result = cacheGetType(m.typeCache, sig)
if result == "": if result == "":
discard getTypeDescAux(m, t, check, skVar) discard getTypeDescAux(m, t, check, skVar)
@ -664,7 +664,7 @@ proc resolveStarsInCppType(typ: PType, idx, stars: int): PType =
else: result.elemType else: result.elemType
proc getOpenArrayDesc(m: BModule, t: PType, check: var IntSet; kind: TSymKind): Rope = 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: if kind == skParam:
result = getTypeDescWeak(m, t[0], check, kind) & "*" result = getTypeDescWeak(m, t[0], check, kind) & "*"
else: 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. # C type generation into an analysis and a code generation phase somehow.
if t.sym != nil: useHeader(m, t.sym) if t.sym != nil: useHeader(m, t.sym)
if t != origTyp and origTyp.sym != nil: useHeader(m, origTyp.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 defer: # defer is the simplest in this case
if isImportedType(t) and not m.typeABICache.containsOrIncl(sig): 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 result = getTypeDescAux(m, et, check, kind) & star
else: else:
# no restriction! We have a forward declaration for structs # 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 result = name & star
m.typeCache[sig] = result m.typeCache[sig] = result
of tySequence: of tySequence:
@ -726,7 +726,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
m.typeCache[sig] = result m.typeCache[sig] = result
else: else:
# no restriction! We have a forward declaration for structs # 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 result = name & seqStar(m) & star
m.typeCache[sig] = result m.typeCache[sig] = result
pushType(m, et) 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' # Don't use the imported name as it may be scoped: 'Foo::SomeKind'
result = rope("tySet_") result = rope("tySet_")
t.lastSon.typeName(result) t.lastSon.typeName(result)
result.add $t.lastSon.hashType result.add $t.lastSon.hashType(m.config)
m.typeCache[sig] = result m.typeCache[sig] = result
if not isImportedType(t): if not isImportedType(t):
let s = int(getSize(m.config, 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) objtype = objtype[0].skipTypes(abstractPtrs)
if objtype.sym == nil: if objtype.sym == nil:
internalError(m.config, d.info, "anonymous obj with discriminator") 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) 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 m.name.s & "."
result.add it.sym.name.s result.add it.sym.name.s
else: else:
result = $hashType(it) result = $hashType(it, m.config)
result = makeCString(result) result = makeCString(result)
proc isTrivialProc(g: ModuleGraph; s: PSym): bool {.inline.} = getBody(g, s).len == 0 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 += uint32(d[i])
result = result shl 8 result = result shl 8
proc genDisplay(t: PType, depth: int): Rope = proc genDisplay(m: BModule, t: PType, depth: int): Rope =
result = Rope"{" result = Rope"{"
var x = t var x = t
var seqs = newSeq[string](depth+1) var seqs = newSeq[string](depth+1)
var i = 0 var i = 0
while x != nil: while x != nil:
x = skipTypes(x, skipPtrs) x = skipTypes(x, skipPtrs)
seqs[i] = $genDisplayElem(MD5Digest(hashType(x))) seqs[i] = $genDisplayElem(MD5Digest(hashType(x, m.config)))
x = x[0] x = x[0]
inc i 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)]) [name, getTypeDesc(m, t), rope(objDepth), rope(flags)])
if objDepth >= 0: if objDepth >= 0:
let objDisplay = genDisplay(t, objDepth) let objDisplay = genDisplay(m, t, objDepth)
let objDisplayStore = getTempName(m) 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]) 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)]) 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)]) [getTypeDesc(m, t), rope(objDepth)])
if objDepth >= 0: if objDepth >= 0:
let objDisplay = genDisplay(t, objDepth) let objDisplay = genDisplay(m, t, objDepth)
let objDisplayStore = getTempName(m) 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]) 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)]) 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 prefixTI = if m.hcrOn: "(" else: "(&"
let sig = hashType(origType) let sig = hashType(origType, m.config)
result = m.typeInfoMarkerV2.getOrDefault(sig) result = m.typeInfoMarkerV2.getOrDefault(sig)
if result != "": if result != "":
return prefixTI.rope & result & ")".rope 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 prefixTI = if m.hcrOn: "(" else: "(&"
let sig = hashType(origType) let sig = hashType(origType, m.config)
result = m.typeInfoMarker.getOrDefault(sig) result = m.typeInfoMarker.getOrDefault(sig)
if result != "": if result != "":
return prefixTI.rope & result & ")".rope return prefixTI.rope & result & ")".rope

View file

@ -1630,7 +1630,7 @@ proc registerModuleToMain(g: BModuleList; m: BModule) =
hcrModuleMeta.addf("\t\"\"};$n", []) 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(void**, HcrGetImportedModules)() { return (void**)hcr_module_list; }$n", [])
hcrModuleMeta.addf("$nN_LIB_EXPORT N_NIMCALL(char*, HcrGetSigHash)() { return \"$1\"; }$n$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: if sfMainModule in m.module.flags:
g.mainModProcs.add(hcrModuleMeta) g.mainModProcs.add(hcrModuleMeta)
g.mainModProcs.addf("static void* hcr_handle;$N", []) 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) var op = getAttachedOp(c.graph, t, kind)
if op == nil or op.ast.isGenericRoutine: if op == nil or op.ast.isGenericRoutine:
# give up and find the canonical type instead: # 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) let canon = c.graph.canonTypes.getOrDefault(h)
if canon != nil: if canon != nil:
op = getAttachedOp(c.graph, canon, kind) op = getAttachedOp(c.graph, canon, kind)

View file

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

View file

@ -553,7 +553,7 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
# operation here: # operation here:
var t = t var t = t
if t.assignment == nil or t.destructor == nil: 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) let canon = c.g.canonTypes.getOrDefault(h)
if canon != nil: t = canon 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}) let skipped = orig.skipTypes({tyGenericInst, tyAlias, tySink})
if isEmptyContainer(skipped) or skipped.kind == tyStatic: return 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) var canon = g.canonTypes.getOrDefault(h)
if canon == nil: if canon == nil:
g.canonTypes[h] = skipped g.canonTypes[h] = skipped

View file

@ -10,7 +10,7 @@
## Path handling utilities for Nim. Strictly typed code in order ## Path handling utilities for Nim. Strictly typed code in order
## to avoid the never ending time sink in getting path handling right. ## to avoid the never ending time sink in getting path handling right.
import os, pathnorm import os, pathnorm, strutils
when defined(nimPreviewSlimSystem): when defined(nimPreviewSlimSystem):
import std/[syncio, assertions] import std/[syncio, assertions]
@ -102,3 +102,52 @@ when true:
proc addFileExt*(x: RelativeFile; ext: string): RelativeFile {.borrow.} proc addFileExt*(x: RelativeFile; ext: string): RelativeFile {.borrow.}
proc writeFile*(x: AbsoluteFile; content: string) {.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. ## 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 from hashes import Hash
import types import types
import std/os
when defined(nimPreviewSlimSystem): when defined(nimPreviewSlimSystem):
import std/assertions import std/assertions
@ -42,8 +44,7 @@ type
CoDistinct CoDistinct
CoHashTypeInsideNode 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) = proc hashSym(c: var MD5Context, s: PSym) =
if sfAnon in s.flags or s.kind == skGenericParam: if sfAnon in s.flags or s.kind == skGenericParam:
c &= ":anon" c &= ":anon"
@ -54,20 +55,21 @@ proc hashSym(c: var MD5Context, s: PSym) =
c &= "." c &= "."
it = it.owner 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: if sfAnon in s.flags or s.kind == skGenericParam:
c &= ":anon" c &= ":anon"
else: else:
var it = s var it = s
c &= customPath(conf.toFullPath(s.info))
while it != nil: while it != nil:
if sfFromGeneric in it.flags and it.kind in routineKinds and if sfFromGeneric in it.flags and it.kind in routineKinds and
it.typ != nil: it.typ != nil:
hashType c, it.typ, {CoProc} hashType c, it.typ, {CoProc}, conf
c &= it.name.s c &= it.name.s
c &= "." c &= "."
it = it.owner 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: if n == nil:
c &= "\255" c &= "\255"
return return
@ -82,7 +84,7 @@ proc hashTree(c: var MD5Context, n: PNode; flags: set[ConsiderFlag]) =
of nkSym: of nkSym:
hashSym(c, n.sym) hashSym(c, n.sym)
if CoHashTypeInsideNode in flags and n.sym.typ != nil: 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: of nkCharLit..nkUInt64Lit:
let v = n.intVal let v = n.intVal
lowlevel v lowlevel v
@ -92,9 +94,9 @@ proc hashTree(c: var MD5Context, n: PNode; flags: set[ConsiderFlag]) =
of nkStrLit..nkTripleStrLit: of nkStrLit..nkTripleStrLit:
c &= n.strVal c &= n.strVal
else: 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: if t == nil:
c &= "\254" c &= "\254"
return return
@ -102,14 +104,14 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
case t.kind case t.kind
of tyGenericInvocation: of tyGenericInvocation:
for i in 0..<t.len: for i in 0..<t.len:
c.hashType t[i], flags c.hashType t[i], flags, conf
of tyDistinct: of tyDistinct:
if CoDistinct in flags: if CoDistinct in flags:
if t.sym != nil: c.hashSym(t.sym) if t.sym != nil: c.hashSym(t.sym)
if t.sym == nil or tfFromGeneric in t.flags: 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: elif CoType in flags or t.sym == nil:
c.hashType t.lastSon, flags c.hashType t.lastSon, flags, conf
else: else:
c.hashSym(t.sym) c.hashSym(t.sym)
of tyGenericInst: 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: # value for each instantiation, so we hash the generic parameters here:
let normalizedType = t.skipGenericAlias let normalizedType = t.skipGenericAlias
for i in 0..<normalizedType.len - 1: for i in 0..<normalizedType.len - 1:
c.hashType t[i], flags c.hashType t[i], flags, conf
else: else:
c.hashType t.lastSon, flags c.hashType t.lastSon, flags, conf
of tyAlias, tySink, tyUserTypeClasses, tyInferred: of tyAlias, tySink, tyUserTypeClasses, tyInferred:
c.hashType t.lastSon, flags c.hashType t.lastSon, flags, conf
of tyOwned: of tyOwned:
if CoConsiderOwned in flags: if CoConsiderOwned in flags:
c &= char(t.kind) c &= char(t.kind)
c.hashType t.lastSon, flags c.hashType t.lastSon, flags, conf
of tyBool, tyChar, tyInt..tyUInt64: of tyBool, tyChar, tyInt..tyUInt64:
# no canonicalization for integral types, so that e.g. ``pid_t`` is # no canonicalization for integral types, so that e.g. ``pid_t`` is
# produced instead of ``NI``: # produced instead of ``NI``:
@ -141,7 +143,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
t.typeInst = nil t.typeInst = nil
assert inst.kind == tyGenericInst assert inst.kind == tyGenericInst
for i in 0..<inst.len - 1: for i in 0..<inst.len - 1:
c.hashType inst[i], flags c.hashType inst[i], flags, conf
t.typeInst = inst t.typeInst = inst
return return
c &= char(t.kind) 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 # The user has set a specific name for this type
c &= t.sym.loc.r c &= t.sym.loc.r
elif CoOwnerSig in flags: elif CoOwnerSig in flags:
c.hashTypeSym(t.sym) c.hashTypeSym(t.sym, conf)
else: else:
c.hashSym(t.sym) 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 # xxx instead, use a hash table to indicate we've already visited a type, which
# would also be more efficient. # would also be more efficient.
symWithFlags.flags.excl {sfAnon, sfGenSym} symWithFlags.flags.excl {sfAnon, sfGenSym}
hashTree(c, t.n, flags + {CoHashTypeInsideNode}) hashTree(c, t.n, flags + {CoHashTypeInsideNode}, conf)
symWithFlags.flags = oldFlags symWithFlags.flags = oldFlags
else: else:
# The object has no fields: we _must_ add something here in order to # 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: else:
c &= t.id c &= t.id
if t.len > 0 and t[0] != nil: if t.len > 0 and t[0] != nil:
hashType c, t[0], flags hashType c, t[0], flags, conf
of tyRef, tyPtr, tyGenericBody, tyVar: of tyRef, tyPtr, tyGenericBody, tyVar:
c &= char(t.kind) c &= char(t.kind)
if t.sons.len > 0: if t.sons.len > 0:
c.hashType t.lastSon, flags c.hashType t.lastSon, flags, conf
if tfVarIsPtr in t.flags: c &= ".varisptr" if tfVarIsPtr in t.flags: c &= ".varisptr"
of tyFromExpr: of tyFromExpr:
c &= char(t.kind) c &= char(t.kind)
c.hashTree(t.n, {}) c.hashTree(t.n, {}, conf)
of tyTuple: of tyTuple:
c &= char(t.kind) c &= char(t.kind)
if t.n != nil and CoType notin flags: 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) assert(t.n[i].kind == nkSym)
c &= t.n[i].sym.name.s c &= t.n[i].sym.name.s
c &= ':' c &= ':'
c.hashType(t[i], flags+{CoIgnoreRange}) c.hashType(t[i], flags+{CoIgnoreRange}, conf)
c &= ',' c &= ','
else: 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: of tyRange:
if CoIgnoreRange notin flags: if CoIgnoreRange notin flags:
c &= char(t.kind) c &= char(t.kind)
c.hashTree(t.n, {}) c.hashTree(t.n, {}, conf)
c.hashType(t[0], flags) c.hashType(t[0], flags, conf)
of tyStatic: of tyStatic:
c &= char(t.kind) c &= char(t.kind)
c.hashTree(t.n, {}) c.hashTree(t.n, {}, conf)
c.hashType(t[0], flags) c.hashType(t[0], flags, conf)
of tyProc: of tyProc:
c &= char(t.kind) c &= char(t.kind)
c &= (if tfIterator in t.flags: "iterator " else: "proc ") 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 let param = params[i].sym
c &= param.name.s c &= param.name.s
c &= ':' c &= ':'
c.hashType(param.typ, flags) c.hashType(param.typ, flags, conf)
c &= ',' c &= ','
c.hashType(t[0], flags) c.hashType(t[0], flags, conf)
else: 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) c &= char(t.callConv)
# purity of functions doesn't have to affect the mangling (which is in fact # 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 # 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" if tfVarargs in t.flags: c &= ".varargs"
of tyArray: of tyArray:
c &= char(t.kind) 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: else:
c &= char(t.kind) 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" if tfNotNil in t.flags and CoType notin flags: c &= "not nil"
when defined(debugSigHashes): when defined(debugSigHashes):
@ -257,19 +259,19 @@ when defined(debugSigHashes):
# select hash, type from sighashes where hash in # select hash, type from sighashes where hash in
# (select hash from sighashes group by hash having count(*) > 1) order by hash; # (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 var c: MD5Context
md5Init c md5Init c
hashType c, t, flags+{CoOwnerSig} hashType c, t, flags+{CoOwnerSig}, conf
md5Final c, result.MD5Digest md5Final c, result.MD5Digest
when defined(debugSigHashes): when defined(debugSigHashes):
db.exec(sql"INSERT OR IGNORE INTO sighashes(type, hash) VALUES (?, ?)", db.exec(sql"INSERT OR IGNORE INTO sighashes(type, hash) VALUES (?, ?)",
typeToString(t), $result) typeToString(t), $result)
proc hashProc*(s: PSym): SigHash = proc hashProc*(s: PSym; conf: ConfigRef): SigHash =
var c: MD5Context var c: MD5Context
md5Init c md5Init c
hashType c, s.typ, {CoProc} hashType c, s.typ, {CoProc}, conf
var m = s var m = s
while m.kind != skModule: m = m.owner while m.kind != skModule: m = m.owner
@ -315,9 +317,9 @@ proc hashOwner*(s: PSym): SigHash =
md5Final c, result.MD5Digest 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: if s.kind in routineKinds and s.typ != nil:
result = hashProc(s) result = hashProc(s, conf)
else: else:
result = hashNonProc(s) result = hashNonProc(s)
@ -378,7 +380,7 @@ proc symBodyDigest*(graph: ModuleGraph, sym: PSym): SigHash =
var c: MD5Context var c: MD5Context
md5Init(c) md5Init(c)
c.hashType(sym.typ, {CoProc}) c.hashType(sym.typ, {CoProc}, graph.config)
c &= char(sym.kind) c &= char(sym.kind)
c.md5Final(result.MD5Digest) c.md5Final(result.MD5Digest)
graph.symBodyHashes[sym.id] = result # protect from recursion in the body 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 graph.symBodyHashes[sym.id] = result
proc idOrSig*(s: PSym, currentModule: string, 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: if s.kind in routineKinds and s.typ != nil:
# signatures for exported routines are reliable enough to # signatures for exported routines are reliable enough to
# produce a unique name and this means produced C++ is more stable regarding # produce a unique name and this means produced C++ is more stable regarding
# Nim changes: # Nim changes:
let sig = hashProc(s) let sig = hashProc(s, conf)
result = rope($sig) result = rope($sig)
#let m = if s.typ.callConv != ccInline: findPendingModule(m, s) else: m #let m = if s.typ.callConv != ccInline: findPendingModule(m, s) else: m
let counter = sigCollisions.getOrDefault(sig) 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: if regs[rb].node.kind != nkSym:
stackTrace(c, tos, pc, "node is not a symbol") stackTrace(c, tos, pc, "node is not a symbol")
else: else:
regs[ra].node.strVal = $sigHash(regs[rb].node.sym) regs[ra].node.strVal = $sigHash(regs[rb].node.sym, c.config)
of opcSlurp: of opcSlurp:
decodeB(rkNode) decodeB(rkNode)
createStr regs[ra] 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')"""