Skip to content

Commit ffa9983

Browse files
committed
cmd/compile/internal/types2: review of api_test.go
The changes between (equivalent, and reviewed) go/types/api_test.go and api_test.go can be seen by comparing patchset 1 and 2. The actual changes are removing the "// UNREVIEWED" marker, the addition of the TestConvertibleTo and TestAssignableTo tests, and adjustments to test prefixes (genericPkg, brokenPkg to be in line with go/types). There are several differences to go/types/api_test.go: - use of syntax rather than go/ast package - use of the parseSrc helper function - TestTypesInfo test entries reflect different handling of untyped nil - TestInferredInfo is (for go1.17) in another file controlled by a build constraint in go/types - TestSelection test is currently skipped (types2 position information is not accurate enough) - TestScopeLookupParent doesn't have access to a scanner and instead relies on syntax.CommentsDo. - Broken packages are assumed to contain generic code for the tests. Change-Id: Ic14e6fb9d6bef5416df39e465b5994de76f84097 Reviewed-on: https://go-review.googlesource.com/c/go/+/304131 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
1 parent 34ef294 commit ffa9983

File tree

2 files changed

+103
-51
lines changed

2 files changed

+103
-51
lines changed

src/cmd/compile/internal/types2/api_test.go

Lines changed: 101 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// UNREVIEWED
21
// Copyright 2013 The Go Authors. All rights reserved.
32
// Use of this source code is governed by a BSD-style
43
// license that can be found in the LICENSE file.
@@ -22,9 +21,21 @@ func unimplemented() {
2221
panic("unimplemented")
2322
}
2423

24+
// genericPkg is a source prefix for packages that contain generic code.
25+
const genericPkg = "package generic_"
26+
27+
// brokenPkg is a source prefix for packages that are not expected to parse
28+
// or type-check cleanly. They are always parsed assuming that they contain
29+
// generic code.
30+
const brokenPkg = "package broken_"
31+
2532
func parseSrc(path, src string) (*syntax.File, error) {
33+
var mode syntax.Mode
34+
if strings.HasPrefix(src, genericPkg) || strings.HasPrefix(src, brokenPkg) {
35+
mode = syntax.AllowGenerics
36+
}
2637
errh := func(error) {} // dummy error handler so that parsing continues in presence of errors
27-
return syntax.Parse(syntax.NewFileBase(path), strings.NewReader(src), errh, nil, syntax.AllowGenerics)
38+
return syntax.Parse(syntax.NewFileBase(path), strings.NewReader(src), errh, nil, mode)
2839
}
2940

3041
func pkgFor(path, source string, info *Info) (*Package, error) {
@@ -182,9 +193,6 @@ func TestValuesInfo(t *testing.T) {
182193
}
183194

184195
func TestTypesInfo(t *testing.T) {
185-
// Test sources that are not expected to typecheck must start with the broken prefix.
186-
const broken = "package broken_"
187-
188196
var tests = []struct {
189197
src string
190198
expr string // expression
@@ -315,37 +323,37 @@ func TestTypesInfo(t *testing.T) {
315323
},
316324

317325
// tests for broken code that doesn't parse or type-check
318-
{broken + `x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`},
319-
{broken + `x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`},
320-
{broken + `x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a, f: b,}}`, `b`, `string`},
321-
{broken + `x3; var x = panic("");`, `panic`, `func(interface{})`},
326+
{brokenPkg + `x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`},
327+
{brokenPkg + `x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`},
328+
{brokenPkg + `x2; func _() { var a, b string; type x struct {f string}; z := &x{f: a, f: b,}}`, `b`, `string`},
329+
{brokenPkg + `x3; var x = panic("");`, `panic`, `func(interface{})`},
322330
{`package x4; func _() { panic("") }`, `panic`, `func(interface{})`},
323-
{broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`},
331+
{brokenPkg + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`},
324332

325333
// parameterized functions
326-
{`package p0; func f[T any](T); var _ = f[int]`, `f`, `func[T₁ interface{}](T₁)`},
327-
{`package p1; func f[T any](T); var _ = f[int]`, `f[int]`, `func(int)`},
328-
{`package p2; func f[T any](T); func _() { f(42) }`, `f`, `func[T₁ interface{}](T₁)`},
329-
{`package p3; func f[T any](T); func _() { f(42) }`, `f(42)`, `()`},
334+
{genericPkg + `p0; func f[T any](T); var _ = f[int]`, `f`, `func[T₁ interface{}](T₁)`},
335+
{genericPkg + `p1; func f[T any](T); var _ = f[int]`, `f[int]`, `func(int)`},
336+
{genericPkg + `p2; func f[T any](T); func _() { f(42) }`, `f`, `func[T₁ interface{}](T₁)`},
337+
{genericPkg + `p3; func f[T any](T); func _() { f(42) }`, `f(42)`, `()`},
330338

331339
// type parameters
332-
{`package t0; type t[] int; var _ t`, `t`, `t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t
333-
{`package t1; type t[P any] int; var _ t[int]`, `t`, `t1.t[P₁ interface{}]`},
334-
{`package t2; type t[P interface{}] int; var _ t[int]`, `t`, `t2.t[P₁ interface{}]`},
335-
{`package t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `t3.t[P₁, Q₂ interface{}]`},
336-
{broken + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[P₁, Q₂ interface{m()}]`},
340+
{genericPkg + `t0; type t[] int; var _ t`, `t`, `generic_t0.t`}, // t[] is a syntax error that is ignored in this test in favor of t
341+
{genericPkg + `t1; type t[P any] int; var _ t[int]`, `t`, `generic_t1.t[P₁ interface{}]`},
342+
{genericPkg + `t2; type t[P interface{}] int; var _ t[int]`, `t`, `generic_t2.t[P₁ interface{}]`},
343+
{genericPkg + `t3; type t[P, Q interface{}] int; var _ t[int, int]`, `t`, `generic_t3.t[P₁, Q₂ interface{}]`},
344+
{brokenPkg + `t4; type t[P, Q interface{ m() }] int; var _ t[int, int]`, `t`, `broken_t4.t[P₁, Q₂ interface{m()}]`},
337345

338346
// instantiated types must be sanitized
339-
{`package g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `g0.t[int]`},
347+
{genericPkg + `g0; type t[P any] int; var x struct{ f t[int] }; var _ = x.f`, `x.f`, `generic_g0.t[int]`},
340348

341349
// issue 45096
342-
{`package issue45096; func _[T interface{ type int8, int16, int32 }](x T) { _ = x < 0 }`, `0`, `T₁`},
350+
{genericPkg + `issue45096; func _[T interface{ type int8, int16, int32 }](x T) { _ = x < 0 }`, `0`, `T₁`},
343351
}
344352

345353
for _, test := range tests {
346354
info := Info{Types: make(map[syntax.Expr]TypeAndValue)}
347355
var name string
348-
if strings.HasPrefix(test.src, broken) {
356+
if strings.HasPrefix(test.src, brokenPkg) {
349357
var err error
350358
name, err = mayTypecheck(t, "TypesInfo", test.src, &info)
351359
if err == nil {
@@ -383,103 +391,103 @@ func TestInferredInfo(t *testing.T) {
383391
targs []string
384392
sig string
385393
}{
386-
{`package p0; func f[T any](T); func _() { f(42) }`,
394+
{genericPkg + `p0; func f[T any](T); func _() { f(42) }`,
387395
`f`,
388396
[]string{`int`},
389397
`func(int)`,
390398
},
391-
{`package p1; func f[T any](T) T; func _() { f('@') }`,
399+
{genericPkg + `p1; func f[T any](T) T; func _() { f('@') }`,
392400
`f`,
393401
[]string{`rune`},
394402
`func(rune) rune`,
395403
},
396-
{`package p2; func f[T any](...T) T; func _() { f(0i) }`,
404+
{genericPkg + `p2; func f[T any](...T) T; func _() { f(0i) }`,
397405
`f`,
398406
[]string{`complex128`},
399407
`func(...complex128) complex128`,
400408
},
401-
{`package p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`,
409+
{genericPkg + `p3; func f[A, B, C any](A, *B, []C); func _() { f(1.2, new(string), []byte{}) }`,
402410
`f`,
403411
[]string{`float64`, `string`, `byte`},
404412
`func(float64, *string, []byte)`,
405413
},
406-
{`package p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`,
414+
{genericPkg + `p4; func f[A, B any](A, *B, ...[]B); func _() { f(1.2, new(byte)) }`,
407415
`f`,
408416
[]string{`float64`, `byte`},
409417
`func(float64, *byte, ...[]byte)`,
410418
},
411419

412420
// we don't know how to translate these but we can type-check them
413-
{`package q0; type T struct{}; func (T) m[P any](P); func _(x T) { x.m(42) }`,
421+
{genericPkg + `q0; type T struct{}; func (T) m[P any](P); func _(x T) { x.m(42) }`,
414422
`x.m`,
415423
[]string{`int`},
416424
`func(int)`,
417425
},
418-
{`package q1; type T struct{}; func (T) m[P any](P) P; func _(x T) { x.m(42) }`,
426+
{genericPkg + `q1; type T struct{}; func (T) m[P any](P) P; func _(x T) { x.m(42) }`,
419427
`x.m`,
420428
[]string{`int`},
421429
`func(int) int`,
422430
},
423-
{`package q2; type T struct{}; func (T) m[P any](...P) P; func _(x T) { x.m(42) }`,
431+
{genericPkg + `q2; type T struct{}; func (T) m[P any](...P) P; func _(x T) { x.m(42) }`,
424432
`x.m`,
425433
[]string{`int`},
426434
`func(...int) int`,
427435
},
428-
{`package q3; type T struct{}; func (T) m[A, B, C any](A, *B, []C); func _(x T) { x.m(1.2, new(string), []byte{}) }`,
436+
{genericPkg + `q3; type T struct{}; func (T) m[A, B, C any](A, *B, []C); func _(x T) { x.m(1.2, new(string), []byte{}) }`,
429437
`x.m`,
430438
[]string{`float64`, `string`, `byte`},
431439
`func(float64, *string, []byte)`,
432440
},
433-
{`package q4; type T struct{}; func (T) m[A, B any](A, *B, ...[]B); func _(x T) { x.m(1.2, new(byte)) }`,
441+
{genericPkg + `q4; type T struct{}; func (T) m[A, B any](A, *B, ...[]B); func _(x T) { x.m(1.2, new(byte)) }`,
434442
`x.m`,
435443
[]string{`float64`, `byte`},
436444
`func(float64, *byte, ...[]byte)`,
437445
},
438446

439-
{`package r0; type T[P any] struct{}; func (_ T[P]) m[Q any](Q); func _[P any](x T[P]) { x.m(42) }`,
447+
{genericPkg + `r0; type T[P any] struct{}; func (_ T[P]) m[Q any](Q); func _[P any](x T[P]) { x.m(42) }`,
440448
`x.m`,
441449
[]string{`int`},
442450
`func(int)`,
443451
},
444452
// TODO(gri) record method type parameters in syntax.FuncType so we can check this
445-
// {`package r1; type T interface{ m[P any](P) }; func _(x T) { x.m(4.2) }`,
453+
// {genericPkg + `r1; type T interface{ m[P any](P) }; func _(x T) { x.m(4.2) }`,
446454
// `x.m`,
447455
// []string{`float64`},
448456
// `func(float64)`,
449457
// },
450458

451-
{`package s1; func f[T any, P interface{type *T}](x T); func _(x string) { f(x) }`,
459+
{genericPkg + `s1; func f[T any, P interface{type *T}](x T); func _(x string) { f(x) }`,
452460
`f`,
453461
[]string{`string`, `*string`},
454462
`func(x string)`,
455463
},
456-
{`package s2; func f[T any, P interface{type *T}](x []T); func _(x []int) { f(x) }`,
464+
{genericPkg + `s2; func f[T any, P interface{type *T}](x []T); func _(x []int) { f(x) }`,
457465
`f`,
458466
[]string{`int`, `*int`},
459467
`func(x []int)`,
460468
},
461-
{`package s3; type C[T any] interface{type chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`,
469+
{genericPkg + `s3; type C[T any] interface{type chan<- T}; func f[T any, P C[T]](x []T); func _(x []int) { f(x) }`,
462470
`f`,
463471
[]string{`int`, `chan<- int`},
464472
`func(x []int)`,
465473
},
466-
{`package s4; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`,
474+
{genericPkg + `s4; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T); func _(x []int) { f(x) }`,
467475
`f`,
468476
[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
469477
`func(x []int)`,
470478
},
471479

472-
{`package t1; func f[T any, P interface{type *T}]() T; func _() { _ = f[string] }`,
480+
{genericPkg + `t1; func f[T any, P interface{type *T}]() T; func _() { _ = f[string] }`,
473481
`f`,
474482
[]string{`string`, `*string`},
475483
`func() string`,
476484
},
477-
{`package t2; type C[T any] interface{type chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`,
485+
{genericPkg + `t2; type C[T any] interface{type chan<- T}; func f[T any, P C[T]]() []T; func _() { _ = f[int] }`,
478486
`f`,
479487
[]string{`int`, `chan<- int`},
480488
`func() []int`,
481489
},
482-
{`package t3; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`,
490+
{genericPkg + `t3; type C[T any] interface{type chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T; func _() { _ = f[int] }`,
483491
`f`,
484492
[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
485493
`func() []int`,
@@ -551,10 +559,10 @@ func TestDefsInfo(t *testing.T) {
551559

552560
// generic types must be sanitized
553561
// (need to use sufficiently nested types to provoke unexpanded types)
554-
{`package g0; type t[P any] P; const x = t[int](42)`, `x`, `const g0.x g0.t[int]`},
555-
{`package g1; type t[P any] P; var x = t[int](42)`, `x`, `var g1.x g1.t[int]`},
556-
{`package g2; type t[P any] P; type x struct{ f t[int] }`, `x`, `type g2.x struct{f g2.t[int]}`},
557-
{`package g3; type t[P any] P; func f(x struct{ f t[string] }); var g = f`, `g`, `var g3.g func(x struct{f g3.t[string]})`},
562+
{genericPkg + `g0; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`},
563+
{genericPkg + `g1; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`},
564+
{genericPkg + `g2; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`},
565+
{genericPkg + `g3; type t[P any] P; func f(x struct{ f t[string] }); var g = f`, `g`, `var generic_g3.g func(x struct{f generic_g3.t[string]})`},
558566
}
559567

560568
for _, test := range tests {
@@ -596,10 +604,10 @@ func TestUsesInfo(t *testing.T) {
596604

597605
// generic types must be sanitized
598606
// (need to use sufficiently nested types to provoke unexpanded types)
599-
{`package g0; func _() { _ = x }; type t[P any] P; const x = t[int](42)`, `x`, `const g0.x g0.t[int]`},
600-
{`package g1; func _() { _ = x }; type t[P any] P; var x = t[int](42)`, `x`, `var g1.x g1.t[int]`},
601-
{`package g2; func _() { type _ x }; type t[P any] P; type x struct{ f t[int] }`, `x`, `type g2.x struct{f g2.t[int]}`},
602-
{`package g3; func _() { _ = f }; type t[P any] P; func f(x struct{ f t[string] })`, `f`, `func g3.f(x struct{f g3.t[string]})`},
607+
{genericPkg + `g0; func _() { _ = x }; type t[P any] P; const x = t[int](42)`, `x`, `const generic_g0.x generic_g0.t[int]`},
608+
{genericPkg + `g1; func _() { _ = x }; type t[P any] P; var x = t[int](42)`, `x`, `var generic_g1.x generic_g1.t[int]`},
609+
{genericPkg + `g2; func _() { type _ x }; type t[P any] P; type x struct{ f t[int] }`, `x`, `type generic_g2.x struct{f generic_g2.t[int]}`},
610+
{genericPkg + `g3; func _() { _ = f }; type t[P any] P; func f(x struct{ f t[string] })`, `f`, `func generic_g3.f(x struct{f generic_g3.t[string]})`},
603611
}
604612

605613
for _, test := range tests {
@@ -1560,6 +1568,50 @@ func F(){
15601568
}
15611569
}
15621570

1571+
func TestConvertibleTo(t *testing.T) {
1572+
for _, test := range []struct {
1573+
v, t Type
1574+
want bool
1575+
}{
1576+
{Typ[Int], Typ[Int], true},
1577+
{Typ[Int], Typ[Float32], true},
1578+
{newDefined(Typ[Int]), Typ[Int], true},
1579+
{newDefined(new(Struct)), new(Struct), true},
1580+
{newDefined(Typ[Int]), new(Struct), false},
1581+
{Typ[UntypedInt], Typ[Int], true},
1582+
// Untyped string values are not permitted by the spec, so the below
1583+
// behavior is undefined.
1584+
{Typ[UntypedString], Typ[String], true},
1585+
} {
1586+
if got := ConvertibleTo(test.v, test.t); got != test.want {
1587+
t.Errorf("ConvertibleTo(%v, %v) = %t, want %t", test.v, test.t, got, test.want)
1588+
}
1589+
}
1590+
}
1591+
1592+
func TestAssignableTo(t *testing.T) {
1593+
for _, test := range []struct {
1594+
v, t Type
1595+
want bool
1596+
}{
1597+
{Typ[Int], Typ[Int], true},
1598+
{Typ[Int], Typ[Float32], false},
1599+
{newDefined(Typ[Int]), Typ[Int], false},
1600+
{newDefined(new(Struct)), new(Struct), true},
1601+
{Typ[UntypedBool], Typ[Bool], true},
1602+
{Typ[UntypedString], Typ[Bool], false},
1603+
// Neither untyped string nor untyped numeric assignments arise during
1604+
// normal type checking, so the below behavior is technically undefined by
1605+
// the spec.
1606+
{Typ[UntypedString], Typ[String], true},
1607+
{Typ[UntypedInt], Typ[Int], true},
1608+
} {
1609+
if got := AssignableTo(test.v, test.t); got != test.want {
1610+
t.Errorf("AssignableTo(%v, %v) = %t, want %t", test.v, test.t, got, test.want)
1611+
}
1612+
}
1613+
}
1614+
15631615
func TestIdentical_issue15173(t *testing.T) {
15641616
// Identical should allow nil arguments and be symmetric.
15651617
for _, test := range []struct {

src/cmd/compile/internal/types2/typestring_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ var dependentTestTypes = []testEntry{
111111
// interfaces
112112
dup(`interface{io.Reader; io.Writer}`),
113113
dup(`interface{m() int; io.Writer}`),
114-
{`interface{m() interface{T}}`, `interface{m() interface{p.T}}`},
114+
{`interface{m() interface{T}}`, `interface{m() interface{generic_p.T}}`},
115115
}
116116

117117
func TestTypeString(t *testing.T) {
@@ -122,7 +122,7 @@ func TestTypeString(t *testing.T) {
122122
tests = append(tests, dependentTestTypes...)
123123

124124
for _, test := range tests {
125-
src := `package p; import "io"; type _ io.Writer; type T ` + test.src
125+
src := `package generic_p; import "io"; type _ io.Writer; type T ` + test.src
126126
pkg, err := makePkg(src)
127127
if err != nil {
128128
t.Errorf("%s: %s", src, err)

0 commit comments

Comments
 (0)