]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: wrap Named.fromRHS into Named.rhs
authorMark Freeman <mark@golang.org>
Thu, 23 Oct 2025 16:15:21 +0000 (12:15 -0400)
committerGopher Robot <gobot@golang.org>
Mon, 27 Oct 2025 18:47:38 +0000 (11:47 -0700)
In debug mode, the Named.rhs method asserts that Named is in a state
with Named.fromRHS populated.

This caught a missing call to Named.unpack in validtype, which has been
added.

Change-Id: Id3f95f78f03d98a6efe87af6ac24f2ac2e285f96
Reviewed-on: https://go-review.googlesource.com/c/go/+/714242
Auto-Submit: Mark Freeman <markfreeman@google.com>
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/named.go
src/cmd/compile/internal/types2/validtype.go
src/go/types/named.go
src/go/types/validtype.go

index 11d7ba1734e72acd466c227dd92d5891de8f01e7..e451defce6d688dba5930e13556512377f364202 100644 (file)
@@ -562,6 +562,16 @@ func (t *Named) methodIndex(name string, foldCase bool) int {
        return -1
 }
 
+// rhs returns [Named.fromRHS].
+//
+// In debug mode, it also asserts that n is in an appropriate state.
+func (n *Named) rhs() Type {
+       if debug {
+               assert(n.stateHas(lazyLoaded | unpacked))
+       }
+       return n.fromRHS
+}
+
 // Underlying returns the [underlying type] of the named type t, resolving all
 // forwarding declarations. Underlying types are never Named, TypeParam, or
 // Alias types.
@@ -573,7 +583,7 @@ func (n *Named) Underlying() Type {
        // The gccimporter depends on writing a nil underlying via NewNamed and
        // immediately reading it back. Rather than putting that in Named.under
        // and complicating things there, we just check for that special case here.
-       if n.fromRHS == nil {
+       if n.rhs() == nil {
                assert(n.allowNilRHS)
                if n.allowNilUnderlying {
                        return nil
@@ -649,8 +659,8 @@ func (n *Named) resolveUnderlying() {
                        t.mu.Lock()
                        defer t.mu.Unlock()
 
-                       assert(t.fromRHS != nil || t.allowNilRHS)
-                       rhs = t.fromRHS
+                       assert(t.rhs() != nil || t.allowNilRHS)
+                       rhs = t.rhs()
 
                default:
                        u = rhs // any type literal works
@@ -735,7 +745,7 @@ func (n *Named) expandRHS() (rhs Type) {
        }
 
        assert(!n.stateHas(unpacked))
-       assert(n.inst.orig.stateHas(unpacked | lazyLoaded))
+       assert(n.inst.orig.stateHas(lazyLoaded | unpacked))
 
        if n.inst.ctxt == nil {
                n.inst.ctxt = NewContext()
@@ -760,7 +770,7 @@ func (n *Named) expandRHS() (rhs Type) {
                ctxt = check.context()
        }
 
-       rhs = check.subst(n.obj.pos, orig.fromRHS, m, n, ctxt)
+       rhs = check.subst(n.obj.pos, orig.rhs(), m, n, ctxt)
 
        // TODO(markfreeman): Can we handle this in substitution?
        // If the RHS is an interface, we must set the receiver of interface methods
@@ -769,7 +779,7 @@ func (n *Named) expandRHS() (rhs Type) {
                if methods, copied := replaceRecvType(iface.methods, orig, n); copied {
                        // If the RHS doesn't use type parameters, it may not have been
                        // substituted; we need to craft a new interface first.
-                       if iface == orig.fromRHS {
+                       if iface == orig.rhs() {
                                assert(iface.complete) // otherwise we are copying incomplete data
 
                                crafted := check.newInterface()
index c21c36d6f6fd1a95ca3254ada8e0fc10f0a853b0..bec6412f86153a1ff8dbceae2758dd4ab1c8978a 100644 (file)
@@ -141,7 +141,8 @@ func (check *Checker) validType0(pos syntax.Pos, typ Type, nest, path []*Named)
                // Every type added to nest is also added to path; thus every type that is in nest
                // must also be in path (invariant). But not every type in path is in nest, since
                // nest may be pruned (see below, *TypeParam case).
-               if !check.validType0(pos, t.Origin().fromRHS, append(nest, t), append(path, t)) {
+               t.Origin().unpack()
+               if !check.validType0(pos, t.Origin().rhs(), append(nest, t), append(path, t)) {
                        return false
                }
 
index 564c1be3e0ef70056c8d55d01a5c8fb8af2fb865..e49bdc966663135250df2bc5d7529e8f0e8e322c 100644 (file)
@@ -565,6 +565,16 @@ func (t *Named) methodIndex(name string, foldCase bool) int {
        return -1
 }
 
+// rhs returns [Named.fromRHS].
+//
+// In debug mode, it also asserts that n is in an appropriate state.
+func (n *Named) rhs() Type {
+       if debug {
+               assert(n.stateHas(lazyLoaded | unpacked))
+       }
+       return n.fromRHS
+}
+
 // Underlying returns the [underlying type] of the named type t, resolving all
 // forwarding declarations. Underlying types are never Named, TypeParam, or
 // Alias types.
@@ -576,7 +586,7 @@ func (n *Named) Underlying() Type {
        // The gccimporter depends on writing a nil underlying via NewNamed and
        // immediately reading it back. Rather than putting that in Named.under
        // and complicating things there, we just check for that special case here.
-       if n.fromRHS == nil {
+       if n.rhs() == nil {
                assert(n.allowNilRHS)
                if n.allowNilUnderlying {
                        return nil
@@ -652,8 +662,8 @@ func (n *Named) resolveUnderlying() {
                        t.mu.Lock()
                        defer t.mu.Unlock()
 
-                       assert(t.fromRHS != nil || t.allowNilRHS)
-                       rhs = t.fromRHS
+                       assert(t.rhs() != nil || t.allowNilRHS)
+                       rhs = t.rhs()
 
                default:
                        u = rhs // any type literal works
@@ -738,7 +748,7 @@ func (n *Named) expandRHS() (rhs Type) {
        }
 
        assert(!n.stateHas(unpacked))
-       assert(n.inst.orig.stateHas(unpacked | lazyLoaded))
+       assert(n.inst.orig.stateHas(lazyLoaded | unpacked))
 
        if n.inst.ctxt == nil {
                n.inst.ctxt = NewContext()
@@ -763,7 +773,7 @@ func (n *Named) expandRHS() (rhs Type) {
                ctxt = check.context()
        }
 
-       rhs = check.subst(n.obj.pos, orig.fromRHS, m, n, ctxt)
+       rhs = check.subst(n.obj.pos, orig.rhs(), m, n, ctxt)
 
        // TODO(markfreeman): Can we handle this in substitution?
        // If the RHS is an interface, we must set the receiver of interface methods
@@ -772,7 +782,7 @@ func (n *Named) expandRHS() (rhs Type) {
                if methods, copied := replaceRecvType(iface.methods, orig, n); copied {
                        // If the RHS doesn't use type parameters, it may not have been
                        // substituted; we need to craft a new interface first.
-                       if iface == orig.fromRHS {
+                       if iface == orig.rhs() {
                                assert(iface.complete) // otherwise we are copying incomplete data
 
                                crafted := check.newInterface()
index 46c7fae14fc48f0710f565c0522982829cf5cab8..c23316da82fff4496167299fc120e31de503dedc 100644 (file)
@@ -144,7 +144,8 @@ func (check *Checker) validType0(pos token.Pos, typ Type, nest, path []*Named) b
                // Every type added to nest is also added to path; thus every type that is in nest
                // must also be in path (invariant). But not every type in path is in nest, since
                // nest may be pruned (see below, *TypeParam case).
-               if !check.validType0(pos, t.Origin().fromRHS, append(nest, t), append(path, t)) {
+               t.Origin().unpack()
+               if !check.validType0(pos, t.Origin().rhs(), append(nest, t), append(path, t)) {
                        return false
                }