From 2a5864fcfb595b4ee9a7607f1beb25778cf64c6e Mon Sep 17 00:00:00 2001 From: Spencer Nelson Date: Wed, 22 Mar 2017 14:59:57 -0400 Subject: [PATCH] x/tools/go/ssa: Accept struct conversions that ignore tags This is now allowed in go1.8. Fixes golang/go#19646. Change-Id: Iece4fd2a881144bdbe841e0a26ba4348d6b8828e Reviewed-on: https://go-review.googlesource.com/38452 Reviewed-by: Alan Donovan Run-TryBot: Alan Donovan TryBot-Result: Gobot Gobot --- go/ssa/emit.go | 2 +- go/ssa/identical.go | 7 +++++++ go/ssa/identical_17.go | 7 +++++++ go/ssa/identical_test.go | 9 +++++++++ go/ssa/source_test.go | 6 +++++- go/ssa/testdata/structconv.go | 24 ++++++++++++++++++++++++ 6 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 go/ssa/identical.go create mode 100644 go/ssa/identical_17.go create mode 100644 go/ssa/identical_test.go create mode 100644 go/ssa/testdata/structconv.go diff --git a/go/ssa/emit.go b/go/ssa/emit.go index 66107621..1036988a 100644 --- a/go/ssa/emit.go +++ b/go/ssa/emit.go @@ -147,7 +147,7 @@ func emitCompare(f *Function, op token.Token, x, y Value, pos token.Pos) Value { // func isValuePreserving(ut_src, ut_dst types.Type) bool { // Identical underlying types? - if types.Identical(ut_dst, ut_src) { + if structTypesIdentical(ut_dst, ut_src) { return true } diff --git a/go/ssa/identical.go b/go/ssa/identical.go new file mode 100644 index 00000000..53cbee10 --- /dev/null +++ b/go/ssa/identical.go @@ -0,0 +1,7 @@ +// +build go1.8 + +package ssa + +import "go/types" + +var structTypesIdentical = types.IdenticalIgnoreTags diff --git a/go/ssa/identical_17.go b/go/ssa/identical_17.go new file mode 100644 index 00000000..da89d333 --- /dev/null +++ b/go/ssa/identical_17.go @@ -0,0 +1,7 @@ +// +build !go1.8 + +package ssa + +import "go/types" + +var structTypesIdentical = types.Identical diff --git a/go/ssa/identical_test.go b/go/ssa/identical_test.go new file mode 100644 index 00000000..404693dc --- /dev/null +++ b/go/ssa/identical_test.go @@ -0,0 +1,9 @@ +//+build go1.8 + +package ssa_test + +import "testing" + +func TestValueForExprStructConv(t *testing.T) { + testValueForExpr(t, "testdata/structconv.go") +} diff --git a/go/ssa/source_test.go b/go/ssa/source_test.go index 85b55c21..43051f80 100644 --- a/go/ssa/source_test.go +++ b/go/ssa/source_test.go @@ -194,12 +194,16 @@ func checkVarValue(t *testing.T, prog *ssa.Program, pkg *ssa.Package, ref []ast. // Ensure that, in debug mode, we can determine the ssa.Value // corresponding to every ast.Expr. func TestValueForExpr(t *testing.T) { + testValueForExpr(t, "testdata/valueforexpr.go") +} + +func testValueForExpr(t *testing.T, testfile string) { if runtime.GOOS == "android" { t.Skipf("no testdata dir on %s", runtime.GOOS) } conf := loader.Config{ParserMode: parser.ParseComments} - f, err := conf.ParseFile("testdata/valueforexpr.go", nil) + f, err := conf.ParseFile(testfile, nil) if err != nil { t.Error(err) return diff --git a/go/ssa/testdata/structconv.go b/go/ssa/testdata/structconv.go new file mode 100644 index 00000000..31264691 --- /dev/null +++ b/go/ssa/testdata/structconv.go @@ -0,0 +1,24 @@ +//+build ignore + +// This file is the input to TestValueForExprStructConv in identical_test.go, +// which uses the same framework as TestValueForExpr does in source_test.go. +// +// In Go 1.8, struct conversions are permitted even when the struct types have +// different tags. This wasn't permitted in earlier versions of Go, so this file +// exists separately from valueforexpr.go to just test this behavior in Go 1.8 +// and later. + +package main + +type t1 struct { + x int +} +type t2 struct { + x int `tag` +} + +func main() { + var tv1 t1 + var tv2 t2 = /*@ChangeType*/ (t2(tv1)) + _ = tv2 +}