Skip to content

Commit 1c86bee

Browse files
committed
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 <[email protected]> Run-TryBot: Robert Findley <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent cb908f1 commit 1c86bee

4 files changed

Lines changed: 67 additions & 3 deletions

File tree

src/go/types/expr.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
12301230

12311231
switch utyp := structure(base).(type) {
12321232
case *Struct:
1233+
// Prevent crash if the struct referred to is not yet set up.
1234+
// See analogous comment for *Array.
1235+
if utyp.fields == nil {
1236+
check.error(e, _Todo, "illegal cycle in type declaration")
1237+
goto Error
1238+
}
12331239
if len(e.Elts) == 0 {
12341240
break
12351241
}

src/go/types/struct.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515

1616
// A Struct represents a struct type.
1717
type Struct struct {
18-
fields []*Var
18+
fields []*Var // fields != nil indicates the struct is set up (possibly with len(fields) == 0)
1919
tags []string // field tags; nil if there are no tags
2020
}
2121

@@ -33,7 +33,9 @@ func NewStruct(fields []*Var, tags []string) *Struct {
3333
if len(tags) > len(fields) {
3434
panic("more tags than fields")
3535
}
36-
return &Struct{fields: fields, tags: tags}
36+
s := &Struct{fields: fields, tags: tags}
37+
s.markComplete()
38+
return s
3739
}
3840

3941
// 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) }
5658
// ----------------------------------------------------------------------------
5759
// Implementation
5860

61+
func (s *Struct) markComplete() {
62+
if s.fields == nil {
63+
s.fields = make([]*Var, 0)
64+
}
65+
}
66+
5967
func (check *Checker) structType(styp *Struct, e *ast.StructType) {
6068
list := e.Fields
6169
if list == nil {
70+
styp.markComplete()
6271
return
6372
}
6473

@@ -161,6 +170,7 @@ func (check *Checker) structType(styp *Struct, e *ast.StructType) {
161170

162171
styp.fields = fields
163172
styp.tags = tags
173+
styp.markComplete()
164174
}
165175

166176
func embeddedFieldIdent(e ast.Expr) *ast.Ident {

src/go/types/subst.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,9 @@ func (subst *subster) typ(typ Type) Type {
9191

9292
case *Struct:
9393
if fields, copied := subst.varList(t.fields); copied {
94-
return &Struct{fields: fields, tags: t.tags}
94+
s := &Struct{fields: fields, tags: t.tags}
95+
s.markComplete()
96+
return s
9597
}
9698

9799
case *Pointer:
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
import "unsafe"
8+
9+
type S /* ERROR illegal cycle in declaration of S */ struct {
10+
_ [unsafe.Sizeof(s)]byte
11+
}
12+
13+
var s S
14+
15+
// Since f is a pointer, this case could be valid.
16+
// But it's pathological and not worth the expense.
17+
type T struct {
18+
f *[unsafe.Sizeof(T /* ERROR illegal cycle in type declaration */ {})]int
19+
}
20+
21+
// a mutually recursive case using unsafe.Sizeof
22+
type (
23+
A1 struct {
24+
_ [unsafe.Sizeof(B1{})]int
25+
}
26+
27+
B1 struct {
28+
_ [unsafe.Sizeof(A1 /* ERROR illegal cycle in type declaration */ {})]int
29+
}
30+
)
31+
32+
// a mutually recursive case using len
33+
type (
34+
A2 struct {
35+
f [len(B2{}.f)]int
36+
}
37+
38+
B2 struct {
39+
f [len(A2 /* ERROR illegal cycle in type declaration */ {}.f)]int
40+
}
41+
)
42+
43+
// test case from issue
44+
type a struct {
45+
_ [42 - unsafe.Sizeof(a /* ERROR illegal cycle in type declaration */ {})]byte
46+
}

0 commit comments

Comments
 (0)