mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-11 22:08:54 +00:00
fixes #25459; hashType returns different hash from instantiated generics with distinct types (#25471)
`hashType` proc returned the same hash value from different instanced generics types like `D[int64]` and `D[F]`. That caused the struct type with wrong field types. object/tuple type size check code is generated when it is compiled with `-d:checkAbi` option.
This commit is contained in:
@@ -294,7 +294,12 @@ proc cacheGetType(tab: TypeCache; sig: SigHash): Rope =
|
||||
result = tab.getOrDefault(sig)
|
||||
|
||||
proc addAbiCheck(m: BModule; t: PType, name: Rope) =
|
||||
if isDefined(m.config, "checkAbi") and (let size = getSize(m.config, t); size != szUnknownSize):
|
||||
if isDefined(m.config, "checkAbi") and (let size = getSize(m.config, t); size != szUnknownSize) and
|
||||
not (t.kind == tyObject and searchTypeFor(t, proc (t: PType): bool {.nimcall.} = t.kind == tyUncheckedArray)):
|
||||
# `UncheckedArray`, not `ptr UncheckedArray` type field in object types is a flexible array.
|
||||
# `sizeof` in C and Nim doesn't always return the same value for object types containing it.
|
||||
# making `getSize` in Nim always returns the same value as `sizeof` in C from flexible arrays seems hard.
|
||||
# See `SEQ_DECL_SIZE` in lib/nimbase.h
|
||||
var msg = "backend & Nim disagree on size for: "
|
||||
msg.addTypeHeader(m.config, t)
|
||||
var msg2 = ""
|
||||
@@ -1067,6 +1072,7 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
|
||||
else: getTupleDesc(m, t, result, check)
|
||||
if not isImportedType(t):
|
||||
m.s[cfsTypes].add(recdesc)
|
||||
addAbiCheck(m, t, result)
|
||||
elif tfIncompleteStruct notin t.flags:
|
||||
discard # addAbiCheck(m, t, result) # already handled elsewhere
|
||||
of tySet:
|
||||
|
||||
@@ -154,7 +154,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]; conf: Confi
|
||||
assert inst.kind == tyGenericInst
|
||||
c.hashType inst.genericHead, flags, conf
|
||||
for _, a in inst.genericInstParams:
|
||||
c.hashType a, flags, conf
|
||||
c.hashType a, flags+{CoDistinct}, conf
|
||||
t.typeInstImpl = inst
|
||||
return
|
||||
c &= char(t.kind)
|
||||
|
||||
@@ -143,7 +143,7 @@ proc getFloatValue*(n: PNode): BiggestFloat =
|
||||
|
||||
proc addTypeHeader*(result: var string, conf: ConfigRef; typ: PType; prefer: TPreferedDesc = preferMixed; getDeclarationPath = true) =
|
||||
result.add typeToString(typ, prefer)
|
||||
if getDeclarationPath: result.addDeclaredLoc(conf, typ.sym)
|
||||
if getDeclarationPath and typ.sym != nil: result.addDeclaredLoc(conf, typ.sym)
|
||||
|
||||
proc getProcHeader*(conf: ConfigRef; sym: PSym; prefer: TPreferedDesc = preferName; getDeclarationPath = true): string =
|
||||
assert sym != nil
|
||||
|
||||
11
tests/ccgbugs2/m25459/g.nim
Normal file
11
tests/ccgbugs2/m25459/g.nim
Normal file
@@ -0,0 +1,11 @@
|
||||
proc v[T](_: typedesc[T]): int =
|
||||
if T is int64: 6 else: 4
|
||||
|
||||
type
|
||||
D*[T] = object
|
||||
c*: seq[T]
|
||||
k*: array[v(T), int]
|
||||
F = distinct int64
|
||||
W* = object
|
||||
y: D[F]
|
||||
j*: D[int64]
|
||||
8
tests/ccgbugs2/m25459/h.nim
Normal file
8
tests/ccgbugs2/m25459/h.nim
Normal file
@@ -0,0 +1,8 @@
|
||||
import ./g
|
||||
export g
|
||||
|
||||
proc a*(): W =
|
||||
var e = D[int64]()
|
||||
e.c.setLen(8)
|
||||
e.k[1] = 0
|
||||
result = W(j: e)
|
||||
10
tests/ccgbugs2/t25459.nim
Normal file
10
tests/ccgbugs2/t25459.nim
Normal file
@@ -0,0 +1,10 @@
|
||||
discard """
|
||||
targets: "c cpp"
|
||||
matrix: "-d:checkAbi"
|
||||
"""
|
||||
|
||||
import ./m25459/h
|
||||
|
||||
for _ in 0 ..< 500:
|
||||
let u = new W
|
||||
u[] = a()
|
||||
31
tests/ccgbugs2/t25459b.nim
Normal file
31
tests/ccgbugs2/t25459b.nim
Normal file
@@ -0,0 +1,31 @@
|
||||
discard """
|
||||
targets: "c cpp"
|
||||
matrix: "-d:checkAbi"
|
||||
"""
|
||||
|
||||
proc v[T](_: typedesc[T]): int =
|
||||
if T is int64: 2 else: 1
|
||||
|
||||
type
|
||||
D[T] = object
|
||||
k: array[v(T), int]
|
||||
E[T] = object
|
||||
k: array[v(T), int]
|
||||
F = distinct int64
|
||||
W = object
|
||||
a: D[int64]
|
||||
b: D[F]
|
||||
|
||||
proc csizeof[T](x {.bycopy.} : T): cint {.importc: "sizeof", nodecl.}
|
||||
|
||||
var w: W
|
||||
assert sizeof(w) == csizeof(w)
|
||||
|
||||
var
|
||||
e0: E[F]
|
||||
e1: E[int64]
|
||||
assert sizeof(e0) == csizeof(e0)
|
||||
assert sizeof(e1) == csizeof(e1)
|
||||
|
||||
var tup: (E[F], E[int64])
|
||||
assert sizeof(tup) == csizeof(tup)
|
||||
Reference in New Issue
Block a user