mirror of
https://github.com/golang/go
synced 2024-11-14 05:50:27 -07:00
go/types: improve recursive type error message
This change improves error message for recursive types.
Currently, compilation of the [following program](https://go.dev/play/p/3ef84ObpzfG):
package main
type T1[T T2] struct{}
type T2[T T1] struct{}
returns an error:
./prog.go:3:6: invalid recursive type T1
./prog.go:3:6: T1 refers to
./prog.go:4:6: T2 refers to
./prog.go:3:6: T1
With the patch applied the error message looks like:
./prog.go:3:6: invalid recursive type T1
./prog.go:3:6: T1 refers to T2
./prog.go:4:6: T2 refers to T1
Change-Id: Ic07cdffcffb1483c672b241fede4e694269b5b79
GitHub-Last-Rev: cd042fdc38
GitHub-Pull-Request: golang/go#69574
Reviewed-on: https://go-review.googlesource.com/c/go/+/614084
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Tim King <taking@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
d40ae5efc8
commit
bdc6dbbc64
@ -334,17 +334,14 @@ func (check *Checker) cycleError(cycle []Object, start int) {
|
|||||||
} else {
|
} else {
|
||||||
err.addf(obj, "invalid cycle in declaration of %s", objName)
|
err.addf(obj, "invalid cycle in declaration of %s", objName)
|
||||||
}
|
}
|
||||||
i := start
|
// "cycle[i] refers to cycle[j]" for (i,j) = (s, s+1), (s+1, s+2), ..., (n, 0), (0,1), ..., (s-1,s) for len(cycle) = n, s = start.
|
||||||
for range cycle {
|
n := len(cycle)
|
||||||
err.addf(obj, "%s refers to", objName)
|
rotate := func(i int) int { return (i + start) % n }
|
||||||
i++
|
for i := range n {
|
||||||
if i >= len(cycle) {
|
obj := cycle[rotate(i)]
|
||||||
i = 0
|
next := cycle[rotate(i+1)]
|
||||||
}
|
err.addf(obj, "%s refers to %s", name(obj), name(next))
|
||||||
obj = cycle[i]
|
|
||||||
objName = name(obj)
|
|
||||||
}
|
}
|
||||||
err.addf(obj, "%s", objName)
|
|
||||||
err.report()
|
err.report()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,13 +163,11 @@ func (check *Checker) reportCycle(cycle []Object) {
|
|||||||
|
|
||||||
err := check.newError(InvalidInitCycle)
|
err := check.newError(InvalidInitCycle)
|
||||||
err.addf(obj, "initialization cycle for %s", obj.Name())
|
err.addf(obj, "initialization cycle for %s", obj.Name())
|
||||||
// subtle loop: print cycle[i] for i = 0, n-1, n-2, ... 1 for len(cycle) = n
|
// "cycle[i] refers to cycle[j]" for (i,j) = (0, n-1), (n-1, n-2), ..., (1,0) for len(cycle) = n.
|
||||||
for i := len(cycle) - 1; i >= 0; i-- {
|
for j := len(cycle) - 1; j >= 0; j-- {
|
||||||
err.addf(obj, "%s refers to", obj.Name())
|
err.addf(obj, "%s refers to %s", obj.Name(), cycle[j].Name())
|
||||||
obj = cycle[i]
|
obj = cycle[j]
|
||||||
}
|
}
|
||||||
// print cycle[0] again to close the cycle
|
|
||||||
err.addf(obj, "%s", obj.Name())
|
|
||||||
err.report()
|
err.report()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,17 +335,15 @@ func (check *Checker) cycleError(cycle []Object, start int) {
|
|||||||
} else {
|
} else {
|
||||||
err.addf(obj, "invalid cycle in declaration of %s", objName)
|
err.addf(obj, "invalid cycle in declaration of %s", objName)
|
||||||
}
|
}
|
||||||
i := start
|
|
||||||
for range cycle {
|
// "cycle[i] refers to cycle[j]" for (i,j) = (s, s+1), (s+1, s+2), ..., (n, 0), (0,1), ..., (s-1,s) for len(cycle) = n, s = start.
|
||||||
err.addf(obj, "%s refers to", objName)
|
n := len(cycle)
|
||||||
i++
|
rotate := func(i int) int { return (i + start) % n }
|
||||||
if i >= len(cycle) {
|
for i := range n {
|
||||||
i = 0
|
obj := cycle[rotate(i)]
|
||||||
}
|
next := cycle[rotate(i+1)]
|
||||||
obj = cycle[i]
|
err.addf(obj, "%s refers to %s", name(obj), name(next))
|
||||||
objName = name(obj)
|
|
||||||
}
|
}
|
||||||
err.addf(obj, "%s", objName)
|
|
||||||
err.report()
|
err.report()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,13 +166,11 @@ func (check *Checker) reportCycle(cycle []Object) {
|
|||||||
|
|
||||||
err := check.newError(InvalidInitCycle)
|
err := check.newError(InvalidInitCycle)
|
||||||
err.addf(obj, "initialization cycle for %s", obj.Name())
|
err.addf(obj, "initialization cycle for %s", obj.Name())
|
||||||
// subtle loop: print cycle[i] for i = 0, n-1, n-2, ... 1 for len(cycle) = n
|
// "cycle[i] refers to cycle[j]" for (i,j) = (0, n-1), (n-1, n-2), ..., (1,0) for len(cycle) = n.
|
||||||
for i := len(cycle) - 1; i >= 0; i-- {
|
for j := len(cycle) - 1; j >= 0; j-- {
|
||||||
err.addf(obj, "%s refers to", obj.Name())
|
err.addf(obj, "%s refers to %s", obj.Name(), cycle[j].Name())
|
||||||
obj = cycle[i]
|
obj = cycle[j]
|
||||||
}
|
}
|
||||||
// print cycle[0] again to close the cycle
|
|
||||||
err.addf(obj, "%s", obj.Name())
|
|
||||||
err.report()
|
err.report()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ type I4 interface { // GC_ERROR "invalid recursive type: I4 refers to itself"
|
|||||||
I4 // GCCGO_ERROR "interface"
|
I4 // GCCGO_ERROR "interface"
|
||||||
}
|
}
|
||||||
|
|
||||||
type I5 interface { // GC_ERROR "invalid recursive type I5\n\tLINE:.* I5 refers to\n\tLINE+4:.* I6 refers to\n\tLINE:.* I5$"
|
type I5 interface { // GC_ERROR "invalid recursive type I5\n\tLINE:.* I5 refers to I6\n\tLINE+4:.* I6 refers to I5$"
|
||||||
I6
|
I6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
package p
|
package p
|
||||||
|
|
||||||
type T1 struct { // ERROR "invalid recursive type T1\n\tLINE: T1 refers to\n\tLINE+4: T2 refers to\n\tLINE: T1$|invalid recursive type"
|
type T1 struct { // ERROR "invalid recursive type T1\n.*T1 refers to T2\n.*T2 refers to T1|invalid recursive type"
|
||||||
f2 T2
|
f2 T2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,21 +15,21 @@ type T2 struct { // GCCGO_ERROR "invalid recursive type"
|
|||||||
}
|
}
|
||||||
|
|
||||||
type a b // GCCGO_ERROR "invalid recursive type"
|
type a b // GCCGO_ERROR "invalid recursive type"
|
||||||
type b c // ERROR "invalid recursive type b\n\tLINE: b refers to\n\tLINE+1: c refers to\n\tLINE: b$|invalid recursive type"
|
type b c // ERROR "invalid recursive type b\n.*b refers to c\n.*c refers to b|invalid recursive type|invalid recursive type"
|
||||||
type c b // GCCGO_ERROR "invalid recursive type"
|
type c b // GCCGO_ERROR "invalid recursive type"
|
||||||
|
|
||||||
type d e
|
type d e
|
||||||
type e f
|
type e f
|
||||||
type f f // ERROR "invalid recursive type f\n\tLINE: f refers to\n\tLINE: f$|invalid recursive type"
|
type f f // ERROR "invalid recursive type: f refers to itself|invalid recursive type|invalid recursive type"
|
||||||
|
|
||||||
type g struct { // ERROR "invalid recursive type g\n\tLINE: g refers to\n\tLINE: g$|invalid recursive type"
|
type g struct { // ERROR "invalid recursive type: g refers to itself|invalid recursive type"
|
||||||
h struct {
|
h struct {
|
||||||
g
|
g
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type w x
|
type w x
|
||||||
type x y // ERROR "invalid recursive type x\n\tLINE: x refers to\n\tLINE+1: y refers to\n\tLINE+2: z refers to\n\tLINE: x$|invalid recursive type"
|
type x y // ERROR "invalid recursive type x\n.*x refers to y\n.*y refers to z\n.*z refers to x|invalid recursive type"
|
||||||
type y struct{ z } // GCCGO_ERROR "invalid recursive type"
|
type y struct{ z } // GCCGO_ERROR "invalid recursive type"
|
||||||
type z [10]x
|
type z [10]x
|
||||||
|
|
||||||
|
@ -6,4 +6,4 @@ package b
|
|||||||
|
|
||||||
import "./a"
|
import "./a"
|
||||||
|
|
||||||
type T a.T[T] // ERROR "invalid recursive type T\n.*T refers to\n.*a\.T refers to\n.*T"
|
type T a.T[T] // ERROR "invalid recursive type T\n.*T refers to a\.T\n.*a\.T refers to T"
|
||||||
|
@ -11,7 +11,7 @@ package main
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
x int = a
|
x int = a
|
||||||
a int = b // ERROR "a refers to\n.*b refers to\n.*c refers to\n.*a|initialization loop"
|
a int = b // ERROR "a refers to b\n.*b refers to c\n.*c refers to a|initialization loop"
|
||||||
b int = c
|
b int = c
|
||||||
c int = a
|
c int = a
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user