]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typealias] cmd/compile: improved error message for cyles involving type aliases
authorRobert Griesemer <gri@golang.org>
Thu, 12 Jan 2017 22:35:20 +0000 (14:35 -0800)
committerRobert Griesemer <gri@golang.org>
Thu, 12 Jan 2017 23:25:20 +0000 (23:25 +0000)
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>
src/cmd/compile/internal/gc/fmt.go
src/cmd/compile/internal/gc/typecheck.go

index fffce440bc859ea8e22c1c26be2c8b69767a8819..16a4e342fced10e733ac6d6cb0f62d65311f1cd4 100644 (file)
@@ -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) {
index 46c71d69c475c1705bc55b2e4bc5a38c6f56f7d9..f18bcfad78d23b29348b51a34fb9f5d5fe4a582b 100644 (file)
@@ -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