The simplified version of under exposed a bug (by crashing):
When a pointer base is used before the pointer is fully set
up, the base is nil. Set the pointer base to Typ[Invalid]
when creating the pointer, and add an extra safety check
into deref. Reviewed all code that creates pointers.
The same error cannot happen with other types because
accessing parts of another type results in an expression
that is not a type, and thus these kids of cycles cannot
happen.
Change-Id: I8332a281a534c094cfbb3623a636960865813ff6
Reviewed-on: https://go-review.googlesource.com/c/go/+/363665
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
// Otherwise it returns (typ, false).
func deref(typ Type) (Type, bool) {
if p, _ := typ.(*Pointer); p != nil {
+ // p.base should never be nil, but be conservative
+ if p.base == nil {
+ if debug {
+ panic("pointer with nil base type (possibly due to an invalid cyclic declaration)")
+ }
+ return Typ[Invalid], true
+ }
return p.base, true
}
return typ, false
// pointers
P0 *P0
+ PP *struct{ PP.f /* ERROR no field or method f */ }
// functions
F0 func(F0)
// under must only be called when a type is known
// to be fully set up.
func under(t Type) Type {
- switch t := t.(type) {
- case *Named:
+ if t, _ := t.(*Named); t != nil {
return t.under()
- case *TypeParam:
- return t.iface()
}
- return t
+ return t.Underlying()
}
// If x and y are identical, match returns x.
case *syntax.Operation:
if e.Op == syntax.Mul && e.Y == nil {
typ := new(Pointer)
+ typ.base = Typ[Invalid] // avoid nil base in invalid recursive type declaration
def.setUnderlying(typ)
typ.base = check.varType(e.X)
// If typ.base is invalid, it's unlikely that *base is particularly