On 2/16/2022 2:43 PM, Ian Lance Taylor wrote:
On Tue, Feb 15, 2022 at 2:49 PM Blackgreen<bg.theroc...@gmail.com>  wrote:
I came across this stack overflow question:
https://stackoverflow.com/questions/71131665/generics-pass-map-with-derived-types

The OP attempted to pass different maps into this code:

func equal[M1, M2 ~map[K]V, K, V comparable](m1 M1, m2 M2) bool { if len(m1) != 
len(m2) { return false } for k, v1 := range m1 { if v2, ok := m2[k]; !ok || v1 
!= v2 { return false } } return true }

It is clear to me why this doesn't work. However, I was studying possible fixes 
for this function. Here's a 
playground:https://gotipplay.golang.org/p/NPpau1G0Hqp

My first attempt was based on differentiating the K and V type params and came 
up with this:

func equal[M1 ~map[K1]V1, M2 ~map[K2]V2, K1, K2 ~uint32, V1, V2 ~string](m1 M1, 
m2 M2) bool {
         if len(m1) != len(m2) {
                 return false
         }
         for k, v1 := range m1 {
                 if v2, ok := m2[K2(k)]; !ok || V2(v1) != v2 {
                         return false
                 }
         }
         return true
}

I thought this should work, because now it's possible to infer K1 and K2 from M1 and M2 
respectively, and the approximate constraints allow conversion in the function body. But 
it still doesn't compile with error "K2 does not match uint32".

Instead, this works, even though K1 and K2 are defined the same way:

func equalFixed[K1, K2 ~uint32, V1, V2 ~string](m1 map[K1]V1, m2 map[K2]V2) 
bool {
}

By reading the Go 1.18 language specs, my intuition is that the first attempt fails due 
to the so-called "adjusted core type" of the constraint ~uint32, though I'm not 
100% sure of what's going on.
Can you folks confirm my intuition and/or provide some pointers?

This looks like a bug in type inference to me.  I may be missing
something but I don't see how it could be producing that error.  Would
you mind opening a bug report athttps://go.dev/issue?  Thanks.  Note
that this may not be fixed in the upcoming 1.18 release, as we are
trying to be careful about type inference.

Ian


I changed the block below to use alias declarations instead and it worked OK for me:


type (
    someNumericID uint32
    someStringID   string
)

to this:


type (
    someNumericID = uint32
    someStringID  = string
)

https://gotipplay.golang.org/p/diU2c31TC1b

The Go Programming Language Specification - Go 1.18 Draft - The Go Programming Language (golang.org) <https://tip.golang.org/ref/spec#Alias_declarations>




--
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/fb67989c-15e9-edf8-43cb-c76a97b5a572%40gmail.com.

Reply via email to