Skip to content

Commit

Permalink
fixes nim-lang#20139; hash types based on its path relative to its pa…
Browse files Browse the repository at this point in the history
…ckage path (nim-lang#21274) [backport:1.6]

* fixes nim-lang#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>
(cherry picked from commit 38d299d)
  • Loading branch information
ringabout authored and narimiran committed Mar 9, 2023
1 parent b6333c4 commit 19dd56f
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 64 deletions.
28 changes: 14 additions & 14 deletions compiler/ccgtypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ proc mangleName(m: BModule; s: PSym): Rope =
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)

Expand Down Expand Up @@ -311,7 +311,7 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
else: result = nil

if result != nil and typ.isImportedType():
let sig = hashType typ
let sig = hashType(typ, m.config)
if cacheGetType(m.typeCache, sig) == nil:
m.typeCache[sig] = result

Expand Down Expand Up @@ -371,10 +371,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")
Expand Down Expand Up @@ -407,7 +407,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 == nil:
discard getTypeDescAux(m, t, check, skVar)
Expand Down Expand Up @@ -672,7 +672,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:
Expand All @@ -696,7 +696,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):
Expand Down Expand Up @@ -725,7 +725,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:
Expand All @@ -734,7 +734,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)
Expand Down Expand Up @@ -897,7 +897,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKin
discard # addAbiCheck(m, t, result) # already handled elsewhere
of tySet:
# Don't use the imported name as it may be scoped: 'Foo::SomeKind'
result = $t.kind & '_' & t.lastSon.typeName & $t.lastSon.hashType
result = $t.kind & '_' & t.lastSon.typeName & $t.lastSon.hashType(m.config)
m.typeCache[sig] = result
if not isImportedType(t):
let s = int(getSize(m.config, t))
Expand Down Expand Up @@ -1070,7 +1070,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)

Expand Down Expand Up @@ -1291,7 +1291,7 @@ proc genTypeInfo2Name(m: BModule; t: PType): Rope =
res.add m.name.s & "."
res.add it.sym.name.s
else:
res.add $hashType(it)
res.add $hashType(it, m.config)
res.add "|"
it = it[0]
result = makeCString(res)
Expand Down Expand Up @@ -1355,7 +1355,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 != nil:
return prefixTI.rope & result & ")".rope
Expand Down Expand Up @@ -1426,7 +1426,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 != nil:
return prefixTI.rope & result & ")".rope
Expand Down
2 changes: 1 addition & 1 deletion compiler/cgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1600,7 +1600,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", [])
Expand Down
2 changes: 1 addition & 1 deletion compiler/injectdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,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)
Expand Down
4 changes: 2 additions & 2 deletions compiler/jsgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,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))
Expand Down Expand Up @@ -2712,7 +2712,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

Expand Down
4 changes: 2 additions & 2 deletions compiler/liftdestructors.nim
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,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

Expand Down Expand Up @@ -1072,7 +1072,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
Expand Down
51 changes: 50 additions & 1 deletion compiler/pathutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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

type
AbsoluteFile* = distinct string
Expand Down Expand Up @@ -99,3 +99,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
Loading

0 comments on commit 19dd56f

Please sign in to comment.