From e22af33b48447338abf6f788b3eb5b87577f95db Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 28 Sep 2022 16:44:53 -0700 Subject: [PATCH] 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 Reviewed-by: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Gopher Robot Auto-Submit: Robert Griesemer --- src/cmd/compile/internal/types2/decl.go | 13 ++++++- src/cmd/compile/internal/types2/initorder.go | 7 ++++ src/go/types/decl.go | 11 ++++++ src/go/types/initorder.go | 7 ++++ src/internal/types/testdata/check/cycles0.go | 26 +++++++------- src/internal/types/testdata/check/cycles5.go | 6 ++-- src/internal/types/testdata/check/init0.go | 36 +++++++++---------- .../types/testdata/fixedbugs/issue48819.go | 2 +- test/fixedbugs/bug195.go | 2 +- test/fixedbugs/issue23823.go | 2 +- test/fixedbugs/issue44266.go | 2 +- test/fixedbugs/issue48301.go | 2 +- test/fixedbugs/issue7525.go | 2 +- test/fixedbugs/issue7525b.go | 2 +- test/fixedbugs/issue7525c.go | 2 +- test/fixedbugs/issue7525d.go | 2 +- test/fixedbugs/issue7525e.go | 2 +- test/fixedbugs/issue8507.go | 2 +- test/typeparam/issue46461.go | 2 +- 19 files changed, 83 insertions(+), 47 deletions(-) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index ebce3ee2e2..ec9f154664 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -308,7 +308,7 @@ func (check *Checker) cycleError(cycle []Object) { // name returns the (possibly qualified) object name. // This is needed because with generic types, cycles // 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 { var buf bytes.Buffer writePackage(&buf, obj.Pkg(), check.qualifier) @@ -327,6 +327,17 @@ func (check *Checker) cycleError(cycle []Object) { if tname != nil && tname.IsAlias() { 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_ err.code = _InvalidDeclCycle if tname != nil { diff --git a/src/cmd/compile/internal/types2/initorder.go b/src/cmd/compile/internal/types2/initorder.go index af43f53c16..62184ea870 100644 --- a/src/cmd/compile/internal/types2/initorder.go +++ b/src/cmd/compile/internal/types2/initorder.go @@ -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. func (check *Checker) reportCycle(cycle []Object) { 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_ err.code = _InvalidInitCycle err.errorf(obj, "initialization cycle for %s", obj.Name()) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 87d4f3fdf4..628c7bb5d9 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -325,6 +325,17 @@ func (check *Checker) cycleError(cycle []Object) { if tname != nil && tname.IsAlias() { 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 { check.errorf(obj, _InvalidDeclCycle, "invalid recursive type %s", objName) } else { diff --git a/src/go/types/initorder.go b/src/go/types/initorder.go index 1118b58f7b..e9570ad55c 100644 --- a/src/go/types/initorder.go +++ b/src/go/types/initorder.go @@ -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. func (check *Checker) reportCycle(cycle []Object) { 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()) // 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-- { diff --git a/src/internal/types/testdata/check/cycles0.go b/src/internal/types/testdata/check/cycles0.go index e5368d13c9..d4e7e60f83 100644 --- a/src/internal/types/testdata/check/cycles0.go +++ b/src/internal/types/testdata/check/cycles0.go @@ -8,7 +8,7 @@ import "unsafe" type ( T0 int - T1 /* ERROR invalid recursive type */ T1 + T1 /* ERROR invalid recursive type: T1 refers to itself */ T1 T2 *T2 T3 /* ERROR invalid recursive type */ T4 @@ -34,8 +34,8 @@ type ( L0 []L0 // structs - S0 /* ERROR invalid recursive type */ struct{ _ S0 } - S1 /* ERROR invalid recursive type */ struct{ S1 } + S0 /* ERROR invalid recursive type: S0 refers to itself */ struct{ _ S0 } + S1 /* ERROR invalid recursive type: S1 refers to itself */ struct{ S1 } S2 struct{ _ *S2 } S3 struct{ *S3 } @@ -53,7 +53,7 @@ type ( F2 func(F2) F2 // 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 } I2 interface{ I3 } @@ -83,7 +83,7 @@ type ( func _() { type ( - t1 /* ERROR invalid recursive type */ t1 + t1 /* ERROR invalid recursive type: t1 refers to itself */ t1 t2 *t2 t3 t4 /* ERROR undefined */ @@ -91,15 +91,15 @@ func _() { t5 t3 // arrays - a0 /* ERROR invalid recursive type */ [10]a0 + a0 /* ERROR invalid recursive type: a0 refers to itself */ [10]a0 a1 [10]*a1 // slices l0 []l0 // structs - s0 /* ERROR invalid recursive type */ struct{ _ s0 } - s1 /* ERROR invalid recursive type */ struct{ s1 } + s0 /* ERROR invalid recursive type: s0 refers to itself */ struct{ _ s0 } + s1 /* ERROR invalid recursive type: s1 refers to itself */ struct{ s1 } s2 struct{ _ *s2 } s3 struct{ *s3 } @@ -112,7 +112,7 @@ func _() { f2 func(f2) f2 // interfaces - i0 /* ERROR invalid recursive type */ interface{ i0 } + i0 /* ERROR invalid recursive type: i0 refers to itself */ interface{ i0 } // maps m0 map[m0 /* ERROR invalid map key */ ]m0 @@ -135,17 +135,17 @@ type S struct { type ( 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 ) 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() {} diff --git a/src/internal/types/testdata/check/cycles5.go b/src/internal/types/testdata/check/cycles5.go index 68aa913682..5e0d1913d9 100644 --- a/src/internal/types/testdata/check/cycles5.go +++ b/src/internal/types/testdata/check/cycles5.go @@ -159,7 +159,7 @@ var a12 = makeArray() func makeArray() (res T12) { return } // issue #20770 -var r /* ERROR cycle */ = newReader() +var r /* ERROR invalid cycle in declaration of r */ = newReader() func newReader() r // 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 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 func g1() [unsafe.Sizeof(g1)]int @@ -190,7 +190,7 @@ var c14 /* ERROR cycle */ T14 type T14 [uintptr(unsafe.Sizeof(&c14))]byte // issue #34333 -type T15 /* ERROR invalid recursive type */ struct { +type T15 /* ERROR invalid recursive type T15 */ struct { f func() T16 b T16 } diff --git a/src/internal/types/testdata/check/init0.go b/src/internal/types/testdata/check/init0.go index 6e8746afb6..5159a176d7 100644 --- a/src/internal/types/testdata/check/init0.go +++ b/src/internal/types/testdata/check/init0.go @@ -8,50 +8,50 @@ package init0 // initialization cycles (we don't know the types) 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 a0 = b0 - b0 /* ERROR initialization cycle */ = c0 + b0 /* ERROR initialization cycle for b0 */ = c0 c0 = d0 d0 = b0 ) 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 a1 = b1 - b1 /* ERROR initialization cycle */ = c1 + b1 /* ERROR initialization cycle for b1 */ = c1 c1 = d1 d1 = b1 ) // initialization cycles (we know the types) 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 a2 = b2 - b2 /* ERROR initialization cycle */ int = c2 + b2 /* ERROR initialization cycle for b2 */ int = c2 c2 = d2 d2 = b2 ) 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 a3 = b3 - b3 /* ERROR initialization cycle */ int = c3 + b3 /* ERROR initialization cycle for b3 */ int = c3 c3 = d3 d3 = b3 ) @@ -62,12 +62,12 @@ type S1 struct { f int } 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 var x4 = x5 -var x5 /* ERROR initialization cycle */ = f1() +var x5 /* ERROR initialization cycle for x5 */ = f1() func f1() int { return x5*10 } var x6, x7 /* ERROR initialization cycle */ = f2() @@ -77,9 +77,9 @@ func f3() int { return x8 } // 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() { @@ -94,7 +94,7 @@ type T1 struct{} 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 @@ -103,4 +103,4 @@ type T2 struct{} func (T2) m() bool { _ = x12; return false } var t1 T2 -var x12 /* ERROR initialization cycle */ = t1.m +var x12 /* ERROR initialization cycle for x12 */ = t1.m diff --git a/src/internal/types/testdata/fixedbugs/issue48819.go b/src/internal/types/testdata/fixedbugs/issue48819.go index 95e40ea009..5d61803687 100644 --- a/src/internal/types/testdata/fixedbugs/issue48819.go +++ b/src/internal/types/testdata/fixedbugs/issue48819.go @@ -6,7 +6,7 @@ package p import "unsafe" -type T /* ERROR invalid recursive type T */ struct { +type T /* ERROR invalid recursive type: T refers to itself */ struct { T } diff --git a/test/fixedbugs/bug195.go b/test/fixedbugs/bug195.go index 4a3bf0db81..769ed050b3 100644 --- a/test/fixedbugs/bug195.go +++ b/test/fixedbugs/bug195.go @@ -14,7 +14,7 @@ type I3 interface{ int } // ERROR "interface" type S struct { // GC_ERROR "invalid recursive type" 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" } diff --git a/test/fixedbugs/issue23823.go b/test/fixedbugs/issue23823.go index c53415f7b9..0d51f81098 100644 --- a/test/fixedbugs/issue23823.go +++ b/test/fixedbugs/issue23823.go @@ -11,6 +11,6 @@ type I1 = interface { } // 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" } diff --git a/test/fixedbugs/issue44266.go b/test/fixedbugs/issue44266.go index c683e56075..f3c1984b6f 100644 --- a/test/fixedbugs/issue44266.go +++ b/test/fixedbugs/issue44266.go @@ -16,7 +16,7 @@ type T2 struct { io.SectionReader } -type T3 struct { // ERROR "invalid recursive type T3" +type T3 struct { // ERROR "invalid recursive type: T3 refers to itself" T1 T2 parent T3 diff --git a/test/fixedbugs/issue48301.go b/test/fixedbugs/issue48301.go index 94c9a5b6f9..8b6321d19a 100644 --- a/test/fixedbugs/issue48301.go +++ b/test/fixedbugs/issue48301.go @@ -9,5 +9,5 @@ package p func _() { - type T = T // ERROR "T uses T|invalid recursive type T" + type T = T // ERROR "invalid recursive type: T refers to itself" } diff --git a/test/fixedbugs/issue7525.go b/test/fixedbugs/issue7525.go index 05e26d1915..1a81200f13 100644 --- a/test/fixedbugs/issue7525.go +++ b/test/fixedbugs/issue7525.go @@ -10,6 +10,6 @@ package main 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" } diff --git a/test/fixedbugs/issue7525b.go b/test/fixedbugs/issue7525b.go index b72d12fbb7..2b903ae913 100644 --- a/test/fixedbugs/issue7525b.go +++ b/test/fixedbugs/issue7525b.go @@ -8,6 +8,6 @@ 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" } diff --git a/test/fixedbugs/issue7525c.go b/test/fixedbugs/issue7525c.go index 8d51154a35..b94d596044 100644 --- a/test/fixedbugs/issue7525c.go +++ b/test/fixedbugs/issue7525c.go @@ -8,6 +8,6 @@ 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" } diff --git a/test/fixedbugs/issue7525d.go b/test/fixedbugs/issue7525d.go index cedb9f7b31..dc83dbcb46 100644 --- a/test/fixedbugs/issue7525d.go +++ b/test/fixedbugs/issue7525d.go @@ -10,6 +10,6 @@ package main 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" } diff --git a/test/fixedbugs/issue7525e.go b/test/fixedbugs/issue7525e.go index 5746397521..d4f17314db 100644 --- a/test/fixedbugs/issue7525e.go +++ b/test/fixedbugs/issue7525e.go @@ -10,6 +10,6 @@ package main 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" } diff --git a/test/fixedbugs/issue8507.go b/test/fixedbugs/issue8507.go index 392ecf4063..6b513baf27 100644 --- a/test/fixedbugs/issue8507.go +++ b/test/fixedbugs/issue8507.go @@ -9,7 +9,7 @@ package p -type T struct{ T } // ERROR "invalid recursive type .*T" +type T struct{ T } // ERROR "invalid recursive type.*T" func f() { println(T{} == T{}) diff --git a/test/typeparam/issue46461.go b/test/typeparam/issue46461.go index 4d4d4400c2..363a87cfe0 100644 --- a/test/typeparam/issue46461.go +++ b/test/typeparam/issue46461.go @@ -6,7 +6,7 @@ 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