Open
Description
What version of Ristretto are you using?
v1.0.0
What version of Go are you using?
go version go1.23.1 darwin/arm64
Have you tried reproducing the issue with the latest release?
Yes
What is the hardware spec (RAM, CPU, OS)?
N/A
What steps will reproduce the bug?
package main
import (
"github.com/dgraph-io/ristretto"
"github.com/dgraph-io/ristretto/z"
)
type MyKey string
func foo() {
_, _ = ristretto.NewCache[MyKey, any](&ristretto.Config[MyKey, any]{
KeyToHash: func(key MyKey) (uint64, uint64) { return z.KeyToHash(string(key)) },
})
}
Expected behavior and actual result.
Expected: Go should compile this code.
Actual:
MyKey does not satisfy ristretto.Key (possibly missing ~ for string in ristretto.Key)
Additional information
The type definition of z.Key
only allows direct primitive types.
package z
type Key interface {
uint64 | string | []byte | byte | int | int32 | uint32 | int64
}
Ideally, the generic constraint would allow new type wrappers over those already supported in the Key interface.
The rationale is to allow application code to use stronger types than string
. This helps distinguish between string types like UserID
and InvoiceID
.
I suspect the problem with supporting new types is there's no way to detect the underlying type efficiently. You can't do it with a type-switch. However, when the user provides a KeyToHash
function, we don't need the generic constraint.
https://go.dev/play/p/fxOWPUemRz0
package main
import "fmt"
type WrappedInt int
func do(i interface{}) {
switch v := i.(type) {
case int:
fmt.Printf("direct int: %v\n", v)
default:
switch v2 := v.(type) {
case int:
fmt.Printf("wrapped int: %v\n", v2)
default:
fmt.Printf("unknown type: %T\n", v2)
}
}
}
func main() {
do(21) // direct int: 23
do(WrappedInt(123)) // unknown type: main.WrappedInt
}
Proposal
- When calling NewCache, check that either KeyToHash is provided or that the type is an implicitly supported key type. Then relax the Key constraint back to
any
.