From 01987d3117d46688f2a31b03cb0c463d322381e5 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 31 Aug 2023 15:06:03 -0700 Subject: [PATCH] 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 TryBot-Result: Gopher Robot Reviewed-by: Robert Griesemer Run-TryBot: Robert Griesemer Auto-Submit: Robert Griesemer --- src/cmd/compile/internal/types2/call.go | 6 +-- src/cmd/compile/internal/types2/decl.go | 8 +-- src/cmd/compile/internal/types2/interface.go | 6 ++- src/cmd/compile/internal/types2/named.go | 6 --- src/cmd/compile/internal/types2/typexpr.go | 54 ++++++++++++-------- src/go/types/call.go | 6 +-- src/go/types/decl.go | 8 +-- src/go/types/interface.go | 6 ++- src/go/types/named.go | 6 --- src/go/types/typexpr.go | 54 ++++++++++++-------- 10 files changed, 90 insertions(+), 70 deletions(-) diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 718c54913d..7b0fa10f32 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -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: diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index ccdfb19722..ed6b96eb09 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -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 diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index 3866975a91..a815ae2637 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -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) diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index fbe7f8ed12..81db4d84c1 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -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. diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 47e9dbae8b..b1a03bad3d 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -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() { diff --git a/src/go/types/call.go b/src/go/types/call.go index f581a8ad51..18c40629a5 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -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: diff --git a/src/go/types/decl.go b/src/go/types/decl.go index d347ede219..7d6a2aa039 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -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 diff --git a/src/go/types/interface.go b/src/go/types/interface.go index 3aed723542..0a258ce867 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -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) diff --git a/src/go/types/named.go b/src/go/types/named.go index a27143b6c1..440fc87891 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -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. diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 4c7c8a5ab5..d35c6d1263 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -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() { -- 2.50.0