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:
parent
a8fe098a12
commit
196102d046
@ -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)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user