Skip to content

Commit 5c160b2

Browse files
committed
[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 <[email protected]>
1 parent b2386df commit 5c160b2

File tree

2 files changed

+20
-11
lines changed

2 files changed

+20
-11
lines changed

src/cmd/compile/internal/gc/fmt.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -1077,6 +1077,7 @@ var opprec = []int{
10771077
OSEND: 3,
10781078
OANDAND: 2,
10791079
OOROR: 1,
1080+
10801081
// Statements handled by stmtfmt
10811082
OAS: -1,
10821083
OAS2: -1,
@@ -1104,7 +1105,8 @@ var opprec = []int{
11041105
OSWITCH: -1,
11051106
OXCASE: -1,
11061107
OXFALL: -1,
1107-
OEND: 0,
1108+
1109+
OEND: 0,
11081110
}
11091111

11101112
func (n *Node) exprfmt(s fmt.State, prec int) {

src/cmd/compile/internal/gc/typecheck.go

+17-10
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,16 @@ func typekind(t *Type) string {
9696
return fmt.Sprintf("etype=%d", et)
9797
}
9898

99-
// sprint_depchain prints a dependency chain of nodes into fmt.
99+
// sprint_depchain prints a dependency chain of nodes into trace.
100100
// It is used by typecheck in the case of OLITERAL nodes
101101
// to print constant definition loops.
102-
func sprint_depchain(fmt_ *string, stack []*Node, cur *Node, first *Node) {
102+
func sprint_depchain(trace *string, stack []*Node, cur *Node, first *Node) {
103103
for i := len(stack) - 1; i >= 0; i-- {
104104
if n := stack[i]; n.Op == cur.Op {
105105
if n != first {
106-
sprint_depchain(fmt_, stack[:i], n, first)
106+
sprint_depchain(trace, stack[:i], n, first)
107107
}
108-
*fmt_ += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cur)
108+
*trace += fmt.Sprintf("\n\t%v: %v uses %v", n.Line(), n, cur)
109109
return
110110
}
111111
}
@@ -152,30 +152,37 @@ func typecheck(n *Node, top int) *Node {
152152
if n.Typecheck == 2 {
153153
// Typechecking loop. Trying printing a meaningful message,
154154
// otherwise a stack trace of typechecking.
155-
var fmt_ string
156155
switch n.Op {
157156
// We can already diagnose variables used as types.
158157
case ONAME:
159158
if top&(Erv|Etype) == Etype {
160159
yyerror("%v is not a type", n)
161160
}
162161

162+
case OTYPE:
163+
if top&Etype == Etype {
164+
var trace string
165+
sprint_depchain(&trace, typecheck_tcstack, n, n)
166+
yyerrorl(n.Lineno, "invalid recursive type alias %v%s", n, trace)
167+
}
168+
163169
case OLITERAL:
164170
if top&(Erv|Etype) == Etype {
165171
yyerror("%v is not a type", n)
166172
break
167173
}
168-
sprint_depchain(&fmt_, typecheck_tcstack, n, n)
169-
yyerrorl(n.Lineno, "constant definition loop%s", fmt_)
174+
var trace string
175+
sprint_depchain(&trace, typecheck_tcstack, n, n)
176+
yyerrorl(n.Lineno, "constant definition loop%s", trace)
170177
}
171178

172179
if nsavederrors+nerrors == 0 {
173-
fmt_ = ""
180+
var trace string
174181
for i := len(typecheck_tcstack) - 1; i >= 0; i-- {
175182
x := typecheck_tcstack[i]
176-
fmt_ += fmt.Sprintf("\n\t%v %v", x.Line(), x)
183+
trace += fmt.Sprintf("\n\t%v %v", x.Line(), x)
177184
}
178-
yyerror("typechecking loop involving %v%s", n, fmt_)
185+
yyerror("typechecking loop involving %v%s", n, trace)
179186
}
180187

181188
lineno = lno

0 commit comments

Comments
 (0)