Commit 5c160b28 authored by Robert Griesemer's avatar Robert Griesemer

[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/35129Reviewed-by: 's avatarMatthew Dempsky <mdempsky@google.com>
parent b2386dff
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment