diff --git a/refactor/eg/eg.go b/refactor/eg/eg.go index 7d37ec6e6f..a609255568 100644 --- a/refactor/eg/eg.go +++ b/refactor/eg/eg.go @@ -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 diff --git a/refactor/eg/eg_test.go b/refactor/eg/eg_test.go index c44256c501..3c10bef859 100644 --- a/refactor/eg/eg_test.go +++ b/refactor/eg/eg_test.go @@ -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", diff --git a/refactor/eg/match.go b/refactor/eg/match.go index 298a258f31..d8590d4f7c 100644 --- a/refactor/eg/match.go +++ b/refactor/eg/match.go @@ -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()) } diff --git a/refactor/eg/testdata/G.template b/refactor/eg/testdata/G.template new file mode 100644 index 0000000000..69d84fe9f4 --- /dev/null +++ b/refactor/eg/testdata/G.template @@ -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} } + \ No newline at end of file diff --git a/refactor/eg/testdata/G1.go b/refactor/eg/testdata/G1.go new file mode 100644 index 0000000000..07aaff916c --- /dev/null +++ b/refactor/eg/testdata/G1.go @@ -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 +} diff --git a/refactor/eg/testdata/G1.golden b/refactor/eg/testdata/G1.golden new file mode 100644 index 0000000000..c93c53fc3b --- /dev/null +++ b/refactor/eg/testdata/G1.golden @@ -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 +} diff --git a/refactor/eg/testdata/H.template b/refactor/eg/testdata/H.template new file mode 100644 index 0000000000..fa6f802c8a --- /dev/null +++ b/refactor/eg/testdata/H.template @@ -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} } diff --git a/refactor/eg/testdata/H1.go b/refactor/eg/testdata/H1.go new file mode 100644 index 0000000000..ef4291c18a --- /dev/null +++ b/refactor/eg/testdata/H1.go @@ -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 +} diff --git a/refactor/eg/testdata/H1.golden b/refactor/eg/testdata/H1.golden new file mode 100644 index 0000000000..a1e5961264 --- /dev/null +++ b/refactor/eg/testdata/H1.golden @@ -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 +}