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
|
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
|
// Underlying returns the [underlying type] of the named type t, resolving all
|
||||||
// forwarding declarations. Underlying types are never Named, TypeParam, or
|
// forwarding declarations. Underlying types are never Named, TypeParam, or
|
||||||
// Alias types.
|
// Alias types.
|
||||||
|
|
@ -573,7 +583,7 @@ func (n *Named) Underlying() Type {
|
||||||
// The gccimporter depends on writing a nil underlying via NewNamed and
|
// The gccimporter depends on writing a nil underlying via NewNamed and
|
||||||
// immediately reading it back. Rather than putting that in Named.under
|
// immediately reading it back. Rather than putting that in Named.under
|
||||||
// and complicating things there, we just check for that special case here.
|
// and complicating things there, we just check for that special case here.
|
||||||
if n.fromRHS == nil {
|
if n.rhs() == nil {
|
||||||
assert(n.allowNilRHS)
|
assert(n.allowNilRHS)
|
||||||
if n.allowNilUnderlying {
|
if n.allowNilUnderlying {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -649,8 +659,8 @@ func (n *Named) resolveUnderlying() {
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
defer t.mu.Unlock()
|
defer t.mu.Unlock()
|
||||||
|
|
||||||
assert(t.fromRHS != nil || t.allowNilRHS)
|
assert(t.rhs() != nil || t.allowNilRHS)
|
||||||
rhs = t.fromRHS
|
rhs = t.rhs()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
u = rhs // any type literal works
|
u = rhs // any type literal works
|
||||||
|
|
@ -735,7 +745,7 @@ func (n *Named) expandRHS() (rhs Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!n.stateHas(unpacked))
|
assert(!n.stateHas(unpacked))
|
||||||
assert(n.inst.orig.stateHas(unpacked | lazyLoaded))
|
assert(n.inst.orig.stateHas(lazyLoaded | unpacked))
|
||||||
|
|
||||||
if n.inst.ctxt == nil {
|
if n.inst.ctxt == nil {
|
||||||
n.inst.ctxt = NewContext()
|
n.inst.ctxt = NewContext()
|
||||||
|
|
@ -760,7 +770,7 @@ func (n *Named) expandRHS() (rhs Type) {
|
||||||
ctxt = check.context()
|
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?
|
// TODO(markfreeman): Can we handle this in substitution?
|
||||||
// If the RHS is an interface, we must set the receiver of interface methods
|
// 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 methods, copied := replaceRecvType(iface.methods, orig, n); copied {
|
||||||
// If the RHS doesn't use type parameters, it may not have been
|
// If the RHS doesn't use type parameters, it may not have been
|
||||||
// substituted; we need to craft a new interface first.
|
// 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
|
assert(iface.complete) // otherwise we are copying incomplete data
|
||||||
|
|
||||||
crafted := check.newInterface()
|
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
|
// 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
|
// must also be in path (invariant). But not every type in path is in nest, since
|
||||||
// nest may be pruned (see below, *TypeParam case).
|
// 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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -565,6 +565,16 @@ func (t *Named) methodIndex(name string, foldCase bool) int {
|
||||||
return -1
|
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
|
// Underlying returns the [underlying type] of the named type t, resolving all
|
||||||
// forwarding declarations. Underlying types are never Named, TypeParam, or
|
// forwarding declarations. Underlying types are never Named, TypeParam, or
|
||||||
// Alias types.
|
// Alias types.
|
||||||
|
|
@ -576,7 +586,7 @@ func (n *Named) Underlying() Type {
|
||||||
// The gccimporter depends on writing a nil underlying via NewNamed and
|
// The gccimporter depends on writing a nil underlying via NewNamed and
|
||||||
// immediately reading it back. Rather than putting that in Named.under
|
// immediately reading it back. Rather than putting that in Named.under
|
||||||
// and complicating things there, we just check for that special case here.
|
// and complicating things there, we just check for that special case here.
|
||||||
if n.fromRHS == nil {
|
if n.rhs() == nil {
|
||||||
assert(n.allowNilRHS)
|
assert(n.allowNilRHS)
|
||||||
if n.allowNilUnderlying {
|
if n.allowNilUnderlying {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -652,8 +662,8 @@ func (n *Named) resolveUnderlying() {
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
defer t.mu.Unlock()
|
defer t.mu.Unlock()
|
||||||
|
|
||||||
assert(t.fromRHS != nil || t.allowNilRHS)
|
assert(t.rhs() != nil || t.allowNilRHS)
|
||||||
rhs = t.fromRHS
|
rhs = t.rhs()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
u = rhs // any type literal works
|
u = rhs // any type literal works
|
||||||
|
|
@ -738,7 +748,7 @@ func (n *Named) expandRHS() (rhs Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!n.stateHas(unpacked))
|
assert(!n.stateHas(unpacked))
|
||||||
assert(n.inst.orig.stateHas(unpacked | lazyLoaded))
|
assert(n.inst.orig.stateHas(lazyLoaded | unpacked))
|
||||||
|
|
||||||
if n.inst.ctxt == nil {
|
if n.inst.ctxt == nil {
|
||||||
n.inst.ctxt = NewContext()
|
n.inst.ctxt = NewContext()
|
||||||
|
|
@ -763,7 +773,7 @@ func (n *Named) expandRHS() (rhs Type) {
|
||||||
ctxt = check.context()
|
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?
|
// TODO(markfreeman): Can we handle this in substitution?
|
||||||
// If the RHS is an interface, we must set the receiver of interface methods
|
// 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 methods, copied := replaceRecvType(iface.methods, orig, n); copied {
|
||||||
// If the RHS doesn't use type parameters, it may not have been
|
// If the RHS doesn't use type parameters, it may not have been
|
||||||
// substituted; we need to craft a new interface first.
|
// 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
|
assert(iface.complete) // otherwise we are copying incomplete data
|
||||||
|
|
||||||
crafted := check.newInterface()
|
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
|
// 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
|
// must also be in path (invariant). But not every type in path is in nest, since
|
||||||
// nest may be pruned (see below, *TypeParam case).
|
// 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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue