Go

Why does slices.Clone have the signature func Clone[S ~[]E, E any](s S) S instead of func Clone[E any](s []E) []E?

Question 129HardGo 1.22 to 1.25

The goal is to preserve the caller's named slice type. With []E in and []E out, a named type like type IDs []int comes back as a plain []int, and its methods are lost. With S ~[]E, S is inferred as IDs, and constraint type inference derives E = int from the core type.

type IDs []int

func (ids IDs) Sum() (t int) {
    for _, v := range ids {
        t += v
    }
    return
}

func CloneBad[E any](s []E) []E { return append([]E(nil), s...) }

func main() {
    ids := IDs{1, 2, 3}
    fmt.Println(slices.Clone(ids).Sum()) // 6: returns IDs
    // CloneBad(ids).Sum()               // compile error: []int has no method Sum
    var back IDs = CloneBad(ids)         // assignable ([]int is unnamed), but needs a variable
    _ = back
}

The same pattern appears across slices and maps: func Keys[Map ~map[K]V, K comparable, V any]. If your API takes and returns a collection, use S ~[]E. Interviewers are checking that you understand both constraint type inference and API ergonomics.

More on Generics

All 36 Generics questions