1
0
mirror of https://github.com/golang/go synced 2024-11-11 23:20:24 -07:00

[dev.typeparams] cmd/compile/internal/types2: review of typexpr.go

This code matches go/types/typexpr but for the necessary adjustments
because of the use of package syntax rather than go/ast, and for the
code being part of cmd/compile/internal/types2 rather than go/types.

Primary differences to go.types/typexpr.go:
- syntax.FuncType doesn't carry type parameters
- type instantiations are represented using syntax.IndexExpr
  nodes
- there's an explicit syntax.SliceType
- *x is expressed as a unary operation, not a StarExpr
- grouped fields are identified by identical pointer types

To see the changes copied from recent go/types changes, compare Patchsets 1 and 2.

Change-Id: I8aa9452882d1f5e9529c52a30c7c8e65f3fcbb43
Reviewed-on: https://go-review.googlesource.com/c/go/+/281545
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2021-01-05 09:46:23 -08:00
parent a8fe098a12
commit 196102d046

View File

@ -1,4 +1,3 @@
// UNREVIEWED
// Copyright 2013 The Go Authors. All rights reserved. // Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -230,13 +229,13 @@ func isubst(x syntax.Expr, smap map[*syntax.Name]*syntax.Name) syntax.Expr {
case *syntax.ListExpr: case *syntax.ListExpr:
var elems []syntax.Expr var elems []syntax.Expr
for i, elem := range n.ElemList { for i, elem := range n.ElemList {
Elem := isubst(elem, smap) new := isubst(elem, smap)
if Elem != elem { if new != elem {
if elems == nil { if elems == nil {
elems = make([]syntax.Expr, len(n.ElemList)) elems = make([]syntax.Expr, len(n.ElemList))
copy(elems, n.ElemList) copy(elems, n.ElemList)
} }
elems[i] = Elem elems[i] = new
} }
} }
if elems != nil { if elems != nil {
@ -315,6 +314,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
for i, t := range sig.rparams { for i, t := range sig.rparams {
list[i] = t.typ list[i] = t.typ
} }
smap := makeSubstMap(recvTParams, list)
for i, tname := range sig.rparams { for i, tname := range sig.rparams {
bound := recvTParams[i].typ.(*TypeParam).bound bound := recvTParams[i].typ.(*TypeParam).bound
// bound is (possibly) parameterized in the context of the // bound is (possibly) parameterized in the context of the
@ -323,7 +323,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
// TODO(gri) should we assume now that bounds always exist? // TODO(gri) should we assume now that bounds always exist?
// (no bound == empty interface) // (no bound == empty interface)
if bound != nil { if bound != nil {
bound = check.subst(tname.pos, bound, makeSubstMap(recvTParams, list)) bound = check.subst(tname.pos, bound, smap)
tname.typ.(*TypeParam).bound = bound tname.typ.(*TypeParam).bound = bound
} }
} }
@ -646,9 +646,9 @@ func (check *Checker) instantiatedType(x syntax.Expr, targs []syntax.Expr, def *
unreachable() // should have been caught by genericType unreachable() // should have been caught by genericType
} }
// create a new type Instance rather than instantiate the type // create a new type instance rather than instantiate the type
// TODO(gri) should do argument number check here rather than // TODO(gri) should do argument number check here rather than
// when instantiating the type? // when instantiating the type?
typ := new(instance) typ := new(instance)
def.setUnderlying(typ) def.setUnderlying(typ)
@ -1118,8 +1118,9 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
add(f.Name, false, f.Name.Pos()) add(f.Name, false, f.Name.Pos())
} else { } else {
// embedded field // embedded field
// spec: "An embedded type must be specified as a (possibly parenthesized) type name T or // spec: "An embedded type must be specified as a type name T or as a
// as a pointer to a non-interface type name *T, and T itself may not be a pointer type." // pointer to a non-interface type name *T, and T itself may not be a
// pointer type."
pos := startPos(f.Type) pos := startPos(f.Type)
name := embeddedFieldIdent(f.Type) name := embeddedFieldIdent(f.Type)
if name == nil { if name == nil {
@ -1129,6 +1130,7 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
continue continue
} }
add(name, true, pos) add(name, true, pos)
// Because we have a name, typ must be of the form T or *T, where T is the name // Because we have a name, typ must be of the form T or *T, where T is the name
// of a (named or alias) type, and t (= deref(typ)) must be the type of T. // of a (named or alias) type, and t (= deref(typ)) must be the type of T.
// We must delay this check to the end because we don't want to instantiate // We must delay this check to the end because we don't want to instantiate
@ -1204,20 +1206,18 @@ func (check *Checker) collectTypeConstraints(pos syntax.Pos, types []syntax.Expr
list = append(list, typ) list = append(list, typ)
} }
// Ensure that each type is only present once in the type list. // Ensure that each type is only present once in the type list. Types may be
// Types may be interfaces, which may not be complete yet. It's // interfaces, which may not be complete yet. It's ok to do this check at the
// ok to do this check at the end because it's not a requirement // end because it's not a requirement for correctness of the code.
// for correctness of the code. // Note: This is a quadratic algorithm, but type lists tend to be short.
check.atEnd(func() { check.atEnd(func() {
uniques := make([]Type, 0, len(list)) // assume all types are unique
for i, t := range list { for i, t := range list {
if t := t.Interface(); t != nil { if t := t.Interface(); t != nil {
check.completeInterface(types[i].Pos(), t) check.completeInterface(types[i].Pos(), t)
} }
if includes(uniques, t) { if includes(list[:i], t) {
check.softErrorf(types[i], "duplicate type %s in type list", t) check.softErrorf(types[i], "duplicate type %s in type list", t)
} }
uniques = append(uniques, t)
} }
}) })