mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-14 15:23:27 +00:00
* 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:
@@ -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])
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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", [])
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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]
|
||||
|
||||
4
tests/ccgbugs/m1/defs.nim
Normal file
4
tests/ccgbugs/m1/defs.nim
Normal file
@@ -0,0 +1,4 @@
|
||||
type MyObj* = object
|
||||
field1*: int
|
||||
s*: string
|
||||
ch*: char
|
||||
4
tests/ccgbugs/m2/defs.nim
Normal file
4
tests/ccgbugs/m2/defs.nim
Normal file
@@ -0,0 +1,4 @@
|
||||
type MyObj* = object
|
||||
s*: string
|
||||
field1*: int
|
||||
ch*: char
|
||||
10
tests/ccgbugs/t20139.nim
Normal file
10
tests/ccgbugs/t20139.nim
Normal 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')"""
|
||||
Reference in New Issue
Block a user