1
0
mirror of https://github.com/golang/go synced 2024-11-18 09:04:49 -07:00

refactor/eg: fix crash while unifying wildcard with KeyValueExpr, which has no type

+ tests.

Fixes issue golang/go#10923

Change-Id: I0813cdfbb447bbd9f579bb1998b355a3179a7e79
Reviewed-on: https://go-review.googlesource.com/10332
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
Alan Donovan 2015-05-22 15:53:13 -04:00
parent 5e9beacd77
commit 9333b8f458
9 changed files with 87 additions and 1 deletions

View File

@ -84,6 +84,9 @@ a wildcard may have any integer type, for example.
It is not possible to replace an expression by one of a different
type, even in contexts where this is legal, such as x in fmt.Print(x).
The struct literals T{x} and T{K: x} cannot both be matched by a single
template.
SAFETY

View File

@ -64,6 +64,12 @@ func Test(t *testing.T) {
"testdata/F.template",
"testdata/F1.go",
"testdata/G.template",
"testdata/G1.go",
"testdata/H.template",
"testdata/H1.go",
"testdata/bad_type.template",
"testdata/no_before.template",
"testdata/no_after_return.template",

View File

@ -185,7 +185,17 @@ func (tr *Transformer) matchWildcard(xobj *types.Var, y ast.Expr) bool {
}
// Check that y is assignable to the declared type of the param.
if yt := tr.info.TypeOf(y); !types.AssignableTo(yt, xobj.Type()) {
yt := tr.info.TypeOf(y)
if yt == nil {
// y has no type.
// Perhaps it is an *ast.Ellipsis in [...]T{}, or
// an *ast.KeyValueExpr in T{k: v}.
// Clearly these pseudo-expressions cannot match a
// wildcard, but it would nice if we had a way to ignore
// the difference between T{v} and T{k:v} for structs.
return false
}
if !types.AssignableTo(yt, xobj.Type()) {
if tr.verbose {
fmt.Fprintf(os.Stderr, "%s not assignable to %s\n", yt, xobj.Type())
}

10
refactor/eg/testdata/G.template vendored Normal file
View File

@ -0,0 +1,10 @@
package templates
import (
"go/ast" // defines many unencapsulated structs
"go/token"
)
func before(from, to token.Pos) ast.BadExpr { return ast.BadExpr{From: from, To: to} }
func after(from, to token.Pos) ast.BadExpr { return ast.BadExpr{from, to} }

12
refactor/eg/testdata/G1.go vendored Normal file
View File

@ -0,0 +1,12 @@
// +build ignore
package G1
import "go/ast"
func example() {
_ = ast.BadExpr{From: 123, To: 456} // match
_ = ast.BadExpr{123, 456} // no match
_ = ast.BadExpr{From: 123} // no match
_ = ast.BadExpr{To: 456} // no match
}

12
refactor/eg/testdata/G1.golden vendored Normal file
View File

@ -0,0 +1,12 @@
// +build ignore
package G1
import "go/ast"
func example() {
_ = ast.BadExpr{123, 456} // match
_ = ast.BadExpr{123, 456} // no match
_ = ast.BadExpr{From: 123} // no match
_ = ast.BadExpr{To: 456} // no match
}

9
refactor/eg/testdata/H.template vendored Normal file
View File

@ -0,0 +1,9 @@
package templates
import (
"go/ast" // defines many unencapsulated structs
"go/token"
)
func before(from, to token.Pos) ast.BadExpr { return ast.BadExpr{from, to} }
func after(from, to token.Pos) ast.BadExpr { return ast.BadExpr{From: from, To: to} }

12
refactor/eg/testdata/H1.go vendored Normal file
View File

@ -0,0 +1,12 @@
// +build ignore
package H1
import "go/ast"
func example() {
_ = ast.BadExpr{From: 123, To: 456} // no match
_ = ast.BadExpr{123, 456} // match
_ = ast.BadExpr{From: 123} // no match
_ = ast.BadExpr{To: 456} // no match
}

12
refactor/eg/testdata/H1.golden vendored Normal file
View File

@ -0,0 +1,12 @@
// +build ignore
package H1
import "go/ast"
func example() {
_ = ast.BadExpr{From: 123, To: 456} // no match
_ = ast.BadExpr{From: 123, To: 456} // match
_ = ast.BadExpr{From: 123} // no match
_ = ast.BadExpr{To: 456} // no match
}