https://play.golang.org/p/2JNMRctSmRr
The above program prints "3\n2\n", but it should print "3\n0\n". (And it does if K is changed to a "fast" map key type like uint32.)
The problem is that, for "slow" map key types, order.go rewrites
into
ktmp := k
defer mapdelete(m, &ktmp)
but we never mark ktmp as escaping (because escape analysis happens earlier). So in the playground example above, this loop:
for _, k := range ks {
defer delete(m, k)
}
is effectively rewritten into:
var ktmp K
for _, k := range ks {
ktmp = k
defer delete(m, &ktmp)
}
So when the defers finally execute at function return, they all try to delete the last k value.
A similar issue affects go delete(m, k), but there's no way to use this construct in legitimate code.
https://play.golang.org/p/2JNMRctSmRr
The above program prints
"3\n2\n", but it should print"3\n0\n". (And it does ifKis changed to a "fast" map key type like uint32.)The problem is that, for "slow" map key types, order.go rewrites
into
but we never mark ktmp as escaping (because escape analysis happens earlier). So in the playground example above, this loop:
is effectively rewritten into:
So when the defers finally execute at function return, they all try to delete the last k value.
A similar issue affects
go delete(m, k), but there's no way to use this construct in legitimate code.