* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
This CL is only cut-and-paste, moving code around.
Moving it in a separate CL should simplify the diffs in later CLs.
There are three patterns here.
1. A function like
func (v Value) M() (...) {
return v.panicIfNot(K).(*kValue).M()
}
becomes
func (v Value) M() (...) {
vv := v.panicIfNot(K).(*kValue)
// body of (*kValue).M, s/v./vv./g
}
2. A function like
func (v Value) M() (...) {
return v.panicIfNots(kList).(mer).M()
}
becomes
func (v Value) M() (...) {
switch vv := v.panicIfNots(kList).(type) {
case *k1Value:
// body of (*k1Value).M, s/v./vv./g
case *k2Value:
// body of (*k2Value).M, s/v./vv./g
...
}
panic("not reached")
}
3. The rewrite of Value.Set follows 2, but each case
is built from the bodies of (*kValue).SetValue and (*kValue).Set.
func (v *kValue) SetValue(x Value) {
v.Set(x.panicIfNot(K).(*kValue)
}
func (v *kValue) Set(x *kValue) {
... body
}
becomes, in the switch from 2,
case *kValue:
xx := x.panicIfNot(K).(*kValue)
... body, s/v./vv./g; s/x./xx./g
R=r
CC=golang-dev
https://golang.org/cl/4398044
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
This change makes it possible to take the address of a
struct field or slice element in order to call a method that
requires a pointer receiver.
Existing code that uses the Value.Addr method will have
to change (as gob does in this CL) to call UnsafeAddr instead.
R=r, rog
CC=golang-dev
https://golang.org/cl/4239052
The pointer will eventually let us find *T given T.
This CL just makes room for it, always storing a zero.
R=r, r2
CC=golang-dev
https://golang.org/cl/4221046
It was observed that the interface was generic enough
that several other types implemented it too.
Fixes#1530.
R=rsc
CC=golang-dev
https://golang.org/cl/4169063
cc: same
runtime: test cc alignment (required moving #define of offsetof to runtime.h)
fix bug260
Fixes#482.
Fixes#609.
R=ken2, r
CC=golang-dev
https://golang.org/cl/3563042
I have written a tool to verify Printf calls, and although it's not
ready to be reviewed yet it's already uncovered a spate of problems
in the repository. I'm sending this CL to break the changes into
pieces; as the tool improves it will find more, I'm sure.
R=rsc
CC=golang-dev
https://golang.org/cl/3427043
Cleaner, but also results in a 25%+ performance improvement for Get()/SetValue() on my machine.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/3072041
value (through unsafe means) without having a reflect.Type
of type *interface{} (pointer to interface). This is needed to make
gob able to handle interface values by a method analogous to
the way it handles maps.
R=rsc
CC=golang-dev
https://golang.org/cl/2597041
(Argument: For any *PtrValue p, it should
always be possible to do: p.PointTo(p.Elem()),
even if p.Elem() is nil.)
Fixes#1028.
R=rsc
CC=golang-dev, r
https://golang.org/cl/1938044
note that sortmain.go has been run through hg gofmt;
only the formatting of the day initializers changed.
i'm happy to revert that formatting if you'd prefer.
stop on error in doc/progs/run
R=r
CC=golang-dev
https://golang.org/cl/850041
bonus: type switch now detects multiple uses of identical interface types.
bonus: interface types are now order-independent, following the spec.
R=ken2
CC=golang-dev
https://golang.org/cl/194053
- use an interface {Get()}
- implement Get for maps, slices
- for slices, retrieves the address of the end of the array, which will give the
same value for every slice of the same array.
R=rsc
CC=golang-dev
https://golang.org/cl/179129
parsing and printing to new syntax.
Use -oldparser to parse the old syntax,
use -oldprinter to print the old syntax.
2) Change default gofmt formatting settings
to use tabs for indentation only and to use
spaces for alignment. This will make the code
alignment insensitive to an editor's tabwidth.
Use -spaces=false to use tabs for alignment.
3) Manually changed src/exp/parser/parser_test.go
so that it doesn't try to parse the parser's
source files using the old syntax (they have
new syntax now).
4) gofmt -w src misc test/bench
4th set of files.
R=rsc
CC=golang-dev
https://golang.org/cl/180049
the bash scripts and makefiles for building go didn't take into account
the fact $GOROOT / $GOBIN could both be directories containing whitespaces,
and was not possible to build it in such a situation.
this commit adjusts the various makefiles/scripts to make it aware of that
possibility, and now it builds successfully when using a path with whitespaces
as well.
Fixes#115.
R=rsc, dsymonds1
https://golang.org/cl/157067
reflect is a little more detailed than some because it affords an opportunity
to explain how to approach the library.
R=gri, rsc
CC=go-dev
http://go/go-review/1026026
- enabled for function declarations (not just function literals)
- applied gofmt -w $GOROOT/src
(look for instance at src/pkg/debug/elf/elf.go)
R=r, rsc
CC=go-dev
http://go/go-review/1026006
whole-package compilation. new Makefiles,
tests now in separate package
bytes
flag
fmt
io
math
once
os
reflect
strconv
sync
time
utf8
delete import "xxx" in package xxx.
inside package xxx, xxx is not declared
anymore so s/xxx.//g
delete file and package level forward declarations.
note the new internal_test.go and sync
and strconv to provide public access to
internals during testing. the installed version
of the package omits that file and thus does
not open the internals to all clients.
R=r
OCL=33065
CL=33097
tests to use new reflect interface.
also make tests a real gotest.
depends on CL 31107
R=r
DELTA=582 (56 added, 194 deleted, 332 changed)
OCL=31108
CL=31279
* use structs instead of interfaces
* compiler lays out data structures ahead of time,
so no more parsing of strings.
* unified reflect data structures with interface
runtime data structures.
* richer data structures should enable reflection
on chans and maps, but not implemented here.
R=r,iant
DELTA=1179 (1179 added, 0 deleted, 0 changed)
OCL=31107
CL=31213