Commit d97b11f1 authored by Robert Griesemer's avatar Robert Griesemer

go/types: don't report cycle error if clearer error follows

If a cyclic declaration uses a non-type object where it expects
a type, don't report the cycle error in favor of the clearer and
more informative error about the missing type.

Fixes #25790.

Change-Id: If937078383def878efb4c69686e5b4b2a495fd5d
Reviewed-on: https://go-review.googlesource.com/135700Reviewed-by: default avatarAlan Donovan <adonovan@google.com>
parent 36531204
...@@ -1010,7 +1010,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { ...@@ -1010,7 +1010,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
goto Error // error was reported before goto Error // error was reported before
case *ast.Ident: case *ast.Ident:
check.ident(x, e, nil) check.ident(x, e, nil, false)
case *ast.Ellipsis: case *ast.Ellipsis:
// ellipses are handled explicitly where they are legal // ellipses are handled explicitly where they are legal
......
...@@ -162,20 +162,29 @@ func makeArray() (res T12) { return } ...@@ -162,20 +162,29 @@ func makeArray() (res T12) { return }
var r /* ERROR cycle */ = newReader() var r /* ERROR cycle */ = newReader()
func newReader() r func newReader() r
// variations of the theme of #8699 amd #20770 // variations of the theme of #8699 and #20770
var arr /* ERROR cycle */ = f() var arr /* ERROR cycle */ = f()
func f() [len(arr)]int func f() [len(arr)]int
// TODO(gri) here we should only get one error // issue #25790
func ff /* ERROR cycle */ (ff /* ERROR not a type */ ) func ff(ff /* ERROR not a type */ )
func gg((gg /* ERROR not a type */ ))
type T13 /* ERROR cycle */ [len(b13)]int type T13 /* ERROR cycle */ [len(b13)]int
var b13 T13 var b13 T13
func g /* ERROR cycle */ () [unsafe.Sizeof(x)]int func g1() [unsafe.Sizeof(g1)]int
var x = g func g2() [unsafe.Sizeof(x2)]int
var x2 = g2
func h /* ERROR cycle */ () [h /* ERROR no value */ ()[0]]int { panic(0) } // verify that we get the correct sizes for the functions above
// (note: assert is statically evaluated in go/types test mode)
func init() {
assert(unsafe.Sizeof(g1) == 8)
assert(unsafe.Sizeof(x2) == 8)
}
func h() [h /* ERROR no value */ ()[0]]int { panic(0) }
var c14 /* ERROR cycle */ T14 var c14 /* ERROR cycle */ T14
type T14 [uintptr(unsafe.Sizeof(&c14))]byte type T14 [uintptr(unsafe.Sizeof(&c14))]byte
...@@ -183,11 +183,11 @@ type ( ...@@ -183,11 +183,11 @@ type (
) )
// cycles in function/method declarations // cycles in function/method declarations
// (test cases for issue 5217 and variants) // (test cases for issues #5217, #25790 and variants)
func f1 /* ERROR cycle */ (x f1 /* ERROR "not a type" */ ) {} func f1(x f1 /* ERROR "not a type" */ ) {}
func f2 /* ERROR cycle */ (x *f2 /* ERROR "not a type" */ ) {} func f2(x *f2 /* ERROR "not a type" */ ) {}
func f3 /* ERROR cycle */ () (x f3 /* ERROR "not a type" */ ) { return } func f3() (x f3 /* ERROR "not a type" */ ) { return }
func f4 /* ERROR cycle */ () (x *f4 /* ERROR "not a type" */ ) { return } func f4() (x *f4 /* ERROR "not a type" */ ) { return }
func (S0) m1(x S0.m1 /* ERROR "field or method" */ ) {} func (S0) m1(x S0.m1 /* ERROR "field or method" */ ) {}
func (S0) m2(x *S0.m2 /* ERROR "field or method" */ ) {} func (S0) m2(x *S0.m2 /* ERROR "field or method" */ ) {}
......
...@@ -17,8 +17,9 @@ import ( ...@@ -17,8 +17,9 @@ import (
// ident type-checks identifier e and initializes x with the value or type of e. // ident type-checks identifier e and initializes x with the value or type of e.
// If an error occurred, x.mode is set to invalid. // If an error occurred, x.mode is set to invalid.
// For the meaning of def, see Checker.definedType, below. // For the meaning of def, see Checker.definedType, below.
// If wantType is set, the identifier e is expected to denote a type.
// //
func (check *Checker) ident(x *operand, e *ast.Ident, def *Named) { func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) {
x.mode = invalid x.mode = invalid
x.expr = e x.expr = e
...@@ -35,8 +36,19 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named) { ...@@ -35,8 +36,19 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named) {
} }
check.recordUse(e, obj) check.recordUse(e, obj)
check.objDecl(obj, def) // Type-check the object.
// Only call Checker.objDecl if the object doesn't have a type yet
// (in which case we must actually determine it) or the object is a
// TypeName and we also want a type (in which case we might detect
// a cycle which needs to be reported). Otherwise we can skip the
// call and avoid a possible cycle error in favor of the more
// informative "not a type/value" error that this function's caller
// will issue (see issue #25790).
typ := obj.Type() typ := obj.Type()
if _, gotType := obj.(*TypeName); typ == nil || gotType && wantType {
check.objDecl(obj, def)
typ = obj.Type() // type must have been assigned by Checker.objDecl
}
assert(typ != nil) assert(typ != nil)
// The object may be dot-imported: If so, remove its package from // The object may be dot-imported: If so, remove its package from
...@@ -215,7 +227,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { ...@@ -215,7 +227,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
case *ast.Ident: case *ast.Ident:
var x operand var x operand
check.ident(&x, e, def) check.ident(&x, e, def, true)
switch x.mode { switch x.mode {
case typexpr: case typexpr:
......
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