mirror of
https://github.com/golang/go
synced 2024-09-24 05:20:13 -06: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:
parent
a8fe098a12
commit
196102d046
@ -1,4 +1,3 @@
|
||||
// UNREVIEWED
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// 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:
|
||||
var elems []syntax.Expr
|
||||
for i, elem := range n.ElemList {
|
||||
Elem := isubst(elem, smap)
|
||||
if Elem != elem {
|
||||
new := isubst(elem, smap)
|
||||
if new != elem {
|
||||
if elems == nil {
|
||||
elems = make([]syntax.Expr, len(n.ElemList))
|
||||
copy(elems, n.ElemList)
|
||||
}
|
||||
elems[i] = Elem
|
||||
elems[i] = new
|
||||
}
|
||||
}
|
||||
if elems != nil {
|
||||
@ -315,6 +314,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
|
||||
for i, t := range sig.rparams {
|
||||
list[i] = t.typ
|
||||
}
|
||||
smap := makeSubstMap(recvTParams, list)
|
||||
for i, tname := range sig.rparams {
|
||||
bound := recvTParams[i].typ.(*TypeParam).bound
|
||||
// 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?
|
||||
// (no bound == empty interface)
|
||||
if bound != nil {
|
||||
bound = check.subst(tname.pos, bound, makeSubstMap(recvTParams, list))
|
||||
bound = check.subst(tname.pos, bound, smap)
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
// when instantiating the type?
|
||||
// when instantiating the type?
|
||||
typ := new(instance)
|
||||
def.setUnderlying(typ)
|
||||
|
||||
@ -1118,8 +1118,9 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
|
||||
add(f.Name, false, f.Name.Pos())
|
||||
} else {
|
||||
// embedded field
|
||||
// spec: "An embedded type must be specified as a (possibly parenthesized) type name T or
|
||||
// as a pointer to a non-interface type name *T, and T itself may not be a pointer type."
|
||||
// spec: "An embedded type must be specified as a type name T or as a
|
||||
// pointer to a non-interface type name *T, and T itself may not be a
|
||||
// pointer type."
|
||||
pos := startPos(f.Type)
|
||||
name := embeddedFieldIdent(f.Type)
|
||||
if name == nil {
|
||||
@ -1129,6 +1130,7 @@ func (check *Checker) structType(styp *Struct, e *syntax.StructType) {
|
||||
continue
|
||||
}
|
||||
add(name, true, pos)
|
||||
|
||||
// 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.
|
||||
// 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)
|
||||
}
|
||||
|
||||
// Ensure that each type is only present once in the type list.
|
||||
// Types may be interfaces, which may not be complete yet. It's
|
||||
// ok to do this check at the end because it's not a requirement
|
||||
// for correctness of the code.
|
||||
// Ensure that each type is only present once in the type list. Types may be
|
||||
// interfaces, which may not be complete yet. It's ok to do this check at the
|
||||
// end because it's not a requirement for correctness of the code.
|
||||
// Note: This is a quadratic algorithm, but type lists tend to be short.
|
||||
check.atEnd(func() {
|
||||
uniques := make([]Type, 0, len(list)) // assume all types are unique
|
||||
for i, t := range list {
|
||||
if t := t.Interface(); t != nil {
|
||||
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)
|
||||
}
|
||||
uniques = append(uniques, t)
|
||||
}
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user