compiler: alignof [0]func() = 1
In the go protobuf code, a pattern is used to statically prevent comparable structs by embedding: ``` type DoNotCompare [0]func() type message struct { DoNotCompare data *uint32 } ``` Previously, sizezof(message{}) is 2 words large, but it only needs to be 1 byte. Making it be 1 byte allows protobufs to compile slightly more (though not all the way).
Этот коммит содержится в:
родитель
995e815b63
коммит
4c7449efe5
2 изменённых файлов: 16 добавлений и 0 удалений
|
@ -21,6 +21,12 @@ func (s *stdSizes) Alignof(T types.Type) int64 {
|
||||||
// of alignment of the elements and fields, respectively.
|
// of alignment of the elements and fields, respectively.
|
||||||
switch t := T.Underlying().(type) {
|
switch t := T.Underlying().(type) {
|
||||||
case *types.Array:
|
case *types.Array:
|
||||||
|
if t.Len() == 0 {
|
||||||
|
// 0-sized arrays, always have 0 size.
|
||||||
|
// And from the spec, should have an alignment of _at least_ 1
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
// spec: "For a variable x of array type: unsafe.Alignof(x)
|
// spec: "For a variable x of array type: unsafe.Alignof(x)
|
||||||
// is the same as unsafe.Alignof(x[0]), but at least 1."
|
// is the same as unsafe.Alignof(x[0]), but at least 1."
|
||||||
return s.Alignof(t.Elem())
|
return s.Alignof(t.Elem())
|
||||||
|
|
10
testdata/reflect.go
предоставленный
10
testdata/reflect.go
предоставленный
|
@ -52,6 +52,12 @@ func main() {
|
||||||
println("\nvalues of interfaces")
|
println("\nvalues of interfaces")
|
||||||
var zeroSlice []byte
|
var zeroSlice []byte
|
||||||
var zeroFunc func()
|
var zeroFunc func()
|
||||||
|
// by embedding a 0-array func type in your struct, it is not comparable
|
||||||
|
type doNotCompare [0]func()
|
||||||
|
type notComparable struct {
|
||||||
|
doNotCompare
|
||||||
|
data *int32
|
||||||
|
}
|
||||||
var zeroMap map[string]int
|
var zeroMap map[string]int
|
||||||
var zeroChan chan int
|
var zeroChan chan int
|
||||||
n := 42
|
n := 42
|
||||||
|
@ -170,6 +176,10 @@ func main() {
|
||||||
assertSize(reflect.TypeOf(new(int)).Size() == unsafe.Sizeof(new(int)), "*int")
|
assertSize(reflect.TypeOf(new(int)).Size() == unsafe.Sizeof(new(int)), "*int")
|
||||||
assertSize(reflect.TypeOf(zeroFunc).Size() == unsafe.Sizeof(zeroFunc), "func()")
|
assertSize(reflect.TypeOf(zeroFunc).Size() == unsafe.Sizeof(zeroFunc), "func()")
|
||||||
|
|
||||||
|
// make sure embedding a zero-sized "not comparable" struct does not add size to a struct
|
||||||
|
assertSize(reflect.TypeOf(doNotCompare{}).Size() == unsafe.Sizeof(doNotCompare{}), "[0]func()")
|
||||||
|
assertSize(unsafe.Sizeof(notComparable{}) == unsafe.Sizeof((*int32)(nil)), "struct{[0]func(); *int32}")
|
||||||
|
|
||||||
// Test that offset is correctly calculated.
|
// Test that offset is correctly calculated.
|
||||||
// This doesn't just test reflect but also (indirectly) that unsafe.Alignof
|
// This doesn't just test reflect but also (indirectly) that unsafe.Alignof
|
||||||
// works correctly.
|
// works correctly.
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче