1
0
mirror of https://github.com/golang/go synced 2024-11-17 12:24:51 -07:00

go/types: report error for incomplete struct composite literal type

This is a port of CL 361412 to go/types.

Change-Id: Ie5bccc7faba7ca9230e712f867b27ca9dcddba79
Reviewed-on: https://go-review.googlesource.com/c/go/+/362739
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Robert Findley 2021-11-09 14:20:11 -05:00
parent cb908f1d4d
commit 1c86beeadf
4 changed files with 67 additions and 3 deletions

View File

@ -1230,6 +1230,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
switch utyp := structure(base).(type) {
case *Struct:
// Prevent crash if the struct referred to is not yet set up.
// See analogous comment for *Array.
if utyp.fields == nil {
check.error(e, _Todo, "illegal cycle in type declaration")
goto Error
}
if len(e.Elts) == 0 {
break
}

View File

@ -15,7 +15,7 @@ import (
// A Struct represents a struct type.
type Struct struct {
fields []*Var
fields []*Var // fields != nil indicates the struct is set up (possibly with len(fields) == 0)
tags []string // field tags; nil if there are no tags
}
@ -33,7 +33,9 @@ func NewStruct(fields []*Var, tags []string) *Struct {
if len(tags) > len(fields) {
panic("more tags than fields")
}
return &Struct{fields: fields, tags: tags}
s := &Struct{fields: fields, tags: tags}
s.markComplete()
return s
}
// NumFields returns the number of fields in the struct (including blank and embedded fields).
@ -56,9 +58,16 @@ func (t *Struct) String() string { return TypeString(t, nil) }
// ----------------------------------------------------------------------------
// Implementation
func (s *Struct) markComplete() {
if s.fields == nil {
s.fields = make([]*Var, 0)
}
}
func (check *Checker) structType(styp *Struct, e *ast.StructType) {
list := e.Fields
if list == nil {
styp.markComplete()
return
}
@ -161,6 +170,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
styp.fields = fields
styp.tags = tags
styp.markComplete()
}
func embeddedFieldIdent(e ast.Expr) *ast.Ident {

View File

@ -91,7 +91,9 @@ func (subst *subster) typ(typ Type) Type {
case *Struct:
if fields, copied := subst.varList(t.fields); copied {
return &Struct{fields: fields, tags: t.tags}
s := &Struct{fields: fields, tags: t.tags}
s.markComplete()
return s
}
case *Pointer:

View File

@ -0,0 +1,46 @@
// Copyright 2021 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 S /* ERROR illegal cycle in declaration of S */ struct {
_ [unsafe.Sizeof(s)]byte
}
var s S
// 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 illegal cycle in type declaration */ {})]int
}
// a mutually recursive case using unsafe.Sizeof
type (
A1 struct {
_ [unsafe.Sizeof(B1{})]int
}
B1 struct {
_ [unsafe.Sizeof(A1 /* ERROR illegal cycle in type declaration */ {})]int
}
)
// a mutually recursive case using len
type (
A2 struct {
f [len(B2{}.f)]int
}
B2 struct {
f [len(A2 /* ERROR illegal cycle in type declaration */ {}.f)]int
}
)
// test case from issue
type a struct {
_ [42 - unsafe.Sizeof(a /* ERROR illegal cycle in type declaration */ {})]byte
}