check.nonGeneric(T, x)
}
+ // Here, x is a value, meaning it has a type. If that type is pending, then we have
+ // a cycle. As an example:
+ //
+ // type T [unsafe.Sizeof(T{})]int
+ //
+ // has a cycle T->T which is deemed valid (by decl.go), but which is in fact invalid.
+ check.pendingType(x)
check.record(x)
return kind
}
}
+// If x has a pending type (i.e. its declaring object is on the object path), pendingType
+// reports an error and invalidates x.mode and x.typ.
+// Otherwise it leaves x alone.
+func (check *Checker) pendingType(x *operand) {
+ if x.mode == invalid || x.mode == novalue {
+ return
+ }
+ if n, ok := Unalias(x.typ).(*Named); ok {
+ if i, ok := check.objPathIdx[n.obj]; ok {
+ check.cycleError(check.objPath, i)
+ x.mode = invalid
+ x.typ = Typ[Invalid]
+ }
+ }
+}
+
// exprInternal contains the core of type checking of expressions.
// Must only be called by rawExpr.
// (See rawExpr for an explanation of the parameters.)
return typ
}
-func setDefType(def *TypeName, typ Type) {
- if def != nil {
- switch t := def.typ.(type) {
- case *Alias:
- t.fromRHS = typ
- case *Basic:
- assert(t == Typ[Invalid])
- case *Named:
- t.fromRHS = typ
- default:
- panic(fmt.Sprintf("unexpected type %T", t))
- }
- }
-}
+// TODO(markfreeman): Remove this function.
+func setDefType(def *TypeName, typ Type) {}
func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *TypeName) (res Type) {
if check.conf.Trace {
check.nonGeneric(T, x)
}
+ // Here, x is a value, meaning it has a type. If that type is pending, then we have
+ // a cycle. As an example:
+ //
+ // type T [unsafe.Sizeof(T{})]int
+ //
+ // has a cycle T->T which is deemed valid (by decl.go), but which is in fact invalid.
+ check.pendingType(x)
check.record(x)
return kind
}
}
+// If x has a pending type (i.e. its declaring object is on the object path), pendingType
+// reports an error and invalidates x.mode and x.typ.
+// Otherwise it leaves x alone.
+func (check *Checker) pendingType(x *operand) {
+ if x.mode == invalid || x.mode == novalue {
+ return
+ }
+ if n, ok := Unalias(x.typ).(*Named); ok {
+ if i, ok := check.objPathIdx[n.obj]; ok {
+ check.cycleError(check.objPath, i)
+ x.mode = invalid
+ x.typ = Typ[Invalid]
+ }
+ }
+}
+
// exprInternal contains the core of type checking of expressions.
// Must only be called by rawExpr.
// (See rawExpr for an explanation of the parameters.)
return typ
}
-func setDefType(def *TypeName, typ Type) {
- if def != nil {
- switch t := def.typ.(type) {
- case *Alias:
- t.fromRHS = typ
- case *Basic:
- assert(t == Typ[Invalid])
- case *Named:
- t.fromRHS = typ
- default:
- panic(fmt.Sprintf("unexpected type %T", t))
- }
- }
-}
+// TODO(markfreeman): Remove this function.
+func setDefType(def *TypeName, typ Type) {}
func (check *Checker) instantiatedType(ix *indexedExpr, def *TypeName) (res Type) {
if check.conf._Trace {
// S
// }
//
- InvalidDeclCycle
-
- // InvalidTypeCycle occurs when a cycle in type definitions results in a
- // type that is not well-defined.
- //
// Example:
// import "unsafe"
//
// type T [unsafe.Sizeof(T{})]int
+ InvalidDeclCycle
+
+ // TODO(markfreeman): Retire InvalidTypeCycle, as it's never emitted.
+
+ // InvalidTypeCycle occurs when a cycle in type definitions results in a
+ // type that is not well-defined.
InvalidTypeCycle
// InvalidConstInit occurs when a const declaration has a non-constant
// pointers
P0 *P0
- PP *struct{ PP.f /* ERROR "PP.f is not a type" */ }
+ PP /* ERROR "invalid recursive type" */ *struct{ PP.f }
// functions
F0 func(F0)
// test cases for issue 18643
// (type cycle detection when non-type expressions are involved)
type (
- T14 [len(T14 /* ERROR "invalid recursive type" */ {})]int
- T15 [][len(T15 /* ERROR "invalid recursive type" */ {})]int
- T16 map[[len(T16 /* ERROR "invalid recursive type" */ {1:2})]int]int
- T17 map[int][len(T17 /* ERROR "invalid recursive type" */ {1:2})]int
+ T14 /* ERROR "invalid recursive type" */ [len(T14{})]int
+ T15 /* ERROR "invalid recursive type" */ [][len(T15{})]int
+ T16 /* ERROR "invalid recursive type" */ map[[len(T16{1:2})]int]int
+ T17 /* ERROR "invalid recursive type" */ map[int][len(T17{1:2})]int
)
// Test case for types depending on function literals (see also #22992).
// Test case for issue 6638.
-type T interface {
- m() [T(nil).m /* ERROR "undefined" */ ()[0]]int
+type T /* ERROR "invalid recursive type" */ interface {
+ m() [T(nil).m()[0]]int
}
// Variations of this test case.
// Check that accessing an interface method too early doesn't lead
// to follow-on errors due to an incorrectly computed type set.
-type T8 interface {
- m() [unsafe.Sizeof(T8.m /* ERROR "undefined" */ )]int
+type T8 /* ERROR "invalid recursive type" */ interface {
+ m() [unsafe.Sizeof(T8.m)]int
}
var _ = T8.m // no error expected here
type _ interface {
nosuchpkg /* ERROR "undefined: nosuchpkg" */ .Nosuchtype
}
- type I interface {
- I.m /* ERROR "I.m is not a type" */
+ type I /* ERROR "invalid recursive type" */ interface {
+ I.m
m()
}
}
// func t2[T Numeric2](s[]T){0 /* ERROR "not a type */ []{s /* ERROR cannot index" */ [0][0]}}
// crash 3
-type t3 *interface{ t3.p /* ERROR "t3.p is not a type" */ }
+type t3 /* ERROR "invalid recursive type" */ *interface{ t3.p }
// crash 4
type Numeric4 interface{t4 /* ERROR "not a type" */ }
type o18[T any] []func(_ o18[[]_ /* ERROR "cannot use _" */ ])
// crash 19
-type Z19 [][[]Z19{}[0][0]]c19 /* ERROR "undefined" */
+type Z19 /* ERROR "invalid recursive type: Z19 refers to itself" */ [][[]Z19{}[0][0]]int
// crash 20
type Z20 /* ERROR "invalid recursive type" */ interface{ Z20 }
// Since f is a pointer, this case could be valid.
// But it's pathological and not worth the expense.
-type T struct {
- f *[unsafe.Sizeof(T /* ERROR "invalid recursive type" */ {})]int
+type T /* ERROR "invalid recursive type" */ struct {
+ f *[unsafe.Sizeof(T{})]int
}
// a mutually recursive case using unsafe.Sizeof
type (
- A1 struct {
+ A1/* ERROR "invalid recursive type" */ struct {
_ [unsafe.Sizeof(B1{})]int
}
B1 struct {
- _ [unsafe.Sizeof(A1 /* ERROR "invalid recursive type" */ {})]int
+ _ [unsafe.Sizeof(A1{})]int
}
)
// a mutually recursive case using len
type (
- A2 struct {
+ A2/* ERROR "invalid recursive type" */ struct {
f [len(B2{}.f)]int
}
B2 struct {
- f [len(A2 /* ERROR "invalid recursive type" */ {}.f)]int
+ f [len(A2{}.f)]int
}
)
// test case from issue
-type a struct {
- _ [42 - unsafe.Sizeof(a /* ERROR "invalid recursive type" */ {})]byte
+type a /* ERROR "invalid recursive type" */ struct {
+ _ [42 - unsafe.Sizeof(a{})]byte
}
--- /dev/null
+// Copyright 2025 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.
+
+package p
+
+import "unsafe"
+
+var v any = 42
+
+type T /* ERROR "invalid recursive type" */ struct {
+ f [unsafe.Sizeof(v.(T))]int
+}
--- /dev/null
+// Copyright 2025 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.
+
+package p
+
+import "unsafe"
+
+type T /* ERROR "invalid recursive type" */ [unsafe.Sizeof(f())]int
+
+func f() T {
+ return T{}
+}
\ No newline at end of file
package p
-type A interface {
- // TODO(mdempsky): This should be an error, but this error is
- // nonsense. The error should actually mention that there's a
- // type loop.
- Fn(A.Fn) // ERROR "type A has no method Fn|A.Fn undefined|A.Fn is not a type"
+type A interface { // ERROR "invalid recursive type"
+ Fn(A.Fn)
}