diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index fbfe3c81ff..b4035e16b3 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -491,6 +491,13 @@ func (check *Checker) assertableTo(V *Interface, T Type) (method, wrongType *Fun // 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 diff --git a/src/cmd/compile/internal/types2/testdata/check/cycles.src b/src/cmd/compile/internal/types2/testdata/check/cycles.src index b2ee8ecd5f..998f9f7da9 100644 --- a/src/cmd/compile/internal/types2/testdata/check/cycles.src +++ b/src/cmd/compile/internal/types2/testdata/check/cycles.src @@ -45,6 +45,7 @@ type ( // pointers P0 *P0 + PP *struct{ PP.f /* ERROR no field or method f */ } // functions F0 func(F0) diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index 7fcb196c5a..af195c08a4 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -21,13 +21,10 @@ type Type interface { // 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. diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index e22b1ff0a0..e077879b9d 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -315,6 +315,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) { 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