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:
parent
5e9beacd77
commit
9333b8f458
|
@ -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
|
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).
|
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
|
SAFETY
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,12 @@ func Test(t *testing.T) {
|
||||||
"testdata/F.template",
|
"testdata/F.template",
|
||||||
"testdata/F1.go",
|
"testdata/F1.go",
|
||||||
|
|
||||||
|
"testdata/G.template",
|
||||||
|
"testdata/G1.go",
|
||||||
|
|
||||||
|
"testdata/H.template",
|
||||||
|
"testdata/H1.go",
|
||||||
|
|
||||||
"testdata/bad_type.template",
|
"testdata/bad_type.template",
|
||||||
"testdata/no_before.template",
|
"testdata/no_before.template",
|
||||||
"testdata/no_after_return.template",
|
"testdata/no_after_return.template",
|
||||||
|
|
|
@ -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.
|
// 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 {
|
if tr.verbose {
|
||||||
fmt.Fprintf(os.Stderr, "%s not assignable to %s\n", yt, xobj.Type())
|
fmt.Fprintf(os.Stderr, "%s not assignable to %s\n", yt, xobj.Type())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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} }
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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} }
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue