runtime: panic on uncomparable map key, even if map is empty

Reorg map flags a bit so we don't need any extra space for the extra flag.

Fixes #23734

Change-Id: I436812156240ae90de53d0943fe1aabf3ea37417
Reviewed-on: https://go-review.googlesource.com/c/155918
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Keith Randall 2018-12-28 14:34:48 -08:00 committed by Keith Randall
parent 14bdcc76fd
commit ed15e82413
5 changed files with 172 additions and 60 deletions

View file

@ -1095,6 +1095,28 @@ func needkeyupdate(t *types.Type) bool {
}
}
// hashMightPanic reports whether the hash of a map key of type t might panic.
func hashMightPanic(t *types.Type) bool {
switch t.Etype {
case TINTER:
return true
case TARRAY:
return hashMightPanic(t.Elem())
case TSTRUCT:
for _, t1 := range t.Fields().Slice() {
if hashMightPanic(t1.Type) {
return true
}
}
return false
default:
return false
}
}
// formalType replaces byte and rune aliases with real types.
// They've been separate internally to make error messages
// better, but we have to merge them in the reflect tables.
@ -1257,25 +1279,33 @@ func dtypesym(t *types.Type) *obj.LSym {
ot = dsymptr(lsym, ot, s1, 0)
ot = dsymptr(lsym, ot, s2, 0)
ot = dsymptr(lsym, ot, s3, 0)
var flags uint32
// Note: flags must match maptype accessors in ../../../../runtime/type.go
// and maptype builder in ../../../../reflect/type.go:MapOf.
if t.Key().Width > MAXKEYSIZE {
ot = duint8(lsym, ot, uint8(Widthptr))
ot = duint8(lsym, ot, 1) // indirect
flags |= 1 // indirect key
} else {
ot = duint8(lsym, ot, uint8(t.Key().Width))
ot = duint8(lsym, ot, 0) // not indirect
}
if t.Elem().Width > MAXVALSIZE {
ot = duint8(lsym, ot, uint8(Widthptr))
ot = duint8(lsym, ot, 1) // indirect
flags |= 2 // indirect value
} else {
ot = duint8(lsym, ot, uint8(t.Elem().Width))
ot = duint8(lsym, ot, 0) // not indirect
}
ot = duint16(lsym, ot, uint16(bmap(t).Width))
ot = duint8(lsym, ot, uint8(obj.Bool2int(isreflexive(t.Key()))))
ot = duint8(lsym, ot, uint8(obj.Bool2int(needkeyupdate(t.Key()))))
if isreflexive(t.Key()) {
flags |= 4 // reflexive key
}
if needkeyupdate(t.Key()) {
flags |= 8 // need key update
}
if hashMightPanic(t.Key()) {
flags |= 16 // hash might panic
}
ot = duint32(lsym, ot, flags)
ot = dextratype(lsym, ot, t, 0)
case TPTR: