'go 1.18 generic compile error when use maps.Copy on map with struct key
I implemented a Set based on generic, and everything ok until i use struct as Set element instead of base type. I got an compliation error.
go version: go version go1.18 windows/amd64
Below code is failed to complie in function AddSet.
package main
import (
"fmt"
"golang.org/x/exp/maps"
)
type Key struct {
A, B int
}
func main() {
s := SetOf(
Key{1, 1},
Key{2, 2},
Key{3, 3},
)
s.AddSet(SetOf(
Key{3, 3},
Key{4, 4},
Key{5, 5},
))
fmt.Println(s)
}
type Set[T comparable] map[T]struct{}
func SetOf[T comparable](vs ...T) Set[T] {
s := Set[T]{}
for _, v := range vs {
s[v] = struct{}{}
}
return s
}
func (s Set[T]) AddSet(another Set[T]) {
maps.Copy(s, another)
}
when run it:
> go run .\main.go
# command-line-arguments
.\main.go:19:10: cannot use &.autotmp_29 (type *struct { A int; B int }) as type *Key in argument to runtime.mapassign
<autogenerated>:1: cannot use &.autotmp_12 (type *struct { A int; B int }) as type *Key in argument to runtime.mapassign
- if
Keyonly has 1 field, it can be compiled successful. - if i use
for v := range another { s[v]=struct{}{} }, it can be compiled successful.
i think it's strange, can someone explain please?
Solution 1:[1]
It looks like this compiler error. It is fixed in Go 1.19 and backported to Go 1.18.2.
If you are on an older version, I'd recommend simply forgoing the maps package and doing things by hand, as you already tried. It's just a simple loop:
func (s Set[T]) AddSet(another Set[T]) {
for k := range another {
s[k] = struct{}{}
}
}
@icza's comment of explicitly converting the named map type to its underlying type also works:
maps.Copy(map[T]struct{}(s), another)
In case you use functions that expect more than one map type parameter (with the same constraints), as maps.Equal or maps.EqualFunc, you have to convert both arguments:
func (s Set[T]) Compare(another Set[T]) bool {
// signature is Equal[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool
return maps.Equal(map[T]struct{}(s), map[T]struct{}(another))
}
It seems the crash was reproduced also with parametrized map types instantiated with arrays with len >= 2.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
