1
0
mirror of https://github.com/golang/go synced 2024-11-18 19:54:44 -07:00

go.tools/go/types: tests for cycles in type decls

Fixed one aspect of issue 5090. Fixing it completely
requires a bit more work around the representation of
interface types.

R=adonovan
CC=golang-dev
https://golang.org/cl/10678045
This commit is contained in:
Robert Griesemer 2013-06-27 12:43:20 -07:00
parent b52f745c3a
commit a0160af20b
3 changed files with 132 additions and 11 deletions

View File

@ -45,6 +45,7 @@ var (
// Each tests entry is list of files belonging to the same package.
var tests = [][]string{
{"testdata/cycles.src"},
{"testdata/decls0.src"},
{"testdata/decls1.src"},
{"testdata/decls2a.src", "testdata/decls2b.src"},
@ -205,7 +206,7 @@ func checkFiles(t *testing.T, testfiles []string) {
ctxt.Check(pkgName, fset, files...)
if *listErrors {
t.Errorf("--- %s: %d errors found:", pkgName, len(errlist))
t.Errorf("--- %s: %d errors found", pkgName, len(errlist))
for _, err := range errlist {
t.Error(err)
}

View File

@ -116,13 +116,13 @@ func (check *checker) collectParams(scope *Scope, list *ast.FieldList, variadicO
return
}
func (check *checker) collectMethods(list *ast.FieldList) (methods []*Func) {
func (check *checker) collectMethods(list *ast.FieldList, cycleOk bool) (methods []*Func) {
if list == nil {
return nil
}
scope := NewScope(nil)
for _, f := range list.List {
typ := check.typ(f.Type, len(f.Names) > 0) // cycles are not ok for embedded interfaces
typ := check.typ(f.Type, cycleOk)
// the parser ensures that f.Tag is nil and we don't
// care if a constructed AST contains a non-nil tag
if len(f.Names) > 0 {
@ -140,15 +140,23 @@ func (check *checker) collectMethods(list *ast.FieldList) (methods []*Func) {
}
} else {
// embedded interface
utyp := typ.Underlying()
if ityp, ok := utyp.(*Interface); ok {
for _, m := range ityp.methods {
switch t := typ.Underlying().(type) {
case nil:
// The underlying type is in the process of being defined
// but we need it in order to complete this type. For now
// complain with an "unimplemented" error. This requires
// a bit more work.
// TODO(gri) finish this.
check.errorf(f.Type.Pos(), "reference to incomplete type %s - unimplemented", f.Type)
case *Interface:
for _, m := range t.methods {
check.declare(scope, nil, m)
methods = append(methods, m)
}
} else if utyp != Typ[Invalid] {
// if utyp is invalid, don't complain (the root cause was reported before)
check.errorf(f.Type.Pos(), "%s is not an interface type", typ)
default:
if t != Typ[Invalid] {
check.errorf(f.Type.Pos(), "%s is not an interface type", typ)
}
}
}
}
@ -1042,7 +1050,7 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type, iota int, cycle
check.errorf(obj.pos, "illegal cycle in declaration of %s", obj.name)
x.expr = e
x.typ = Typ[Invalid]
return // don't goto Error - need x.mode == typexpr
return // don't goto Error - want x.mode == typexpr
}
case *Var:
x.mode = variable
@ -1494,7 +1502,7 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type, iota int, cycle
case *ast.InterfaceType:
x.mode = typexpr
x.typ = NewInterface(check.collectMethods(e.Methods))
x.typ = NewInterface(check.collectMethods(e.Methods, cycleOk))
case *ast.MapType:
x.mode = typexpr

112
go/types/testdata/cycles.src vendored Normal file
View File

@ -0,0 +1,112 @@
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cycles
type (
T0 int
T1 /* ERROR "cycle" */ T1
T2 *T2
T3 /* ERROR "cycle" */ T4
T4 T5
T5 T3
T6 T7
T7 *T8
T8 T6
// arrays
A0 /* ERROR "cycle" */ [10]A0
A1 [10]*A1
A2 /* ERROR "cycle" */ [10]A3
A3 [10]A4
A4 A2
A5 [10]A6
A6 *A5
// slices
L0 []L0
// structs
S0 /* ERROR "cycle" */ struct{ _ S0 }
S1 /* ERROR "cycle" */ struct{ S1 }
S2 struct{ _ *S2 }
S3 struct{ *S3 }
S4 /* ERROR "cycle" */ struct{ S5 }
S5 struct{ S6 }
S6 S4
// pointers
P0 *P0
// functions
F0 func(F0)
F1 func() F1
F2 func(F2) F2
// interfaces
I0 /* ERROR "cycle" */ interface{ I0 }
I1 /* ERROR "cycle" */ interface{ I2 }
I2 interface{ I3 }
I3 interface{ I1 }
I4 interface{ f(I4) }
// testcase for issue 5090
// TODO(gri) fix this
I5 interface{ f(I6) }
I6 interface{ I5 /* ERROR "unimplemented" */ }
// maps
M0 map[M0]M0
// channels
C0 chan C0
)
func _() {
type (
t1 /* ERROR "cycle" */ t1
t2 *t2
t3 t4 /* ERROR "undeclared" */
t4 t5 /* ERROR "undeclared" */
t5 t3
// arrays
a0 /* ERROR "cycle" */ [10]a0
a1 [10]*a1
// slices
l0 []l0
// structs
s0 /* ERROR "cycle" */ struct{ _ s0 }
s1 /* ERROR "cycle" */ struct{ s1 }
s2 struct{ _ *s2 }
s3 struct{ *s3 }
// pointers
p0 *p0
// functions
f0 func(f0)
f1 func() f1
f2 func(f2) f2
// interfaces
i0 /* ERROR "cycle" */ interface{ i0 }
// maps
m0 map[m0]m0
// channels
c0 chan c0
)
}