@@ -182,7 +182,7 @@ proc hashData*(data: pointer, size: int): Hash =
182182 var h: Hash = 0
183183 when defined (js):
184184 var p: cstring
185- asm """ ` p` = ` Data` ; """
185+ asm """ ` p` = ` Data` """
186186 else :
187187 var p = cast [cstring ](data)
188188 var i = 0
@@ -193,12 +193,22 @@ proc hashData*(data: pointer, size: int): Hash =
193193 dec (s)
194194 result = !$ h
195195
196+ proc hashIdentity * [T: Ordinal | enum ](x: T): Hash {.inline , since : (1 , 3 ).} =
197+ # # The identity hash, i.e. `hashIdentity(x) = x`.
198+ cast [Hash ](ord (x))
199+
200+ when defined (nimIntHash1):
201+ proc hash * [T: Ordinal | enum ](x: T): Hash {.inline .} =
202+ # # Efficient hashing of integers.
203+ cast [Hash ](ord (x))
204+ else :
205+ proc hash * [T: Ordinal | enum ](x: T): Hash {.inline .} =
206+ # # Efficient hashing of integers.
207+ hashWangYi1 (uint64 (ord (x)))
208+
196209when defined (js):
197210 var objectID = 0
198-
199- proc hash * (x: pointer ): Hash {.inline .} =
200- # # Efficient hashing of pointers.
201- when defined (js):
211+ proc getObjectId (x: pointer ): int =
202212 asm """
203213 if (typeof ` x` == "object") {
204214 if ("_NimID" in ` x` )
@@ -209,29 +219,46 @@ proc hash*(x: pointer): Hash {.inline.} =
209219 }
210220 }
211221 """
222+
223+ proc hash * (x: pointer ): Hash {.inline .} =
224+ # # Efficient `hash` overload.
225+ when defined (js):
226+ let y = getObjectId (x)
212227 else :
213- result = cast [Hash ](cast [uint ](x) shr 3 ) # skip the alignment
228+ let y = cast [int ](x)
229+ hash (y) # consistent with code expecting scrambled hashes depending on `nimIntHash1`.
230+
231+ proc hash * [T](x: ref [T] | ptr [T]): Hash {.inline .} =
232+ # # Efficient `hash` overload.
233+ runnableExamples:
234+ var a: array [10 , uint8 ]
235+ assert a[0 ].addr .hash != a[1 ].addr .hash
236+ assert cast [pointer ](a[0 ].addr ).hash == a[0 ].addr .hash
237+ runnableExamples:
238+ type A = ref object
239+ x: int
240+ let a = A (x: 3 )
241+ let ha = a.hash
242+ assert ha != A (x: 3 ).hash # A(x: 3) is a different ref object from `a`.
243+ a.x = 4
244+ assert ha == a.hash # the hash only depends on the address
245+ runnableExamples:
246+ # you can overload `hash` if you want to customize semantics
247+ type A[T] = ref object
248+ x, y: T
249+ proc hash (a: A): Hash = hash (a.x)
250+ assert A [int ](x: 3 , y: 4 ).hash == A [int ](x: 3 , y: 5 ).hash
251+ # xxx pending bug #17733, merge as `proc hash*(pointer | ref | ptr): Hash`
252+ # or `proc hash*[T: ref | ptr](x: T): Hash`
253+ hash (cast [pointer ](x))
214254
215255proc hash * [T: proc ](x: T): Hash {.inline .} =
216256 # # Efficient hashing of proc vars. Closures are supported too.
217257 when T is " closure" :
218- result = hash (rawProc (x)) !& hash ( rawEnv (x))
258+ result = hash (( rawProc (x), rawEnv (x) ))
219259 else :
220260 result = hash (pointer (x))
221261
222- proc hashIdentity * [T: Ordinal | enum ](x: T): Hash {.inline , since : (1 , 3 ).} =
223- # # The identity hash, i.e. `hashIdentity(x) = x`.
224- cast [Hash ](ord (x))
225-
226- when defined (nimIntHash1):
227- proc hash * [T: Ordinal | enum ](x: T): Hash {.inline .} =
228- # # Efficient hashing of integers.
229- cast [Hash ](ord (x))
230- else :
231- proc hash * [T: Ordinal | enum ](x: T): Hash {.inline .} =
232- # # Efficient hashing of integers.
233- hashWangYi1 (uint64 (ord (x)))
234-
235262proc hash * (x: float ): Hash {.inline .} =
236263 # # Efficient hashing of floats.
237264 let y = x + 0.0 # for denormalization
@@ -484,10 +511,9 @@ proc hashIgnoreCase*(sBuf: string, sPos, ePos: int): Hash =
484511 h = h !& ord (c)
485512 result = !$ h
486513
487-
488514proc hash * [T: tuple | object ](x: T): Hash =
489- # # Efficient hashing of tuples and objects .
490- # # There must be a `hash` proc defined for each of the field types .
515+ # # Efficient `hash` overload .
516+ # # `hash` must be defined for each component of `x` .
491517 runnableExamples:
492518 type Obj = object
493519 x: int
0 commit comments