diff options
| author | Mark Freeman <mark@golang.org> | 2026-01-07 16:40:53 -0500 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-01-08 08:31:50 -0800 |
| commit | 5facb3b24b1c388176572eb95239f94d6ed4017d (patch) | |
| tree | f51a8e3d293fec3a323d2077baaf1f2a1698c343 | |
| parent | 28147b528312055b535c6a69d0d4492bd502e1b0 (diff) | |
| download | go-5facb3b24b1c388176572eb95239f94d6ed4017d.tar.xz | |
internal/types: add test for cycles in value context
Exposition is also added to outline a difference between syntax which
can / cannot produce values of incomplete types.
For us to enforce non-nilness of type RHS and remove the pending type
mechanism, I suspect we would need to add completeness guards to
the syntax which *can*.
Enforcing non-nilness of type RHS currently breaks the below test
cases, but I suspect that is simply an implementation artifact.
In other words, they just call Underlying at a bad time.
- T0
- T3
- T6 / T7
- T10
- T12
If we also remove pendingType, all of these test cases break; again,
we would need guards in the appropriate syntax logic.
Change-Id: Ibe22042232e542de1d38b923dd1d5cc50dce08cb
Reviewed-on: https://go-review.googlesource.com/c/go/+/734600
TryBot-Bypass: Mark Freeman <markfreeman@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Auto-Submit: Mark Freeman <markfreeman@google.com>
| -rw-r--r-- | src/internal/types/testdata/check/cycles6.go | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/src/internal/types/testdata/check/cycles6.go b/src/internal/types/testdata/check/cycles6.go new file mode 100644 index 0000000000..e5635ed456 --- /dev/null +++ b/src/internal/types/testdata/check/cycles6.go @@ -0,0 +1,71 @@ +// Copyright 2026 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" + +// Below are the pieces of syntax corresponding to functions which can produce a +// type T without first having a value of type T. Notice that each causes a +// value of type T to be passed to unsafe.Sizeof while T is incomplete. + +// literal on type +type T0 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(T0{})]int +// literal on value (not applicable) +// literal on pointer (not applicable) + +// call on type +type T1 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(T1(42))]int +// call on value +func f2() T2 +type T2 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(f2())]int +// call on pointer (not applicable) + +// assert on type +var i3 interface{} +type T3 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(i3.(T3))]int +// assert on value (not applicable) +// assert on pointer (not applicable) + +// receive on type (not applicable) +// receive on value +func f4() <-chan T4 +type T4 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(<-f4())]int +// receive on pointer (not applicable) + +// star on type (not applicable) +// star on value (not applicable) +// star on pointer +func f5() *T5 +type T5 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(*f5())]int + +// Below is additional syntax which interacts with incomplete types. Notice that +// each of the below falls into 1 of 3 cases: +// 1. It cannot produce a value of (incomplete) type T. +// 2. It can, but only because it already has a value of type T. +// 3. It can, but only because it performs an implicit dereference. + +// select on type (case 1) +// select on value (case 2) +type T6 /* ERROR "invalid recursive type" */ struct { + f T7 +} +type T7 [unsafe.Sizeof(T6{}.f)]int +// select on pointer (case 3) +type T8 /* ERROR "invalid recursive type" */ struct { + f T9 +} +type T9 [unsafe.Sizeof(new(T8).f)]int + +// slice on type (not applicable) +// slice on value (case 2) +type T10 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(T10{}[:])]int +// slice on pointer (case 3) +type T11 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(new(T11)[:])]int + +// index on type (case 1) +// index on value (case 2) +type T12 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(T12{}[42])]int +// index on pointer (case 3) +type T13 /* ERROR "invalid recursive type" */ [unsafe.Sizeof(new(T13)[42])]int |
