1
0
mirror of https://github.com/golang/go synced 2024-07-08 12:18:55 +00:00

go/types, types2: more concise error messages for cycle errors

If a cycle has length 1, don't enumerate the single cycle entry;
instead just mention "refers to itself". For instance, for an
invalid recursive type T we now report:

	invalid recursive type: T refers to itself

instead of:

	invalid recursive type T
		T refers to
		T

Adjust tests to check for the different error messages.

Change-Id: I5bd46f62fac0cf167f0d0c9a55f952981d294ff4
Reviewed-on: https://go-review.googlesource.com/c/go/+/436295
Run-TryBot: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Robert Griesemer <gri@google.com>
This commit is contained in:
Robert Griesemer 2022-09-28 16:44:53 -07:00 committed by Gopher Robot
parent ecd112c0d1
commit e22af33b48
19 changed files with 83 additions and 47 deletions

View File

@ -308,7 +308,7 @@ func (check *Checker) cycleError(cycle []Object) {
// name returns the (possibly qualified) object name. // name returns the (possibly qualified) object name.
// This is needed because with generic types, cycles // This is needed because with generic types, cycles
// may refer to imported types. See issue #50788. // may refer to imported types. See issue #50788.
// TODO(gri) Thus functionality is used elsewhere. Factor it out. // TODO(gri) This functionality is used elsewhere. Factor it out.
name := func(obj Object) string { name := func(obj Object) string {
var buf bytes.Buffer var buf bytes.Buffer
writePackage(&buf, obj.Pkg(), check.qualifier) writePackage(&buf, obj.Pkg(), check.qualifier)
@ -327,6 +327,17 @@ func (check *Checker) cycleError(cycle []Object) {
if tname != nil && tname.IsAlias() { if tname != nil && tname.IsAlias() {
check.validAlias(tname, Typ[Invalid]) check.validAlias(tname, Typ[Invalid])
} }
// report a more concise error for self references
if len(cycle) == 1 {
if tname != nil {
check.errorf(obj, _InvalidDeclCycle, "invalid recursive type: %s refers to itself", objName)
} else {
check.errorf(obj, _InvalidDeclCycle, "invalid cycle in declaration: %s refers to itself", objName)
}
return
}
var err error_ var err error_
err.code = _InvalidDeclCycle err.code = _InvalidDeclCycle
if tname != nil { if tname != nil {

View File

@ -152,6 +152,13 @@ func findPath(objMap map[Object]*declInfo, from, to Object, seen map[Object]bool
// reportCycle reports an error for the given cycle. // reportCycle reports an error for the given cycle.
func (check *Checker) reportCycle(cycle []Object) { func (check *Checker) reportCycle(cycle []Object) {
obj := cycle[0] obj := cycle[0]
// report a more concise error for self references
if len(cycle) == 1 {
check.errorf(obj, _InvalidInitCycle, "initialization cycle: %s refers to itself", obj.Name())
return
}
var err error_ var err error_
err.code = _InvalidInitCycle err.code = _InvalidInitCycle
err.errorf(obj, "initialization cycle for %s", obj.Name()) err.errorf(obj, "initialization cycle for %s", obj.Name())

View File

@ -325,6 +325,17 @@ func (check *Checker) cycleError(cycle []Object) {
if tname != nil && tname.IsAlias() { if tname != nil && tname.IsAlias() {
check.validAlias(tname, Typ[Invalid]) check.validAlias(tname, Typ[Invalid])
} }
// report a more concise error for self references
if len(cycle) == 1 {
if tname != nil {
check.errorf(obj, _InvalidDeclCycle, "invalid recursive type: %s refers to itself", objName)
} else {
check.errorf(obj, _InvalidDeclCycle, "invalid cycle in declaration: %s refers to itself", objName)
}
return
}
if tname != nil { if tname != nil {
check.errorf(obj, _InvalidDeclCycle, "invalid recursive type %s", objName) check.errorf(obj, _InvalidDeclCycle, "invalid recursive type %s", objName)
} else { } else {

View File

@ -152,6 +152,13 @@ func findPath(objMap map[Object]*declInfo, from, to Object, seen map[Object]bool
// reportCycle reports an error for the given cycle. // reportCycle reports an error for the given cycle.
func (check *Checker) reportCycle(cycle []Object) { func (check *Checker) reportCycle(cycle []Object) {
obj := cycle[0] obj := cycle[0]
// report a more concise error for self references
if len(cycle) == 1 {
check.errorf(obj, _InvalidInitCycle, "initialization cycle: %s refers to itself", obj.Name())
return
}
check.errorf(obj, _InvalidInitCycle, "initialization cycle for %s", obj.Name()) check.errorf(obj, _InvalidInitCycle, "initialization cycle for %s", obj.Name())
// subtle loop: print cycle[i] for i = 0, n-1, n-2, ... 1 for len(cycle) = n // subtle loop: print cycle[i] for i = 0, n-1, n-2, ... 1 for len(cycle) = n
for i := len(cycle) - 1; i >= 0; i-- { for i := len(cycle) - 1; i >= 0; i-- {

View File

@ -8,7 +8,7 @@ import "unsafe"
type ( type (
T0 int T0 int
T1 /* ERROR invalid recursive type */ T1 T1 /* ERROR invalid recursive type: T1 refers to itself */ T1
T2 *T2 T2 *T2
T3 /* ERROR invalid recursive type */ T4 T3 /* ERROR invalid recursive type */ T4
@ -34,8 +34,8 @@ type (
L0 []L0 L0 []L0
// structs // structs
S0 /* ERROR invalid recursive type */ struct{ _ S0 } S0 /* ERROR invalid recursive type: S0 refers to itself */ struct{ _ S0 }
S1 /* ERROR invalid recursive type */ struct{ S1 } S1 /* ERROR invalid recursive type: S1 refers to itself */ struct{ S1 }
S2 struct{ _ *S2 } S2 struct{ _ *S2 }
S3 struct{ *S3 } S3 struct{ *S3 }
@ -53,7 +53,7 @@ type (
F2 func(F2) F2 F2 func(F2) F2
// interfaces // interfaces
I0 /* ERROR invalid recursive type */ interface{ I0 } I0 /* ERROR invalid recursive type: I0 refers to itself */ interface{ I0 }
I1 /* ERROR invalid recursive type */ interface{ I2 } I1 /* ERROR invalid recursive type */ interface{ I2 }
I2 interface{ I3 } I2 interface{ I3 }
@ -83,7 +83,7 @@ type (
func _() { func _() {
type ( type (
t1 /* ERROR invalid recursive type */ t1 t1 /* ERROR invalid recursive type: t1 refers to itself */ t1
t2 *t2 t2 *t2
t3 t4 /* ERROR undefined */ t3 t4 /* ERROR undefined */
@ -91,15 +91,15 @@ func _() {
t5 t3 t5 t3
// arrays // arrays
a0 /* ERROR invalid recursive type */ [10]a0 a0 /* ERROR invalid recursive type: a0 refers to itself */ [10]a0
a1 [10]*a1 a1 [10]*a1
// slices // slices
l0 []l0 l0 []l0
// structs // structs
s0 /* ERROR invalid recursive type */ struct{ _ s0 } s0 /* ERROR invalid recursive type: s0 refers to itself */ struct{ _ s0 }
s1 /* ERROR invalid recursive type */ struct{ s1 } s1 /* ERROR invalid recursive type: s1 refers to itself */ struct{ s1 }
s2 struct{ _ *s2 } s2 struct{ _ *s2 }
s3 struct{ *s3 } s3 struct{ *s3 }
@ -112,7 +112,7 @@ func _() {
f2 func(f2) f2 f2 func(f2) f2
// interfaces // interfaces
i0 /* ERROR invalid recursive type */ interface{ i0 } i0 /* ERROR invalid recursive type: i0 refers to itself */ interface{ i0 }
// maps // maps
m0 map[m0 /* ERROR invalid map key */ ]m0 m0 map[m0 /* ERROR invalid map key */ ]m0
@ -135,17 +135,17 @@ type S struct {
type ( type (
P1 *T9 P1 *T9
T9 /* ERROR invalid recursive type */ T9 T9 /* ERROR invalid recursive type: T9 refers to itself */ T9
T10 /* ERROR invalid recursive type */ T10 T10 /* ERROR invalid recursive type: T10 refers to itself */ T10
P2 *T10 P2 *T10
) )
func (T11) m() {} func (T11) m() {}
type T11 /* ERROR invalid recursive type */ struct{ T11 } type T11 /* ERROR invalid recursive type: T11 refers to itself */ struct{ T11 }
type T12 /* ERROR invalid recursive type */ struct{ T12 } type T12 /* ERROR invalid recursive type: T12 refers to itself */ struct{ T12 }
func (*T12) m() {} func (*T12) m() {}

View File

@ -159,7 +159,7 @@ var a12 = makeArray()
func makeArray() (res T12) { return } func makeArray() (res T12) { return }
// issue #20770 // issue #20770
var r /* ERROR cycle */ = newReader() var r /* ERROR invalid cycle in declaration of r */ = newReader()
func newReader() r func newReader() r
// variations of the theme of #8699 and #20770 // variations of the theme of #8699 and #20770
@ -170,7 +170,7 @@ func f() [len(arr)]int
func ff(ff /* ERROR not a type */ ) func ff(ff /* ERROR not a type */ )
func gg((gg /* ERROR not a type */ )) func gg((gg /* ERROR not a type */ ))
type T13 /* ERROR invalid recursive type */ [len(b13)]int type T13 /* ERROR invalid recursive type T13 */ [len(b13)]int
var b13 T13 var b13 T13
func g1() [unsafe.Sizeof(g1)]int func g1() [unsafe.Sizeof(g1)]int
@ -190,7 +190,7 @@ var c14 /* ERROR cycle */ T14
type T14 [uintptr(unsafe.Sizeof(&c14))]byte type T14 [uintptr(unsafe.Sizeof(&c14))]byte
// issue #34333 // issue #34333
type T15 /* ERROR invalid recursive type */ struct { type T15 /* ERROR invalid recursive type T15 */ struct {
f func() T16 f func() T16
b T16 b T16
} }

View File

@ -8,50 +8,50 @@ package init0
// initialization cycles (we don't know the types) // initialization cycles (we don't know the types)
const ( const (
s0 /* ERROR initialization cycle */ = s0 s0 /* ERROR initialization cycle: s0 refers to itself */ = s0
x0 /* ERROR initialization cycle */ = y0 x0 /* ERROR initialization cycle for x0 */ = y0
y0 = x0 y0 = x0
a0 = b0 a0 = b0
b0 /* ERROR initialization cycle */ = c0 b0 /* ERROR initialization cycle for b0 */ = c0
c0 = d0 c0 = d0
d0 = b0 d0 = b0
) )
var ( var (
s1 /* ERROR initialization cycle */ = s1 s1 /* ERROR initialization cycle: s1 refers to itself */ = s1
x1 /* ERROR initialization cycle */ = y1 x1 /* ERROR initialization cycle for x1 */ = y1
y1 = x1 y1 = x1
a1 = b1 a1 = b1
b1 /* ERROR initialization cycle */ = c1 b1 /* ERROR initialization cycle for b1 */ = c1
c1 = d1 c1 = d1
d1 = b1 d1 = b1
) )
// initialization cycles (we know the types) // initialization cycles (we know the types)
const ( const (
s2 /* ERROR initialization cycle */ int = s2 s2 /* ERROR initialization cycle: s2 refers to itself */ int = s2
x2 /* ERROR initialization cycle */ int = y2 x2 /* ERROR initialization cycle for x2 */ int = y2
y2 = x2 y2 = x2
a2 = b2 a2 = b2
b2 /* ERROR initialization cycle */ int = c2 b2 /* ERROR initialization cycle for b2 */ int = c2
c2 = d2 c2 = d2
d2 = b2 d2 = b2
) )
var ( var (
s3 /* ERROR initialization cycle */ int = s3 s3 /* ERROR initialization cycle: s3 refers to itself */ int = s3
x3 /* ERROR initialization cycle */ int = y3 x3 /* ERROR initialization cycle for x3 */ int = y3
y3 = x3 y3 = x3
a3 = b3 a3 = b3
b3 /* ERROR initialization cycle */ int = c3 b3 /* ERROR initialization cycle for b3 */ int = c3
c3 = d3 c3 = d3
d3 = b3 d3 = b3
) )
@ -62,12 +62,12 @@ type S1 struct {
f int f int
} }
const cx3 S1 /* ERROR invalid constant type */ = S1{cx3.f} const cx3 S1 /* ERROR invalid constant type */ = S1{cx3.f}
var vx3 /* ERROR initialization cycle */ S1 = S1{vx3.f} var vx3 /* ERROR initialization cycle: vx3 refers to itself */ S1 = S1{vx3.f}
// cycles via functions // cycles via functions
var x4 = x5 var x4 = x5
var x5 /* ERROR initialization cycle */ = f1() var x5 /* ERROR initialization cycle for x5 */ = f1()
func f1() int { return x5*10 } func f1() int { return x5*10 }
var x6, x7 /* ERROR initialization cycle */ = f2() var x6, x7 /* ERROR initialization cycle */ = f2()
@ -77,9 +77,9 @@ func f3() int { return x8 }
// cycles via function literals // cycles via function literals
var x9 /* ERROR initialization cycle */ = func() int { return x9 }() var x9 /* ERROR initialization cycle: x9 refers to itself */ = func() int { return x9 }()
var x10 /* ERROR initialization cycle */ = f4() var x10 /* ERROR initialization cycle for x10 */ = f4()
func f4() int { func f4() int {
_ = func() { _ = func() {
@ -94,7 +94,7 @@ type T1 struct{}
func (T1) m() bool { _ = x11; return false } func (T1) m() bool { _ = x11; return false }
var x11 /* ERROR initialization cycle */ = T1.m(T1{}) var x11 /* ERROR initialization cycle for x11 */ = T1.m(T1{})
// cycles via method values // cycles via method values
@ -103,4 +103,4 @@ type T2 struct{}
func (T2) m() bool { _ = x12; return false } func (T2) m() bool { _ = x12; return false }
var t1 T2 var t1 T2
var x12 /* ERROR initialization cycle */ = t1.m var x12 /* ERROR initialization cycle for x12 */ = t1.m

View File

@ -6,7 +6,7 @@ package p
import "unsafe" import "unsafe"
type T /* ERROR invalid recursive type T */ struct { type T /* ERROR invalid recursive type: T refers to itself */ struct {
T T
} }

View File

@ -14,7 +14,7 @@ type I3 interface{ int } // ERROR "interface"
type S struct { // GC_ERROR "invalid recursive type" type S struct { // GC_ERROR "invalid recursive type"
x interface{ S } // GCCGO_ERROR "interface" x interface{ S } // GCCGO_ERROR "interface"
} }
type I4 interface { // GC_ERROR "invalid recursive type I4\n\tLINE:.* I4 refers to\n\tLINE:.* I4$" type I4 interface { // GC_ERROR "invalid recursive type: I4 refers to itself"
I4 // GCCGO_ERROR "interface" I4 // GCCGO_ERROR "interface"
} }

View File

@ -11,6 +11,6 @@ type I1 = interface {
} }
// BAD: type loop should mention I1; see also #41669 // BAD: type loop should mention I1; see also #41669
type I2 interface { // GC_ERROR "invalid recursive type I2\n\tLINE: I2 refers to\n\tLINE: I2$|invalid recursive type I2" type I2 interface { // GC_ERROR "invalid recursive type: I2 refers to itself"
I1 // GCCGO_ERROR "invalid recursive interface" I1 // GCCGO_ERROR "invalid recursive interface"
} }

View File

@ -16,7 +16,7 @@ type T2 struct {
io.SectionReader io.SectionReader
} }
type T3 struct { // ERROR "invalid recursive type T3" type T3 struct { // ERROR "invalid recursive type: T3 refers to itself"
T1 T1
T2 T2
parent T3 parent T3

View File

@ -9,5 +9,5 @@
package p package p
func _() { func _() {
type T = T // ERROR "T uses T|invalid recursive type T" type T = T // ERROR "invalid recursive type: T refers to itself"
} }

View File

@ -10,6 +10,6 @@ package main
import "unsafe" import "unsafe"
var x struct { // GC_ERROR "initialization cycle for x" var x struct { // GC_ERROR "initialization cycle: x refers to itself"
a [unsafe.Sizeof(x.a)]int // GCCGO_ERROR "array bound|typechecking loop|invalid expression" a [unsafe.Sizeof(x.a)]int // GCCGO_ERROR "array bound|typechecking loop|invalid expression"
} }

View File

@ -8,6 +8,6 @@
package main package main
var y struct { // GC_ERROR "initialization cycle for y" var y struct { // GC_ERROR "initialization cycle: y refers to itself"
d [len(y.d)]int // GCCGO_ERROR "array bound|typechecking loop|invalid array" d [len(y.d)]int // GCCGO_ERROR "array bound|typechecking loop|invalid array"
} }

View File

@ -8,6 +8,6 @@
package main package main
var z struct { // GC_ERROR "initialization cycle for z" var z struct { // GC_ERROR "initialization cycle: z refers to itself"
e [cap(z.e)]int // GCCGO_ERROR "array bound|typechecking loop|invalid array" e [cap(z.e)]int // GCCGO_ERROR "array bound|typechecking loop|invalid array"
} }

View File

@ -10,6 +10,6 @@ package main
import "unsafe" import "unsafe"
var x struct { // GC_ERROR "initialization cycle for x" var x struct { // GC_ERROR "initialization cycle: x refers to itself"
b [unsafe.Offsetof(x.b)]int // GCCGO_ERROR "array bound|typechecking loop|invalid array" b [unsafe.Offsetof(x.b)]int // GCCGO_ERROR "array bound|typechecking loop|invalid array"
} }

View File

@ -10,6 +10,6 @@ package main
import "unsafe" import "unsafe"
var x struct { // GC_ERROR "initialization cycle for x" var x struct { // GC_ERROR "initialization cycle: x refers to itself"
c [unsafe.Alignof(x.c)]int // GCCGO_ERROR "array bound|typechecking loop|invalid array" c [unsafe.Alignof(x.c)]int // GCCGO_ERROR "array bound|typechecking loop|invalid array"
} }

View File

@ -9,7 +9,7 @@
package p package p
type T struct{ T } // ERROR "invalid recursive type .*T" type T struct{ T } // ERROR "invalid recursive type.*T"
func f() { func f() {
println(T{} == T{}) println(T{} == T{})

View File

@ -6,7 +6,7 @@
package p package p
type T[U interface{ M() T[U] }] int // ERROR "invalid recursive type T" type T[U interface{ M() T[U] }] int // ERROR "invalid recursive type: T refers to itself"
type X int type X int