diff --git a/src/cmd/gofmt/simplify.go b/src/cmd/gofmt/simplify.go index d9afc0e7b4c..9d3cb91439e 100644 --- a/src/cmd/gofmt/simplify.go +++ b/src/cmd/gofmt/simplify.go @@ -6,6 +6,7 @@ package main import ( "go/ast" + "go/token" "reflect" ) @@ -26,10 +27,12 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor { if eltType != nil { typ := reflect.ValueOf(eltType) - for _, x := range outer.Elts { + for i, x := range outer.Elts { + px := &outer.Elts[i] // look at value of indexed/named elements if t, ok := x.(*ast.KeyValueExpr); ok { x = t.Value + px = &t.Value } simplify(x) // if the element is a composite literal and its literal type @@ -40,6 +43,19 @@ func (s *simplifier) Visit(node ast.Node) ast.Visitor { inner.Type = nil } } + // if the outer literal's element type is a pointer type *T + // and the element is & of a composite literal of type T, + // the inner &T may be omitted. + if ptr, ok := eltType.(*ast.StarExpr); ok { + if addr, ok := x.(*ast.UnaryExpr); ok && addr.Op == token.AND { + if inner, ok := addr.X.(*ast.CompositeLit); ok { + if match(nil, reflect.ValueOf(ptr.X), reflect.ValueOf(inner.Type)) { + inner.Type = nil // drop T + *px = inner // drop & + } + } + } + } } // node was simplified - stop walk (there are no subnodes to simplify) diff --git a/src/cmd/gofmt/testdata/composites.golden b/src/cmd/gofmt/testdata/composites.golden index 1fd5847c11e..b2825e732aa 100644 --- a/src/cmd/gofmt/testdata/composites.golden +++ b/src/cmd/gofmt/testdata/composites.golden @@ -102,3 +102,101 @@ var pieces4 = []Piece{ {2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, {3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, } + +var _ = [42]*T{ + {}, + {1, 2}, + {3, 4}, +} + +var _ = [...]*T{ + {}, + {1, 2}, + {3, 4}, +} + +var _ = []*T{ + {}, + {1, 2}, + {3, 4}, +} + +var _ = []*T{ + {}, + 10: {1, 2}, + 20: {3, 4}, +} + +var _ = []*struct { + x, y int +}{ + {}, + 10: {1, 2}, + 20: {3, 4}, +} + +var _ = []interface{}{ + &T{}, + 10: &T{1, 2}, + 20: &T{3, 4}, +} + +var _ = []*[]int{ + {}, + {1, 2}, + {3, 4}, +} + +var _ = []*[]int{ + (&[]int{}), + (&[]int{1, 2}), + {3, 4}, +} + +var _ = []*[]*[]int{ + {}, + { + {}, + {0, 1, 2, 3}, + {4, 5}, + }, +} + +var _ = map[string]*T{ + "foo": {}, + "bar": {1, 2}, + "bal": {3, 4}, +} + +var _ = map[string]*struct { + x, y int +}{ + "foo": {}, + "bar": {1, 2}, + "bal": {3, 4}, +} + +var _ = map[string]interface{}{ + "foo": &T{}, + "bar": &T{1, 2}, + "bal": &T{3, 4}, +} + +var _ = map[string]*[]int{ + "foo": {}, + "bar": {1, 2}, + "bal": {3, 4}, +} + +var _ = map[string]*[]int{ + "foo": (&[]int{}), + "bar": (&[]int{1, 2}), + "bal": {3, 4}, +} + +var pieces4 = []*Piece{ + {0, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, + {1, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, + {2, 0, Point{4, 1}, []Point{{0, 0}, {1, 0}, {1, 0}, {1, 0}}, nil, nil}, + {3, 0, Point{1, 4}, []Point{{0, 0}, {0, 1}, {0, 1}, {0, 1}}, nil, nil}, +} diff --git a/src/cmd/gofmt/testdata/composites.input b/src/cmd/gofmt/testdata/composites.input index 15afd9e5c4f..7210dafc96c 100644 --- a/src/cmd/gofmt/testdata/composites.input +++ b/src/cmd/gofmt/testdata/composites.input @@ -102,3 +102,101 @@ var pieces4 = []Piece{ Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, } + +var _ = [42]*T{ + &T{}, + &T{1, 2}, + &T{3, 4}, +} + +var _ = [...]*T{ + &T{}, + &T{1, 2}, + &T{3, 4}, +} + +var _ = []*T{ + &T{}, + &T{1, 2}, + &T{3, 4}, +} + +var _ = []*T{ + &T{}, + 10: &T{1, 2}, + 20: &T{3, 4}, +} + +var _ = []*struct { + x, y int +}{ + &struct{ x, y int }{}, + 10: &struct{ x, y int }{1, 2}, + 20: &struct{ x, y int }{3, 4}, +} + +var _ = []interface{}{ + &T{}, + 10: &T{1, 2}, + 20: &T{3, 4}, +} + +var _ = []*[]int{ + &[]int{}, + &[]int{1, 2}, + &[]int{3, 4}, +} + +var _ = []*[]int{ + (&[]int{}), + (&[]int{1, 2}), + &[]int{3, 4}, +} + +var _ = []*[]*[]int{ + &[]*[]int{}, + &[]*[]int{ + &[]int{}, + &[]int{0, 1, 2, 3}, + &[]int{4, 5}, + }, +} + +var _ = map[string]*T{ + "foo": &T{}, + "bar": &T{1, 2}, + "bal": &T{3, 4}, +} + +var _ = map[string]*struct { + x, y int +}{ + "foo": &struct{ x, y int }{}, + "bar": &struct{ x, y int }{1, 2}, + "bal": &struct{ x, y int }{3, 4}, +} + +var _ = map[string]interface{}{ + "foo": &T{}, + "bar": &T{1, 2}, + "bal": &T{3, 4}, +} + +var _ = map[string]*[]int{ + "foo": &[]int{}, + "bar": &[]int{1, 2}, + "bal": &[]int{3, 4}, +} + +var _ = map[string]*[]int{ + "foo": (&[]int{}), + "bar": (&[]int{1, 2}), + "bal": &[]int{3, 4}, +} + +var pieces4 = []*Piece{ + &Piece{0, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, + &Piece{1, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, + &Piece{2, 0, Point{4, 1}, []Point{Point{0, 0}, Point{1, 0}, Point{1, 0}, Point{1, 0}}, nil, nil}, + &Piece{3, 0, Point{1, 4}, []Point{Point{0, 0}, Point{0, 1}, Point{0, 1}, Point{0, 1}}, nil, nil}, +}