goto Error // error was reported before
case *ast.Ident:
- check.ident(x, e, nil)
+ check.ident(x, e, nil, false)
case *ast.Ellipsis:
// ellipses are handled explicitly where they are legal
var r /* ERROR cycle */ = newReader()
func newReader() r
-// variations of the theme of #8699 amd #20770
+// variations of the theme of #8699 and #20770
var arr /* ERROR cycle */ = f()
func f() [len(arr)]int
-// TODO(gri) here we should only get one error
-func ff /* ERROR cycle */ (ff /* ERROR not a type */ )
+// issue #25790
+func ff(ff /* ERROR not a type */ )
+func gg((gg /* ERROR not a type */ ))
type T13 /* ERROR cycle */ [len(b13)]int
var b13 T13
-func g /* ERROR cycle */ () [unsafe.Sizeof(x)]int
-var x = g
+func g1() [unsafe.Sizeof(g1)]int
+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
type T14 [uintptr(unsafe.Sizeof(&c14))]byte
)
// cycles in function/method declarations
-// (test cases for issue 5217 and variants)
-func f1 /* ERROR cycle */ (x f1 /* ERROR "not a type" */ ) {}
-func f2 /* ERROR cycle */ (x *f2 /* ERROR "not a type" */ ) {}
-func f3 /* ERROR cycle */ () (x f3 /* ERROR "not a type" */ ) { return }
-func f4 /* ERROR cycle */ () (x *f4 /* ERROR "not a type" */ ) { return }
+// (test cases for issues #5217, #25790 and variants)
+func f1(x f1 /* ERROR "not a type" */ ) {}
+func f2(x *f2 /* ERROR "not a type" */ ) {}
+func f3() (x f3 /* 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) m2(x *S0.m2 /* ERROR "field or method" */ ) {}
// 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.
// 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.expr = e
}
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()
+ 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)
// The object may be dot-imported: If so, remove its package from
case *ast.Ident:
var x operand
- check.ident(&x, e, def)
+ check.ident(&x, e, def, true)
switch x.mode {
case typexpr: