Go: runtime: map lookup of non-comparable value doesn't panic

Created on 7 Feb 2018  ·  5Comments  ·  Source: golang/go

https://play.golang.org/p/ZLieXU_3vuB

This program prints 0:

package main

func main() {
    var m map[interface{}]int
    var k []int

    println(m[k])
}

The Go spec says:

If the key type is an interface type, these comparison operators must be defined for the dynamic key values; failure will cause a run-time panic.

It seems unspecified what exactly "failure" means, but my interpretation is that using a non-comparable value like k above in the expression m[k] should constitute as "failure".

/cc @griesemer @ianlancetaylor @randall77

FrozenDueToAge NeedsFix

Most helpful comment

Same for delete

package main

func main() {
     var m = map[interface{}]int{}
     var i interface{} = []int{}
     delete(m, i)
}

All 5 comments

Oh, the issue is because of this short-circuit in mapaccess1:

    if h == nil || h.count == 0 {
            return unsafe.Pointer(&zeroVal[0])
    }

If m is a non-nil non-empty map, the index expression panics.

We could call alg.hash(key, 0) or alg.equal(k, k) inside that short circuit. I'm not sure if this would be worth fixing though. It seems very unlikely that anyone is depending on this behavior.

alg.hash(k, 0) would be better, because it'll give the same "hash of unhashable type" panic that non-empty maps would raise; alg.equal(k, k) would instead raise "comparing uncomparable type".

That said, I'd expect hash lookups into nil and empty maps might be pretty common, so it'd be desirable to skip the hash operation if possible? The compiler could add another flag to maptype (like reflexivekey) to indicate whether key values are always comparable.

Same for delete

package main

func main() {
     var m = map[interface{}]int{}
     var i interface{} = []int{}
     delete(m, i)
}

Change https://golang.org/cl/155918 mentions this issue: runtime: panic on uncomparable map key, even if map is empty

Was this page helpful?
0 / 5 - 0 ratings