go/types, types2: pass *TypeName instead of *Named as def (defined) type

This permits using the same mechanism not just for *Named types but
also future Alias types.

Change-Id: Ia8dee413d8dff7b08ab073ce03a4779603c4f396
Reviewed-on: https://go-review.googlesource.com/c/go/+/524897
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
This commit is contained in:
Robert Griesemer 2023-08-31 15:06:03 -07:00 committed by Gopher Robot
parent 1ac43e762c
commit 01987d3117
10 changed files with 90 additions and 70 deletions

View file

@ -658,7 +658,7 @@ var cgoPrefixes = [...]string{
"_Cmacro_", // function to evaluate the expanded expression
}
func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *Named, wantType bool) {
func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *TypeName, wantType bool) {
// these must be declared before the "goto Error" statements
var (
obj Object
@ -759,8 +759,8 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *Named, w
switch x.mode {
case typexpr:
// don't crash for "type T T.x" (was go.dev/issue/51509)
if def != nil && x.typ == def {
check.cycleError([]Object{def.obj})
if def != nil && def.typ == x.typ {
check.cycleError([]Object{def})
goto Error
}
case builtin:

View file

@ -55,7 +55,7 @@ func pathString(path []Object) string {
// objDecl type-checks the declaration of obj in its respective (file) environment.
// For the meaning of def, see Checker.definedType, in typexpr.go.
func (check *Checker) objDecl(obj Object, def *Named) {
func (check *Checker) objDecl(obj Object, def *TypeName) {
if check.conf.Trace && obj.Type() == nil {
if check.indent == 0 {
fmt.Println() // empty line between top-level objects for readability
@ -483,7 +483,7 @@ func (check *Checker) isImportedConstraint(typ Type) bool {
return u != nil && !u.IsMethodSet()
}
func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named) {
func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *TypeName) {
assert(obj.typ == nil)
var rhs Type
@ -514,7 +514,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named
// type definition or generic type declaration
named := check.newNamed(obj, nil, nil)
def.setUnderlying(named)
setDefType(def, named)
if tdecl.TParamList != nil {
check.openScope(tdecl, "type parameters")
@ -523,7 +523,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *Named
}
// determine underlying type of named
rhs = check.definedType(tdecl.Type, named)
rhs = check.definedType(tdecl.Type, obj)
assert(rhs != nil)
named.fromRHS = rhs

View file

@ -117,7 +117,7 @@ func (t *Interface) cleanup() {
t.embedPos = nil
}
func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *Named) {
func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *TypeName) {
addEmbedded := func(pos syntax.Pos, typ Type) {
ityp.embeddeds = append(ityp.embeddeds, typ)
if ityp.embedPos == nil {
@ -152,7 +152,9 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType
// use named receiver type if available (for better error messages)
var recvTyp Type = ityp
if def != nil {
recvTyp = def
if named, _ := def.typ.(*Named); named != nil {
recvTyp = named
}
}
sig.recv = NewVar(f.Name.Pos(), check.pkg, "", recvTyp)

View file

@ -550,12 +550,6 @@ loop:
return u
}
func (n *Named) setUnderlying(typ Type) {
if n != nil {
n.underlying = typ
}
}
func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
n.resolve()
// If n is an instance, we may not have yet instantiated all of its methods.

View file

@ -18,7 +18,7 @@ import (
// If an error occurred, x.mode is set to invalid.
// For the meaning of def, see Checker.definedType, below.
// If wantType is set, the identifier e is expected to denote a type.
func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType bool) {
func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType bool) {
x.mode = invalid
x.expr = e
@ -173,10 +173,10 @@ func (check *Checker) validVarType(e syntax.Expr, typ Type) {
}
// definedType is like typ but also accepts a type name def.
// If def != nil, e is the type specification for the defined type def, declared
// in a type declaration, and def.underlying will be set to the type of e before
// any components of e are type-checked.
func (check *Checker) definedType(e syntax.Expr, def *Named) Type {
// If def != nil, e is the type specification for the type named def, declared
// in a type declaration, and def.typ.underlying will be set to the type of e
// before any components of e are type-checked.
func (check *Checker) definedType(e syntax.Expr, def *TypeName) Type {
typ := check.typInternal(e, def)
assert(isTyped(typ))
if isGeneric(typ) {
@ -212,7 +212,7 @@ func goTypeName(typ Type) string {
// typInternal drives type checking of types.
// Must only be called by definedType or genericType.
func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
func (check *Checker) typInternal(e0 syntax.Expr, def *TypeName) (T Type) {
if check.conf.Trace {
check.trace(e0.Pos(), "-- type %s", e0)
check.indent++
@ -243,7 +243,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
switch x.mode {
case typexpr:
typ := x.typ
def.setUnderlying(typ)
setDefType(def, typ)
return typ
case invalid:
// ignore - error reported before
@ -260,7 +260,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
switch x.mode {
case typexpr:
typ := x.typ
def.setUnderlying(typ)
setDefType(def, typ)
return typ
case invalid:
// ignore - error reported before
@ -281,7 +281,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
case *syntax.ArrayType:
typ := new(Array)
def.setUnderlying(typ)
setDefType(def, typ)
if e.Len != nil {
typ.len = check.arrayLength(e.Len)
} else {
@ -297,7 +297,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
case *syntax.SliceType:
typ := new(Slice)
def.setUnderlying(typ)
setDefType(def, typ)
typ.elem = check.varType(e.Elem)
return typ
@ -309,7 +309,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
case *syntax.StructType:
typ := new(Struct)
def.setUnderlying(typ)
setDefType(def, typ)
check.structType(typ, e)
return typ
@ -317,7 +317,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
if e.Op == syntax.Mul && e.Y == nil {
typ := new(Pointer)
typ.base = Typ[Invalid] // avoid nil base in invalid recursive type declaration
def.setUnderlying(typ)
setDefType(def, typ)
typ.base = check.varType(e.X)
// If typ.base is invalid, it's unlikely that *base is particularly
// useful - even a valid dereferenciation will lead to an invalid
@ -334,19 +334,19 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
case *syntax.FuncType:
typ := new(Signature)
def.setUnderlying(typ)
setDefType(def, typ)
check.funcType(typ, nil, nil, e)
return typ
case *syntax.InterfaceType:
typ := check.newInterface()
def.setUnderlying(typ)
setDefType(def, typ)
check.interfaceType(typ, e, def)
return typ
case *syntax.MapType:
typ := new(Map)
def.setUnderlying(typ)
setDefType(def, typ)
typ.key = check.varType(e.Key)
typ.elem = check.varType(e.Value)
@ -371,7 +371,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
case *syntax.ChanType:
typ := new(Chan)
def.setUnderlying(typ)
setDefType(def, typ)
dir := SendRecv
switch e.Dir {
@ -396,11 +396,25 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
}
typ := Typ[Invalid]
def.setUnderlying(typ)
setDefType(def, typ)
return typ
}
func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *Named) (res Type) {
func setDefType(def *TypeName, typ Type) {
if def != nil {
switch t := def.typ.(type) {
// case *_Alias:
case *Basic:
assert(t == Typ[Invalid])
case *Named:
t.underlying = typ
default:
panic(fmt.Sprintf("unexpected type %T", t))
}
}
}
func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *TypeName) (res Type) {
if check.conf.Trace {
check.trace(x.Pos(), "-- instantiating type %s with %s", x, xlist)
check.indent++
@ -428,13 +442,13 @@ func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *
// evaluate arguments
targs := check.typeList(xlist)
if targs == nil {
def.setUnderlying(Typ[Invalid]) // avoid errors later due to lazy instantiation
setDefType(def, Typ[Invalid]) // avoid errors later due to lazy instantiation
return Typ[Invalid]
}
// create the instance
inst := asNamed(check.instance(x.Pos(), orig, targs, nil, check.context()))
def.setUnderlying(inst)
setDefType(def, inst)
// orig.tparams may not be set up, so we need to do expansion later.
check.later(func() {

View file

@ -660,7 +660,7 @@ var cgoPrefixes = [...]string{
"_Cmacro_", // function to evaluate the expanded expression
}
func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *Named, wantType bool) {
func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *TypeName, wantType bool) {
// these must be declared before the "goto Error" statements
var (
obj Object
@ -761,8 +761,8 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *Named, want
switch x.mode {
case typexpr:
// don't crash for "type T T.x" (was go.dev/issue/51509)
if def != nil && x.typ == def {
check.cycleError([]Object{def.obj})
if def != nil && def.typ == x.typ {
check.cycleError([]Object{def})
goto Error
}
case builtin:

View file

@ -53,7 +53,7 @@ func pathString(path []Object) string {
// objDecl type-checks the declaration of obj in its respective (file) environment.
// For the meaning of def, see Checker.definedType, in typexpr.go.
func (check *Checker) objDecl(obj Object, def *Named) {
func (check *Checker) objDecl(obj Object, def *TypeName) {
if check.conf._Trace && obj.Type() == nil {
if check.indent == 0 {
fmt.Println() // empty line between top-level objects for readability
@ -552,7 +552,7 @@ func (check *Checker) isImportedConstraint(typ Type) bool {
return u != nil && !u.IsMethodSet()
}
func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *TypeName) {
assert(obj.typ == nil)
var rhs Type
@ -583,7 +583,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
// type definition or generic type declaration
named := check.newNamed(obj, nil, nil)
def.setUnderlying(named)
setDefType(def, named)
if tdecl.TypeParams != nil {
check.openScope(tdecl, "type parameters")
@ -592,7 +592,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
}
// determine underlying type of named
rhs = check.definedType(tdecl.Type, named)
rhs = check.definedType(tdecl.Type, obj)
assert(rhs != nil)
named.fromRHS = rhs

View file

@ -156,7 +156,7 @@ func (t *Interface) cleanup() {
t.embedPos = nil
}
func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) {
func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *TypeName) {
addEmbedded := func(pos token.Pos, typ Type) {
ityp.embeddeds = append(ityp.embeddeds, typ)
if ityp.embedPos == nil {
@ -200,7 +200,9 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d
// use named receiver type if available (for better error messages)
var recvTyp Type = ityp
if def != nil {
recvTyp = def
if named, _ := def.typ.(*Named); named != nil {
recvTyp = named
}
}
sig.recv = NewVar(name.Pos(), check.pkg, "", recvTyp)

View file

@ -552,12 +552,6 @@ loop:
return u
}
func (n *Named) setUnderlying(typ Type) {
if n != nil {
n.underlying = typ
}
}
func (n *Named) lookupMethod(pkg *Package, name string, foldCase bool) (int, *Func) {
n.resolve()
// If n is an instance, we may not have yet instantiated all of its methods.

View file

@ -19,7 +19,7 @@ import (
// If an error occurred, x.mode is set to invalid.
// For the meaning of def, see Checker.definedType, below.
// If wantType is set, the identifier e is expected to denote a type.
func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool) {
func (check *Checker) ident(x *operand, e *ast.Ident, def *TypeName, wantType bool) {
x.mode = invalid
x.expr = e
@ -173,10 +173,10 @@ func (check *Checker) validVarType(e ast.Expr, typ Type) {
}
// definedType is like typ but also accepts a type name def.
// If def != nil, e is the type specification for the defined type def, declared
// in a type declaration, and def.underlying will be set to the type of e before
// any components of e are type-checked.
func (check *Checker) definedType(e ast.Expr, def *Named) Type {
// If def != nil, e is the type specification for the type named def, declared
// in a type declaration, and def.typ.underlying will be set to the type of e
// before any components of e are type-checked.
func (check *Checker) definedType(e ast.Expr, def *TypeName) Type {
typ := check.typInternal(e, def)
assert(isTyped(typ))
if isGeneric(typ) {
@ -212,7 +212,7 @@ func goTypeName(typ Type) string {
// typInternal drives type checking of types.
// Must only be called by definedType or genericType.
func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
func (check *Checker) typInternal(e0 ast.Expr, def *TypeName) (T Type) {
if check.conf._Trace {
check.trace(e0.Pos(), "-- type %s", e0)
check.indent++
@ -243,7 +243,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
switch x.mode {
case typexpr:
typ := x.typ
def.setUnderlying(typ)
setDefType(def, typ)
return typ
case invalid:
// ignore - error reported before
@ -260,7 +260,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
switch x.mode {
case typexpr:
typ := x.typ
def.setUnderlying(typ)
setDefType(def, typ)
return typ
case invalid:
// ignore - error reported before
@ -283,13 +283,13 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
case *ast.ArrayType:
if e.Len == nil {
typ := new(Slice)
def.setUnderlying(typ)
setDefType(def, typ)
typ.elem = check.varType(e.Elt)
return typ
}
typ := new(Array)
def.setUnderlying(typ)
setDefType(def, typ)
// Provide a more specific error when encountering a [...] array
// rather than leaving it to the handling of the ... expression.
if _, ok := e.Len.(*ast.Ellipsis); ok {
@ -312,32 +312,32 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
case *ast.StructType:
typ := new(Struct)
def.setUnderlying(typ)
setDefType(def, typ)
check.structType(typ, e)
return typ
case *ast.StarExpr:
typ := new(Pointer)
typ.base = Typ[Invalid] // avoid nil base in invalid recursive type declaration
def.setUnderlying(typ)
setDefType(def, typ)
typ.base = check.varType(e.X)
return typ
case *ast.FuncType:
typ := new(Signature)
def.setUnderlying(typ)
setDefType(def, typ)
check.funcType(typ, nil, e)
return typ
case *ast.InterfaceType:
typ := check.newInterface()
def.setUnderlying(typ)
setDefType(def, typ)
check.interfaceType(typ, e, def)
return typ
case *ast.MapType:
typ := new(Map)
def.setUnderlying(typ)
setDefType(def, typ)
typ.key = check.varType(e.Key)
typ.elem = check.varType(e.Value)
@ -362,7 +362,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
case *ast.ChanType:
typ := new(Chan)
def.setUnderlying(typ)
setDefType(def, typ)
dir := SendRecv
switch e.Dir {
@ -387,11 +387,25 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
}
typ := Typ[Invalid]
def.setUnderlying(typ)
setDefType(def, typ)
return typ
}
func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (res Type) {
func setDefType(def *TypeName, typ Type) {
if def != nil {
switch t := def.typ.(type) {
// case *_Alias:
case *Basic:
assert(t == Typ[Invalid])
case *Named:
t.underlying = typ
default:
panic(fmt.Sprintf("unexpected type %T", t))
}
}
}
func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *TypeName) (res Type) {
if check.conf._Trace {
check.trace(ix.Pos(), "-- instantiating type %s with %s", ix.X, ix.Indices)
check.indent++
@ -419,13 +433,13 @@ func (check *Checker) instantiatedType(ix *typeparams.IndexExpr, def *Named) (re
// evaluate arguments
targs := check.typeList(ix.Indices)
if targs == nil {
def.setUnderlying(Typ[Invalid]) // avoid errors later due to lazy instantiation
setDefType(def, Typ[Invalid]) // avoid errors later due to lazy instantiation
return Typ[Invalid]
}
// create the instance
inst := asNamed(check.instance(ix.Pos(), orig, targs, nil, check.context()))
def.setUnderlying(inst)
setDefType(def, inst)
// orig.tparams may not be set up, so we need to do expansion later.
check.later(func() {