Unreviewed changes
7 is the latest approved patch-set.
The change was submitted with unreviewed changes in the following files:
```
The name of the file: src/cmd/compile/internal/types2/named.go
Insertions: 2, Deletions: 2.
@@ -110,8 +110,8 @@
allowNilRHS bool // same as below, as well as briefly during checking of a type declaration
allowNilUnderlying bool // may be true from creation via [NewNamed] until [Named.SetUnderlying]
- inst *instance // information for instantiated types; nil otherwise
- finiteMem *bool // whether the type uses finite memory, or nil
+ inst *instance // information for instantiated types; nil otherwise
+ finite *bool // whether the type has finite size, or nil
mu sync.Mutex // guards all fields below
state_ uint32 // the current state of this type; must only be accessed atomically or when mu is held
```
```
The name of the file: src/cmd/compile/internal/types2/expr.go
Insertions: 1, Deletions: 1.
@@ -1041,7 +1041,7 @@
if x.mode == invalid || x.mode == novalue {
return
}
- if !check.finiteMem(x.typ) {
+ if !check.finiteSize(x.typ) {
x.mode = invalid
x.typ = Typ[Invalid]
}
```
```
The name of the file: src/go/types/named.go
Insertions: 2, Deletions: 2.
@@ -113,8 +113,8 @@
allowNilRHS bool // same as below, as well as briefly during checking of a type declaration
allowNilUnderlying bool // may be true from creation via [NewNamed] until [Named.SetUnderlying]
- inst *instance // information for instantiated types; nil otherwise
- finiteMem *bool // whether the type uses finite memory, or nil
+ inst *instance // information for instantiated types; nil otherwise
+ finite *bool // whether the type has finite size, or nil
mu sync.Mutex // guards all fields below
state_ uint32 // the current state of this type; must only be accessed atomically or when mu is held
```
```
The name of the file: src/go/types/expr.go
Insertions: 1, Deletions: 1.
@@ -1033,7 +1033,7 @@
if x.mode == invalid || x.mode == novalue {
return
}
- if !check.finiteMem(x.typ) {
+ if !check.finiteSize(x.typ) {
x.mode = invalid
x.typ = Typ[Invalid]
}
```
```
The name of the file: src/go/types/cycles.go
Insertions: 9, Deletions: 9.
@@ -108,17 +108,16 @@
// TODO(markfreeman): Can the value cached on Named be used in validType / hasVarSize?
-// finiteMem checks that a Named type uses a finite amount of memory in its
-// definition.
-func (check *Checker) finiteMem(t Type) (b bool) {
+// finiteSize returns whether a type has finite size.
+func (check *Checker) finiteSize(t Type) (b bool) {
switch t := Unalias(t).(type) {
case *Named:
- if t.finiteMem != nil {
- return *t.finiteMem
+ if t.finite != nil {
+ return *t.finite
}
defer func() {
- t.finiteMem = &b
+ t.finite = &b
}()
if i, ok := check.objPathIdx[t.obj]; ok {
@@ -129,19 +128,20 @@
check.push(t.obj)
defer check.pop()
- return check.finiteMem(t.fromRHS)
+ return check.finiteSize(t.fromRHS)
case *Array:
// The array length is already computed. If it was a valid length, it
// is finite; else, an error was reported in the computation.
- return check.finiteMem(t.elem)
+ return check.finiteSize(t.elem)
case *Struct:
for _, f := range t.fields {
- if !check.finiteMem(f.typ) {
+ if !check.finiteSize(f.typ) {
return false
}
}
}
+
return true
}
```
```
The name of the file: src/cmd/compile/internal/types2/cycles.go
Insertions: 9, Deletions: 9.
@@ -105,17 +105,16 @@
// TODO(markfreeman): Can the value cached on Named be used in validType / hasVarSize?
-// finiteMem checks that a Named type uses a finite amount of memory in its
-// definition.
-func (check *Checker) finiteMem(t Type) (b bool) {
+// finiteSize returns whether a type has finite size.
+func (check *Checker) finiteSize(t Type) (b bool) {
switch t := Unalias(t).(type) {
case *Named:
- if t.finiteMem != nil {
- return *t.finiteMem
+ if t.finite != nil {
+ return *t.finite
}
defer func() {
- t.finiteMem = &b
+ t.finite = &b
}()
if i, ok := check.objPathIdx[t.obj]; ok {
@@ -126,19 +125,20 @@
check.push(t.obj)
defer check.pop()
- return check.finiteMem(t.fromRHS)
+ return check.finiteSize(t.fromRHS)
case *Array:
// The array length is already computed. If it was a valid length, it
// is finite; else, an error was reported in the computation.
- return check.finiteMem(t.elem)
+ return check.finiteSize(t.elem)
case *Struct:
for _, f := range t.fields {
- if !check.finiteMem(f.typ) {
+ if !check.finiteSize(f.typ) {
return false
}
}
}
+
return true
}
```
Change information
Commit message:
go/types, types2: add check for finite size at value observance
Each type must be representable by a finite amount of Go source code
after replacing all alias type names, value names, and embedded
interfaces (per #56103) with the RHS from their respective declarations
("expansion"); otherwise the type is invalid.
Furthermore, each type must have a finite size.
Checking for finite source after expansion is handled in decl.go.
Checking for finite size is handled in validtype.go and is delayed to
the end of type checking (unless used in unsafe.Sizeof, in which case
it is computed eagerly).
We can only construct values of valid types. Thus, while a type is
pending (on the object path and thus not yet valid), it cannot construct
a value of its own type (directly or indirectly).
This change enforces the indirect case by validating each type at value
observance (and hence upholding the invariant that values of only valid
types are created). Validation is cached on Named types to avoid
duplicate work.
As an example, consider:
type A [unsafe.Sizeof(B{})]int
type B A
Clearly, since there are no aliases, A and B have finite source. At the
site of B{}, B will be checked for finite size, recursing down the
values of B, at which point A is seen. Since A is on the object path,
there is a cycle preventing B from being proven valid before B{},
violating our invariant.
Note that this change also works for generic types.
Fixes #75918
Fixes #76478
Change-Id: I76d493b5da9571780fed4b3c76803750ec184818
Files:
- M src/cmd/compile/internal/types2/cycles.go
- M src/cmd/compile/internal/types2/expr.go
- M src/cmd/compile/internal/types2/named.go
- M src/cmd/compile/internal/types2/sizeof_test.go
- M src/go/types/cycles.go
- M src/go/types/expr.go
- M src/go/types/named.go
- M src/go/types/sizeof_test.go
- M src/internal/types/testdata/fixedbugs/issue52915.go
- A src/internal/types/testdata/fixedbugs/issue75918.go
- A src/internal/types/testdata/fixedbugs/issue76478.go
Change size: M
Delta: 11 files changed, 131 insertions(+), 19 deletions(-)
Branch: refs/heads/master
Submit Requirements:
Code-Review: +2 by Robert Griesemer
TryBots-Pass: LUCI-TryBot-Result+1 by Go LUCI