1
0
mirror of https://github.com/golang/go synced 2024-11-12 02:00:23 -07:00

cmd/compile/internal/types2: simplify under() and fix a crash

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>
This commit is contained in:
Robert Griesemer 2021-11-12 18:24:54 -08:00
parent c54605266b
commit c2397905e0
4 changed files with 11 additions and 5 deletions

View File

@ -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

View File

@ -45,6 +45,7 @@ type (
// pointers
P0 *P0
PP *struct{ PP.f /* ERROR no field or method f */ }
// functions
F0 func(F0)

View File

@ -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.

View File

@ -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