Skip to content

[BUG]: Cannot use new type of string as z.Key param #400

Open
@jschaf

Description

@jschaf

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

  1. 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.

Metadata

Metadata

Assignees

Labels

kind/bugSomething is broken.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions