mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
go/types, types2: wrap Named.fromRHS into Named.rhs
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>
This commit is contained in:
parent
b2af92270f
commit
d8a32f3d4b
4 changed files with 36 additions and 14 deletions
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue