]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: add missing Named.unpack call in Checker.hasVarSize
authorMark Freeman <mark@golang.org>
Fri, 30 Jan 2026 19:23:02 +0000 (14:23 -0500)
committerRobert Griesemer <gri@google.com>
Mon, 2 Feb 2026 23:18:11 +0000 (15:18 -0800)
CL 734980 swapped use of Type.Underlying() in Checker.hasVarSize for
traversal of Named.fromRHS. It forgot to call Named.unpack() before
inspecting Named.fromRHS, allowing access of unexpanded instantiated
types.

These unexpanded instantiated types are then mistakenly marked as having
fixed size, which fails assertions downstream. This change adds the
missing Named.unpack() call and swaps direct access of Named.fromRHS for
Named.rhs(), which verifies such access in debug mode.

Fixes #77382

Change-Id: I324bbbbf790f8b09e95902ebe67f775483f88417
Reviewed-on: https://go-review.googlesource.com/c/go/+/740620
Reviewed-by: Robert Griesemer <gri@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/cmd/compile/internal/types2/builtins.go
src/go/types/builtins.go
src/internal/types/testdata/fixedbugs/issue77382.go [new file with mode: 0644]

index 59652285853b0b732a5315e6ec26064d29e6b78f..5fa0e6c6f04a660f2dd024dedeb0bbcdd0d26785 100644 (file)
@@ -1009,7 +1009,8 @@ func sliceElem(x *operand) (Type, *typeError) {
 // yet been checked.
 func (check *Checker) hasVarSize(t Type) bool {
        // Note: We could use Underlying here, but passing through the RHS may yield
-       // better error messages.
+       // better error messages and allows us to stash the result on each traversed
+       // Named type.
        switch t := Unalias(t).(type) {
        case *Named:
                if t.stateHas(hasVarSize) {
@@ -1025,7 +1026,9 @@ func (check *Checker) hasVarSize(t Type) bool {
                check.push(t.obj)
                defer check.pop()
 
-               varSize := check.hasVarSize(t.fromRHS)
+               // Careful, we're inspecting t.fromRHS, so we need to unpack first.
+               t.unpack()
+               varSize := check.hasVarSize(t.rhs())
 
                t.mu.Lock()
                defer t.mu.Unlock()
index aea2997f32e890882567c60cdb719c6c9e6c78e7..3b8a91a9f7a43b043450179804b01fcdf1a42910 100644 (file)
@@ -1012,7 +1012,8 @@ func sliceElem(x *operand) (Type, *typeError) {
 // yet been checked.
 func (check *Checker) hasVarSize(t Type) bool {
        // Note: We could use Underlying here, but passing through the RHS may yield
-       // better error messages.
+       // better error messages and allows us to stash the result on each traversed
+       // Named type.
        switch t := Unalias(t).(type) {
        case *Named:
                if t.stateHas(hasVarSize) {
@@ -1028,7 +1029,9 @@ func (check *Checker) hasVarSize(t Type) bool {
                check.push(t.obj)
                defer check.pop()
 
-               varSize := check.hasVarSize(t.fromRHS)
+               // Careful, we're inspecting t.fromRHS, so we need to unpack first.
+               t.unpack()
+               varSize := check.hasVarSize(t.rhs())
 
                t.mu.Lock()
                defer t.mu.Unlock()
diff --git a/src/internal/types/testdata/fixedbugs/issue77382.go b/src/internal/types/testdata/fixedbugs/issue77382.go
new file mode 100644 (file)
index 0000000..251d39a
--- /dev/null
@@ -0,0 +1,15 @@
+// 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"
+
+type T1[T any] [42]T2[T]
+
+type T2[T any] [42]T
+
+func _[T any]() {
+       _ = unsafe.Sizeof(T1[T]{})
+}