mirror of
https://github.com/golang/go
synced 2024-11-02 11:50:30 +00:00
[dev.typealias] cmd/compile: improved error message for cyles involving type aliases
Known issue: #18640 (requires a bit more work, I believe). For #18130. Change-Id: I53dc26012070e0c79f63b7c76266732190a83d47 Reviewed-on: https://go-review.googlesource.com/35129 Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
b2386dffa1
commit
5c160b28ba
2 changed files with 20 additions and 11 deletions
|
@ -1077,6 +1077,7 @@ var opprec = []int{
|
|||
OSEND: 3,
|
||||
OANDAND: 2,
|
||||
OOROR: 1,
|
||||
|
||||
// Statements handled by stmtfmt
|
||||
OAS: -1,
|
||||
OAS2: -1,
|
||||
|
@ -1104,7 +1105,8 @@ var opprec = []int{
|
|||
OSWITCH: -1,
|
||||
OXCASE: -1,
|
||||
OXFALL: -1,
|
||||
OEND: 0,
|
||||
|
||||
OEND: 0,
|
||||
}
|
||||
|
||||
func (n *Node) exprfmt(s fmt.State, prec int) {
|
||||
|
|
|
@ -96,16 +96,16 @@ func typekind(t *Type) string {
|
|||
return fmt.Sprintf("etype=%d", et)
|
||||
}
|
||||
|
||||
// sprint_depchain prints a dependency chain of nodes into fmt.
|
||||
// sprint_depchain prints a dependency chain of nodes into trace.
|
||||
// It is used by typecheck in the case of OLITERAL nodes
|
||||
// to print constant definition loops.
|
||||
func sprint_depchain(fmt_ *string, stack []*Node, cur *Node, first *Node) {
|
||||
func sprint_depchain(trace *string, stack []*Node, cur *Node, first *Node) {
|
||||
for i := len(stack) - 1; i >= 0; i-- {
|
||||
if n := stack[i]; n.Op == cur.Op {
|
||||
if n != first {
|
||||
sprint_depchain(fmt_, stack[:i], n, first)
|
||||
sprint_depchain(trace, stack[:i], n, first)
|
||||
}
|
||||
*fmt_ += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cur)
|
||||
*trace += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cur)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -152,7 +152,6 @@ func typecheck(n *Node, top int) *Node {
|
|||
if n.Typecheck == 2 {
|
||||
// Typechecking loop. Trying printing a meaningful message,
|
||||
// otherwise a stack trace of typechecking.
|
||||
var fmt_ string
|
||||
switch n.Op {
|
||||
// We can already diagnose variables used as types.
|
||||
case ONAME:
|
||||
|
@ -160,22 +159,30 @@ func typecheck(n *Node, top int) *Node {
|
|||
yyerror("%v is not a type", n)
|
||||
}
|
||||
|
||||
case OTYPE:
|
||||
if top&Etype == Etype {
|
||||
var trace string
|
||||
sprint_depchain(&trace, typecheck_tcstack, n, n)
|
||||
yyerrorl(n.Lineno, "invalid recursive type alias %v%s", n, trace)
|
||||
}
|
||||
|
||||
case OLITERAL:
|
||||
if top&(Erv|Etype) == Etype {
|
||||
yyerror("%v is not a type", n)
|
||||
break
|
||||
}
|
||||
sprint_depchain(&fmt_, typecheck_tcstack, n, n)
|
||||
yyerrorl(n.Lineno, "constant definition loop%s", fmt_)
|
||||
var trace string
|
||||
sprint_depchain(&trace, typecheck_tcstack, n, n)
|
||||
yyerrorl(n.Lineno, "constant definition loop%s", trace)
|
||||
}
|
||||
|
||||
if nsavederrors+nerrors == 0 {
|
||||
fmt_ = ""
|
||||
var trace string
|
||||
for i := len(typecheck_tcstack) - 1; i >= 0; i-- {
|
||||
x := typecheck_tcstack[i]
|
||||
fmt_ += fmt.Sprintf("\n\t%v %v", x.Line(), x)
|
||||
trace += fmt.Sprintf("\n\t%v %v", x.Line(), x)
|
||||
}
|
||||
yyerror("typechecking loop involving %v%s", n, fmt_)
|
||||
yyerror("typechecking loop involving %v%s", n, trace)
|
||||
}
|
||||
|
||||
lineno = lno
|
||||
|
|
Loading…
Reference in a new issue