Repository: go-logr/logr (go)

Issue:
Bump min Go version to at least 18?
https://github.com/go-logr/logr/pull/196#discussion_r1283335786

Example: if we use any in code, I get a YCM error: "predeclared any requires go1.18 or later [UnsupportedFeature]"

So maybe we should bump to 18 in go.mod and gh actions tests?

Pull request description:
Bump go versions to 1.18+
Fixes #202

Patch:
diff --git a/.github/workflows/apidiff.yaml b/.github/workflows/apidiff.yaml
index d3dc72b..68391d3 100644
--- a/.github/workflows/apidiff.yaml
+++ b/.github/workflows/apidiff.yaml
@@ -13,7 +13,7 @@ jobs:
       - name: Install Go
         uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1
         with:
-          go-version: 1.18.x
+          go-version: 1.20.x
       - name: Add GOBIN to PATH
         run: echo "PATH=$(go env GOPATH)/bin:$PATH" >>$GITHUB_ENV
       - name: Install dependencies
diff --git a/examples/tab_logger.go b/examples/tab_logger.go
index 1849797..b7335f5 100644
--- a/examples/tab_logger.go
+++ b/examples/tab_logger.go
@@ -28,7 +28,7 @@ import (
 // It's terribly inefficient, and is only a basic example.
 type tabLogSink struct {
 	name      string
-	keyValues map[string]interface{}
+	keyValues map[string]any
 	writer    *tabwriter.Writer
 }
 
@@ -43,7 +43,7 @@ func (_ tabLogSink) Enabled(level int) bool {
 	return true
 }
 
-func (l tabLogSink) Info(level int, msg string, kvs ...interface{}) {
+func (l tabLogSink) Info(level int, msg string, kvs ...any) {
 	fmt.Fprintf(l.writer, "%s\t%s\t", l.name, msg)
 	for k, v := range l.keyValues {
 		fmt.Fprintf(l.writer, "%s: %+v  ", k, v)
@@ -55,7 +55,7 @@ func (l tabLogSink) Info(level int, msg string, kvs ...interface{}) {
 	l.writer.Flush()
 }
 
-func (l tabLogSink) Error(err error, msg string, kvs ...interface{}) {
+func (l tabLogSink) Error(err error, msg string, kvs ...any) {
 	kvs = append(kvs, "error", err)
 	l.Info(0, msg, kvs...)
 }
@@ -68,8 +68,8 @@ func (l tabLogSink) WithName(name string) logr.LogSink {
 	}
 }
 
-func (l tabLogSink) WithValues(kvs ...interface{}) logr.LogSink {
-	newMap := make(map[string]interface{}, len(l.keyValues)+len(kvs)/2)
+func (l tabLogSink) WithValues(kvs ...any) logr.LogSink {
+	newMap := make(map[string]any, len(l.keyValues)+len(kvs)/2)
 	for k, v := range l.keyValues {
 		newMap[k] = v
 	}
diff --git a/examples/usage_example.go b/examples/usage_example.go
index a826d9c..7f736fe 100644
--- a/examples/usage_example.go
+++ b/examples/usage_example.go
@@ -34,17 +34,17 @@ import (
 // (but a bit trickier) to use file-level "base" loggers.
 
 var objectMap = map[string]Object{
-	"obj1": Object{
+	"obj1": {
 		Name:    "obj1",
 		Kind:    "one",
 		Details: 33,
 	},
-	"obj2": Object{
+	"obj2": {
 		Name:    "obj2",
 		Kind:    "two",
 		Details: "hi",
 	},
-	"obj3": Object{
+	"obj3": {
 		Name:    "obj3",
 		Kind:    "one",
 		Details: 1,
@@ -54,7 +54,7 @@ var objectMap = map[string]Object{
 type Object struct {
 	Name    string
 	Kind    string
-	Details interface{}
+	Details any
 }
 
 type Client struct {
diff --git a/funcr/funcr.go b/funcr/funcr.go
index 75a4ee8..12e5807 100644
--- a/funcr/funcr.go
+++ b/funcr/funcr.go
@@ -116,17 +116,17 @@ type Options struct {
 	// Equivalent hooks are offered for key-value pairs saved via
 	// logr.Logger.WithValues or Formatter.AddValues (see RenderValuesHook) and
 	// for user-provided pairs (see RenderArgsHook).
-	RenderBuiltinsHook func(kvList []interface{}) []interface{}
+	RenderBuiltinsHook func(kvList []any) []any
 
 	// RenderValuesHook is the same as RenderBuiltinsHook, except that it is
 	// only called for key-value pairs saved via logr.Logger.WithValues.  See
 	// RenderBuiltinsHook for more details.
-	RenderValuesHook func(kvList []interface{}) []interface{}
+	RenderValuesHook func(kvList []any) []any
 
 	// RenderArgsHook is the same as RenderBuiltinsHook, except that it is only
 	// called for key-value pairs passed directly to Info and Error.  See
 	// RenderBuiltinsHook for more details.
-	RenderArgsHook func(kvList []interface{}) []interface{}
+	RenderArgsHook func(kvList []any) []any
 
 	// MaxLogDepth tells funcr how many levels of nested fields (e.g. a struct
 	// that contains a struct, etc.) it may log.  Every time it finds a struct,
@@ -163,7 +163,7 @@ func (l fnlogger) WithName(name string) logr.LogSink {
 	return &l
 }
 
-func (l fnlogger) WithValues(kvList ...interface{}) logr.LogSink {
+func (l fnlogger) WithValues(kvList ...any) logr.LogSink {
 	l.Formatter.AddValues(kvList)
 	return &l
 }
@@ -173,12 +173,12 @@ func (l fnlogger) WithCallDepth(depth int) logr.LogSink {
 	return &l
 }
 
-func (l fnlogger) Info(level int, msg string, kvList ...interface{}) {
+func (l fnlogger) Info(level int, msg string, kvList ...any) {
 	prefix, args := l.FormatInfo(level, msg, kvList)
 	l.write(prefix, args)
 }
 
-func (l fnlogger) Error(err error, msg string, kvList ...interface{}) {
+func (l fnlogger) Error(err error, msg string, kvList ...any) {
 	prefix, args := l.FormatError(err, msg, kvList)
 	l.write(prefix, args)
 }
@@ -229,7 +229,7 @@ func newFormatter(opts Options, outfmt outputFormat) Formatter {
 type Formatter struct {
 	outputFormat outputFormat
 	prefix       string
-	values       []interface{}
+	values       []any
 	valuesStr    string
 	depth        int
 	opts         *Options
@@ -246,10 +246,10 @@ const (
 )
 
 // PseudoStruct is a list of key-value pairs that gets logged as a struct.
-type PseudoStruct []interface{}
+type PseudoStruct []any
 
 // render produces a log line, ready to use.
-func (f Formatter) render(builtins, args []interface{}) string {
+func (f Formatter) render(builtins, args []any) string {
 	// Empirically bytes.Buffer is faster than strings.Builder for this.
 	buf := bytes.NewBuffer(make([]byte, 0, 1024))
 	if f.outputFormat == outputJSON {
@@ -292,7 +292,7 @@ func (f Formatter) render(builtins, args []interface{}) string {
 // This function returns a potentially modified version of kvList, which
 // ensures that there is a value for every key (adding a value if needed) and
 // that each key is a string (substituting a key if needed).
-func (f Formatter) flatten(buf *bytes.Buffer, kvList []interface{}, continuing bool, escapeKeys bool) []interface{} {
+func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, continuing bool, escapeKeys bool) []any {
 	// This logic overlaps with sanitize() but saves one type-cast per key,
 	// which can be measurable.
 	if len(kvList)%2 != 0 {
@@ -334,7 +334,7 @@ func (f Formatter) flatten(buf *bytes.Buffer, kvList []interface{}, continuing b
 	return kvList
 }
 
-func (f Formatter) pretty(value interface{}) string {
+func (f Formatter) pretty(value any) string {
 	return f.prettyWithFlags(value, 0, 0)
 }
 
@@ -343,7 +343,7 @@ const (
 )
 
 // TODO: This is not fast. Most of the overhead goes here.
-func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) string {
+func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string {
 	if depth > f.opts.MaxLogDepth {
 		return `"<max-log-depth-exceeded>"`
 	}
@@ -614,7 +614,7 @@ func isEmpty(v reflect.Value) bool {
 	return false
 }
 
-func invokeMarshaler(m logr.Marshaler) (ret interface{}) {
+func invokeMarshaler(m logr.Marshaler) (ret any) {
 	defer func() {
 		if r := recover(); r != nil {
 			ret = fmt.Sprintf("<panic: %s>", r)
@@ -675,12 +675,12 @@ func (f Formatter) caller() Caller {
 
 const noValue = "<no-value>"
 
-func (f Formatter) nonStringKey(v interface{}) string {
+func (f Formatter) nonStringKey(v any) string {
 	return fmt.Sprintf("<non-string-key: %s>", f.snippet(v))
 }
 
 // snippet produces a short snippet string of an arbitrary value.
-func (f Formatter) snippet(v interface{}) string {
+func (f Formatter) snippet(v any) string {
 	const snipLen = 16
 
 	snip := f.pretty(v)
@@ -693,7 +693,7 @@ func (f Formatter) snippet(v interface{}) string {
 // sanitize ensures that a list of key-value pairs has a value for every key
 // (adding a value if needed) and that each key is a string (substituting a key
 // if needed).
-func (f Formatter) sanitize(kvList []interface{}) []interface{} {
+func (f Formatter) sanitize(kvList []any) []any {
 	if len(kvList)%2 != 0 {
 		kvList = append(kvList, noValue)
 	}
@@ -727,8 +727,8 @@ func (f Formatter) GetDepth() int {
 // FormatInfo renders an Info log message into strings.  The prefix will be
 // empty when no names were set (via AddNames), or when the output is
 // configured for JSON.
-func (f Formatter) FormatInfo(level int, msg string, kvList []interface{}) (prefix, argsStr string) {
-	args := make([]interface{}, 0, 64) // using a constant here impacts perf
+func (f Formatter) FormatInfo(level int, msg string, kvList []any) (prefix, argsStr string) {
+	args := make([]any, 0, 64) // using a constant here impacts perf
 	prefix = f.prefix
 	if f.outputFormat == outputJSON {
 		args = append(args, "logger", prefix)
@@ -747,8 +747,8 @@ func (f Formatter) FormatInfo(level int, msg string, kvList []interface{}) (pref
 // FormatError renders an Error log message into strings.  The prefix will be
 // empty when no names were set (via AddNames), or when the output is
 // configured for JSON.
-func (f Formatter) FormatError(err error, msg string, kvList []interface{}) (prefix, argsStr string) {
-	args := make([]interface{}, 0, 64) // using a constant here impacts perf
+func (f Formatter) FormatError(err error, msg string, kvList []any) (prefix, argsStr string) {
+	args := make([]any, 0, 64) // using a constant here impacts perf
 	prefix = f.prefix
 	if f.outputFormat == outputJSON {
 		args = append(args, "logger", prefix)
@@ -761,7 +761,7 @@ func (f Formatter) FormatError(err error, msg string, kvList []interface{}) (pre
 		args = append(args, "caller", f.caller())
 	}
 	args = append(args, "msg", msg)
-	var loggableErr interface{}
+	var loggableErr any
 	if err != nil {
 		loggableErr = err.Error()
 	}
@@ -781,7 +781,7 @@ func (f *Formatter) AddName(name string) {
 
 // AddValues adds key-value pairs to the set of saved values to be logged with
 // each log line.
-func (f *Formatter) AddValues(kvList []interface{}) {
+func (f *Formatter) AddValues(kvList []any) {
 	// Three slice args forces a copy.
 	n := len(f.values)
 	f.values = append(f.values[:n:n], kvList...)
diff --git a/go.mod b/go.mod
index 7baec9b..b4f52a4 100644
--- a/go.mod
+++ b/go.mod
@@ -1,3 +1,3 @@
 module github.com/go-logr/logr
 
-go 1.16
+go 1.18
diff --git a/logr.go b/logr.go
index cc8d955..7dd08a6 100644
--- a/logr.go
+++ b/logr.go
@@ -267,7 +267,7 @@ func (l Logger) Enabled() bool {
 // line.  The key/value pairs can then be used to add additional variable
 // information.  The key/value pairs must alternate string keys and arbitrary
 // values.
-func (l Logger) Info(msg string, keysAndValues ...interface{}) {
+func (l Logger) Info(msg string, keysAndValues ...any) {
 	if l.sink == nil {
 		return
 	}
@@ -289,7 +289,7 @@ func (l Logger) Info(msg string, keysAndValues ...interface{}) {
 // while the err argument should be used to attach the actual error that
 // triggered this log line, if present. The err parameter is optional
 // and nil may be passed instead of an error instance.
-func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) {
+func (l Logger) Error(err error, msg string, keysAndValues ...any) {
 	if l.sink == nil {
 		return
 	}
@@ -316,7 +316,7 @@ func (l Logger) V(level int) Logger {
 
 // WithValues returns a new Logger instance with additional key/value pairs.
 // See Info for documentation on how key/value pairs work.
-func (l Logger) WithValues(keysAndValues ...interface{}) Logger {
+func (l Logger) WithValues(keysAndValues ...any) Logger {
 	if l.sink == nil {
 		return l
 	}
@@ -467,15 +467,15 @@ type LogSink interface {
 	// The level argument is provided for optional logging.  This method will
 	// only be called when Enabled(level) is true. See Logger.Info for more
 	// details.
-	Info(level int, msg string, keysAndValues ...interface{})
+	Info(level int, msg string, keysAndValues ...any)
 
 	// Error logs an error, with the given message and key/value pairs as
 	// context.  See Logger.Error for more details.
-	Error(err error, msg string, keysAndValues ...interface{})
+	Error(err error, msg string, keysAndValues ...any)
 
 	// WithValues returns a new LogSink with additional key/value pairs.  See
 	// Logger.WithValues for more details.
-	WithValues(keysAndValues ...interface{}) LogSink
+	WithValues(keysAndValues ...any) LogSink
 
 	// WithName returns a new LogSink with the specified name appended.  See
 	// Logger.WithName for more details.
@@ -546,5 +546,5 @@ type Marshaler interface {
 	//     with exported fields
 	//
 	// It may return any value of any type.
-	MarshalLog() interface{}
+	MarshalLog() any
 }


Test patch:
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 4d17f2f..51af420 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -9,7 +9,7 @@ jobs:
   test:
     strategy:
       matrix:
-        version: [ '1.15', '1.16', '1.17', '1.18' ]
+        version: [ '1.18', '1.19', '1.20', '1.21.0-rc.4' ]
         platform: [ ubuntu-latest, macos-latest, windows-latest ]
     runs-on: ${{ matrix.platform }}
     steps:
diff --git a/benchmark/benchmark_test.go b/benchmark/benchmark_test.go
index 83e77a0..090e3ce 100644
--- a/benchmark/benchmark_test.go
+++ b/benchmark/benchmark_test.go
@@ -130,7 +130,7 @@ func doErrorValue(b *testing.B, log logr.Logger) {
 
 type Tmarshaler struct{ s string }
 
-func (t Tmarshaler) MarshalLog() interface{} {
+func (t Tmarshaler) MarshalLog() any {
 	return t.s
 }
 
diff --git a/example_marshaler_secret_test.go b/example_marshaler_secret_test.go
index 1e59af3..39ac4a4 100644
--- a/example_marshaler_secret_test.go
+++ b/example_marshaler_secret_test.go
@@ -27,7 +27,7 @@ type ComplexObjectRef struct {
 	Secret    string
 }
 
-func (ref ComplexObjectRef) MarshalLog() interface{} {
+func (ref ComplexObjectRef) MarshalLog() any {
 	return struct {
 		Name, Namespace string
 	}{
diff --git a/example_marshaler_test.go b/example_marshaler_test.go
index 12fdaf3..f9cd00a 100644
--- a/example_marshaler_test.go
+++ b/example_marshaler_test.go
@@ -33,7 +33,7 @@ func (ref ObjectRef) String() string {
 	return ref.Name
 }
 
-func (ref ObjectRef) MarshalLog() interface{} {
+func (ref ObjectRef) MarshalLog() any {
 	// We implement fmt.Stringer for non-structured logging, but we want the
 	// raw struct when using structured logs.  Some logr implementations call
 	// String if it is present, so we want to convert this struct to something
diff --git a/funcr/example_formatter_test.go b/funcr/example_formatter_test.go
index e5ed6ec..474e510 100644
--- a/funcr/example_formatter_test.go
+++ b/funcr/example_formatter_test.go
@@ -45,7 +45,7 @@ func (l stdoutlogger) WithName(name string) logr.LogSink {
 	return &l
 }
 
-func (l stdoutlogger) WithValues(kvList ...interface{}) logr.LogSink {
+func (l stdoutlogger) WithValues(kvList ...any) logr.LogSink {
 	l.Formatter.AddValues(kvList)
 	return &l
 }
@@ -55,12 +55,12 @@ func (l stdoutlogger) WithCallDepth(depth int) logr.LogSink {
 	return &l
 }
 
-func (l stdoutlogger) Info(level int, msg string, kvList ...interface{}) {
+func (l stdoutlogger) Info(level int, msg string, kvList ...any) {
 	prefix, args := l.FormatInfo(level, msg, kvList)
 	l.write("INFO", prefix, args)
 }
 
-func (l stdoutlogger) Error(err error, msg string, kvList ...interface{}) {
+func (l stdoutlogger) Error(err error, msg string, kvList ...any) {
 	prefix, args := l.FormatError(err, msg, kvList)
 	l.write("ERROR", prefix, args)
 }
diff --git a/funcr/example_test.go b/funcr/example_test.go
index 53373a2..4918154 100644
--- a/funcr/example_test.go
+++ b/funcr/example_test.go
@@ -74,7 +74,7 @@ func ExampleOptions() {
 
 func ExampleOptions_renderHooks() {
 	// prefix all builtin keys with "log:"
-	prefixSpecialKeys := func(kvList []interface{}) []interface{} {
+	prefixSpecialKeys := func(kvList []any) []any {
 		for i := 0; i < len(kvList); i += 2 {
 			k, _ := kvList[i].(string)
 			kvList[i] = "log:" + k
@@ -83,8 +83,8 @@ func ExampleOptions_renderHooks() {
 	}
 
 	// present saved values as a single JSON object
-	valuesAsObject := func(kvList []interface{}) []interface{} {
-		return []interface{}{"labels", funcr.PseudoStruct(kvList)}
+	valuesAsObject := func(kvList []any) []any {
+		return []any{"labels", funcr.PseudoStruct(kvList)}
 	}
 
 	var log logr.Logger = funcr.NewJSON(
@@ -104,7 +104,7 @@ func ExamplePseudoStruct() {
 	var log logr.Logger = funcr.NewJSON(
 		func(obj string) { fmt.Println(obj) },
 		funcr.Options{})
-	kv := []interface{}{
+	kv := []any{
 		"field1", 12345,
 		"field2", true,
 	}
diff --git a/funcr/funcr_test.go b/funcr/funcr_test.go
index 1165320..b3a6f70 100644
--- a/funcr/funcr_test.go
+++ b/funcr/funcr_test.go
@@ -54,7 +54,7 @@ func (p pointErr) MarshalText() ([]byte, error) {
 // Logging this should result in the MarshalLog() value.
 type Tmarshaler struct{ val string }
 
-func (t Tmarshaler) MarshalLog() interface{} {
+func (t Tmarshaler) MarshalLog() any {
 	return struct{ Inner string }{"I am a logr.Marshaler"}
 }
 
@@ -69,7 +69,7 @@ func (t Tmarshaler) Error() string {
 // Logging this should result in a panic.
 type Tmarshalerpanic struct{ val string }
 
-func (t Tmarshalerpanic) MarshalLog() interface{} {
+func (t Tmarshalerpanic) MarshalLog() any {
 	panic("Tmarshalerpanic")
 }
 
@@ -251,7 +251,7 @@ func TestPretty(t *testing.T) {
 	}
 
 	cases := []struct {
-		val interface{}
+		val any
 		exp string // used in cases where JSON can't handle it
 	}{{
 		val: "strval",
@@ -402,11 +402,11 @@ func TestPretty(t *testing.T) {
 		val: struct {
 			A *int
 			B *int
-			C interface{}
-			D interface{}
+			C any
+			D any
 		}{
 			B: ptrint(1),
-			D: interface{}(2),
+			D: any(2),
 		},
 	}, {
 		val: Tmarshaler{"foobar"},
@@ -678,7 +678,7 @@ func TestPretty(t *testing.T) {
 	}
 }
 
-func makeKV(args ...interface{}) []interface{} {
+func makeKV(args ...any) []any {
 	return args
 }
 
@@ -694,9 +694,9 @@ func TestRender(t *testing.T) {
 
 	testCases := []struct {
 		name       string
-		builtins   []interface{}
-		values     []interface{}
-		args       []interface{}
+		builtins   []any
+		values     []any
+		args       []any
 		expectKV   string
 		expectJSON string
 	}{{
@@ -705,9 +705,9 @@ func TestRender(t *testing.T) {
 		expectJSON: "{}",
 	}, {
 		name:       "empty",
-		builtins:   []interface{}{},
-		values:     []interface{}{},
-		args:       []interface{}{},
+		builtins:   []any{},
+		values:     []any{},
+		args:       []any{},
 		expectKV:   "",
 		expectJSON: "{}",
 	}, {
@@ -800,12 +800,12 @@ func TestRender(t *testing.T) {
 func TestSanitize(t *testing.T) {
 	testCases := []struct {
 		name   string
-		kv     []interface{}
-		expect []interface{}
+		kv     []any
+		expect []any
 	}{{
 		name:   "empty",
-		kv:     []interface{}{},
-		expect: []interface{}{},
+		kv:     []any{},
+		expect: []any{},
 	}, {
 		name:   "already sane",
 		kv:     makeKV("int", 1, "str", "ABC", "bool", true),
@@ -877,7 +877,7 @@ func (c *capture) Func(prefix, args string) {
 func TestInfo(t *testing.T) {
 	testCases := []struct {
 		name       string
-		args       []interface{}
+		args       []any
 		expectKV   string
 		expectJSON string
 	}{{
@@ -1028,7 +1028,7 @@ func TestInfoWithCaller(t *testing.T) {
 func TestError(t *testing.T) {
 	testCases := []struct {
 		name       string
-		args       []interface{}
+		args       []any
 		expectKV   string
 		expectJSON string
 	}{{
@@ -1118,7 +1118,7 @@ func TestInfoWithName(t *testing.T) {
 	testCases := []struct {
 		name       string
 		names      []string
-		args       []interface{}
+		args       []any
 		expectKV   string
 		expectJSON string
 	}{{
@@ -1165,7 +1165,7 @@ func TestErrorWithName(t *testing.T) {
 	testCases := []struct {
 		name       string
 		names      []string
-		args       []interface{}
+		args       []any
 		expectKV   string
 		expectJSON string
 	}{{
@@ -1211,8 +1211,8 @@ func TestErrorWithName(t *testing.T) {
 func TestInfoWithValues(t *testing.T) {
 	testCases := []struct {
 		name       string
-		values     []interface{}
-		args       []interface{}
+		values     []any
+		args       []any
 		expectKV   string
 		expectJSON string
 	}{{
@@ -1266,8 +1266,8 @@ func TestInfoWithValues(t *testing.T) {
 func TestErrorWithValues(t *testing.T) {
 	testCases := []struct {
 		name       string
-		values     []interface{}
-		args       []interface{}
+		values     []any
+		args       []any
 		expectKV   string
 		expectJSON string
 	}{{
diff --git a/logr_test.go b/logr_test.go
index 00ecf98..5613ae6 100644
--- a/logr_test.go
+++ b/logr_test.go
@@ -28,9 +28,9 @@ import (
 type testLogSink struct {
 	fnInit       func(ri RuntimeInfo)
 	fnEnabled    func(lvl int) bool
-	fnInfo       func(lvl int, msg string, kv ...interface{})
-	fnError      func(err error, msg string, kv ...interface{})
-	fnWithValues func(kv ...interface{})
+	fnInfo       func(lvl int, msg string, kv ...any)
+	fnError      func(err error, msg string, kv ...any)
+	fnWithValues func(kv ...any)
 	fnWithName   func(name string)
 }
 
@@ -49,19 +49,19 @@ func (l *testLogSink) Enabled(lvl int) bool {
 	return false
 }
 
-func (l *testLogSink) Info(lvl int, msg string, kv ...interface{}) {
+func (l *testLogSink) Info(lvl int, msg string, kv ...any) {
 	if l.fnInfo != nil {
 		l.fnInfo(lvl, msg, kv...)
 	}
 }
 
-func (l *testLogSink) Error(err error, msg string, kv ...interface{}) {
+func (l *testLogSink) Error(err error, msg string, kv ...any) {
 	if l.fnError != nil {
 		l.fnError(err, msg, kv...)
 	}
 }
 
-func (l *testLogSink) WithValues(kv ...interface{}) LogSink {
+func (l *testLogSink) WithValues(kv ...any) LogSink {
 	if l.fnWithValues != nil {
 		l.fnWithValues(kv...)
 	}
@@ -148,10 +148,10 @@ func TestError(t *testing.T) {
 	calledError := 0
 	errInput := fmt.Errorf("error")
 	msgInput := "msg"
-	kvInput := []interface{}{0, 1, 2}
+	kvInput := []any{0, 1, 2}
 
 	sink := &testLogSink{}
-	sink.fnError = func(err error, msg string, kv ...interface{}) {
+	sink.fnError = func(err error, msg string, kv ...any) {
 		calledError++
 		if err != errInput {
 			t.Errorf("unexpected err input, got %v", err)
@@ -197,14 +197,14 @@ func TestInfo(t *testing.T) {
 	calledInfo := 0
 	lvlInput := 0
 	msgInput := "msg"
-	kvInput := []interface{}{0, 1, 2}
+	kvInput := []any{0, 1, 2}
 
 	sink := &testLogSink{}
 	sink.fnEnabled = func(lvl int) bool {
 		calledEnabled++
 		return lvl < 100
 	}
-	sink.fnInfo = func(lvl int, msg string, kv ...interface{}) {
+	sink.fnInfo = func(lvl int, msg string, kv ...any) {
 		calledInfo++
 		if lvl != lvlInput {
 			t.Errorf("unexpected lvl input, got %v", lvl)
@@ -265,10 +265,10 @@ func TestInfo(t *testing.T) {
 
 func TestWithValues(t *testing.T) {
 	calledWithValues := 0
-	kvInput := []interface{}{"zero", 0, "one", 1, "two", 2}
+	kvInput := []any{"zero", 0, "one", 1, "two", 2}
 
 	sink := &testLogSink{}
-	sink.fnWithValues = func(kv ...interface{}) {
+	sink.fnWithValues = func(kv ...any) {
 		calledWithValues++
 		if !reflect.DeepEqual(kv, kvInput) {
 			t.Errorf("unexpected kv input, got %v", kv)
diff --git a/testr/testr.go b/testr/testr.go
index 2772b49..5eabe2b 100644
--- a/testr/testr.go
+++ b/testr/testr.go
@@ -54,7 +54,7 @@ func NewWithOptions(t *testing.T, opts Options) logr.Logger {
 // TestingT is an interface wrapper around testing.T, testing.B and testing.F.
 type TestingT interface {
 	Helper()
-	Log(args ...interface{})
+	Log(args ...any)
 }
 
 // NewWithInterface returns a logr.Logger that prints through a
@@ -92,7 +92,7 @@ type UnderlierInterface interface {
 }
 
 // Info logging implementation shared between testLogger and testLoggerInterface.
-func logInfo(t TestingT, formatInfo func(int, string, []interface{}) (string, string), level int, msg string, kvList ...interface{}) {
+func logInfo(t TestingT, formatInfo func(int, string, []any) (string, string), level int, msg string, kvList ...any) {
 	prefix, args := formatInfo(level, msg, kvList)
 	t.Helper()
 	if prefix != "" {
@@ -102,7 +102,7 @@ func logInfo(t TestingT, formatInfo func(int, string, []interface{}) (string, st
 }
 
 // Error logging implementation shared between testLogger and testLoggerInterface.
-func logError(t TestingT, formatError func(error, string, []interface{}) (string, string), err error, msg string, kvList ...interface{}) {
+func logError(t TestingT, formatError func(error, string, []any) (string, string), err error, msg string, kvList ...any) {
 	prefix, args := formatError(err, msg, kvList)
 	t.Helper()
 	if prefix != "" {
@@ -134,7 +134,7 @@ func (l testloggerInterface) WithName(name string) logr.LogSink {
 	return &l
 }
 
-func (l testloggerInterface) WithValues(kvList ...interface{}) logr.LogSink {
+func (l testloggerInterface) WithValues(kvList ...any) logr.LogSink {
 	l.Formatter.AddValues(kvList)
 	return &l
 }
@@ -143,12 +143,12 @@ func (l testloggerInterface) GetCallStackHelper() func() {
 	return l.t.Helper
 }
 
-func (l testloggerInterface) Info(level int, msg string, kvList ...interface{}) {
+func (l testloggerInterface) Info(level int, msg string, kvList ...any) {
 	l.t.Helper()
 	logInfo(l.t, l.FormatInfo, level, msg, kvList...)
 }
 
-func (l testloggerInterface) Error(err error, msg string, kvList ...interface{}) {
+func (l testloggerInterface) Error(err error, msg string, kvList ...any) {
 	l.t.Helper()
 	logError(l.t, l.FormatError, err, msg, kvList...)
 }