Commit 892fa3ae authored by Rémy Oudompheng's avatar Rémy Oudompheng

cmd/gc: replace "typechecking loop" by nicer errors in some cases.

For issue 3757:
BEFORE:  test/fixedbugs/bug463.go:12: typechecking loop involving a
             test/fixedbugs/bug463.go:12 a
             test/fixedbugs/bug463.go:12 <node DCLCONST>
AFTER:   test/fixedbugs/bug463.go:12: constant definition loop
             test/fixedbugs/bug463.go:12: a uses a

For issue 3937:
BEFORE: test/fixedbugs/bug464.go:12: typechecking loop involving foo
            test/fixedbugs/bug464.go:12 <T>
            test/fixedbugs/bug464.go:12 foo
            test/fixedbugs/bug464.go:12 <node DCLFUNC>
AFTER:  test/fixedbugs/bug464.go:12: foo is not a type

Fixes #3757.
Fixes #3937.

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6614058
parent 87c35d8d
......@@ -105,6 +105,27 @@ typekind(Type *t)
return buf;
}
/*
* sprint_depchain prints a dependency chain
* of nodes into fmt.
* It is used by typecheck in the case of OLITERAL nodes
* to print constant definition loops.
*/
static void
sprint_depchain(Fmt *fmt, NodeList *stack, Node *cur, Node *first)
{
NodeList *l;
for(l = stack; l; l=l->next) {
if(l->n->op == cur->op) {
if(l->n != first)
sprint_depchain(fmt, l->next, l->n, first);
fmtprint(fmt, "\n\t%L: %N uses %N", l->n->lineno, l->n, cur);
return;
}
}
}
/*
* type check node *np.
* replaces *np with a new pointer in some cases.
......@@ -155,6 +176,24 @@ typecheck(Node **np, int top)
}
if(n->typecheck == 2) {
// Typechecking loop. Trying printing a meaningful message,
// otherwise a stack trace of typechecking.
switch(n->op) {
case ONAME:
// We can already diagnose variables used as types.
if((top & (Erv|Etype)) == Etype)
yyerror("%N is not a type", n);
break;
case OLITERAL:
if((top & (Erv|Etype)) == Etype) {
yyerror("%N is not a type", n);
break;
}
fmtstrinit(&fmt);
sprint_depchain(&fmt, tcstack, n, n);
yyerrorl(n->lineno, "constant definition loop%s", fmtstrflush(&fmt));
break;
}
if(nsavederrors+nerrors == 0) {
fmtstrinit(&fmt);
for(l=tcstack; l; l=l->next)
......@@ -165,7 +204,7 @@ typecheck(Node **np, int top)
return n;
}
n->typecheck = 2;
if(tcfree != nil) {
l = tcfree;
tcfree = l->next;
......
// errorcheck
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 3757: unhelpful typechecking loop message
// for constants that refer to themselves.
package main
const a = a // ERROR "refers to itself|definition loop"
const (
X = A
A = B // ERROR "refers to itself|definition loop"
B = D
C, D = 1, A
)
func main() {
}
// errorcheck
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 3937: unhelpful typechecking loop message
// for identifiers wrongly used as types.
package main
func foo(x foo) {} // ERROR "expected type|not a type"
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