mirror of https://github.com/golang/go.git
go/types: implemented comparison of parameterized types; minor bug fixes
Also: Added -h flag to test framework; setting -h causes a panic when an error is reported (for debugging). Change-Id: Ib45d4ef38769f2ecdd3ce53fa3aed9fd99ef6bc8
This commit is contained in:
parent
06ce58509d
commit
de712f2df8
|
|
@ -18,7 +18,6 @@ import (
|
|||
const (
|
||||
debug = false // leave on during development
|
||||
trace = false // turn on for detailed type resolution traces
|
||||
halt = false // panic on error
|
||||
)
|
||||
|
||||
// If Strict is set, the type-checker enforces additional
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ var tests = [][]string{
|
|||
{"testdata/issue6977.src"},
|
||||
|
||||
// Go 2 tests (type parameters and contracts)
|
||||
// {"testdata/tmp.go2"}, // used for ad-hoc tests - file contents transient, excluded from tests
|
||||
{"testdata/tmp.go2"}, // used for ad-hoc tests - file contents transient
|
||||
{"testdata/typeparams.go2"},
|
||||
{"testdata/typeinst.go2"},
|
||||
{"testdata/typeinst2.go2"},
|
||||
|
|
|
|||
|
|
@ -90,10 +90,6 @@ func (check *Checker) err(pos token.Pos, msg string, soft bool) {
|
|||
if trace {
|
||||
check.trace(pos, "ERROR: %s", msg)
|
||||
}
|
||||
|
||||
if halt {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
f := check.conf.Error
|
||||
if f == nil {
|
||||
|
|
|
|||
|
|
@ -308,7 +308,22 @@ func (check *Checker) identical0(x, y Type, cmpTags bool, p *ifacePair, tparams
|
|||
}
|
||||
|
||||
case *Parameterized:
|
||||
panic("internal error: cannot compare uninstantiated parametrized types for identity")
|
||||
// Two parameterized types are identical if the type name and the parameters are identical.
|
||||
// TODO(gri) This ignores alias types for now. E.g., type A(type P) = P; A(int) == int does
|
||||
// not work.
|
||||
if y, ok := y.(*Parameterized); ok {
|
||||
if x.tname != y.tname {
|
||||
return false
|
||||
}
|
||||
assert(len(x.targs) == len(y.targs)) // since x, y have identical tname
|
||||
for i, x := range x.targs {
|
||||
y := y.targs[i]
|
||||
if !identical(x, y, cmpTags, p, tparams) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
case *TypeParam:
|
||||
if y, ok := y.(*TypeParam); ok {
|
||||
|
|
|
|||
|
|
@ -4,8 +4,14 @@
|
|||
|
||||
package p
|
||||
|
||||
type List(type P) []P
|
||||
type List(type E) []E
|
||||
|
||||
type T(type P) List(P)
|
||||
func f(type P) (x P) List(P) {
|
||||
return List(P){x}
|
||||
}
|
||||
|
||||
var _ T(int) //= T(int)(List(int){1, 2, 3})
|
||||
var (
|
||||
_ []int = f(0)
|
||||
_ []float32 = f(float32)(10)
|
||||
//_ []List(int) = f(List(int){})
|
||||
)
|
||||
|
|
|
|||
|
|
@ -59,7 +59,3 @@ var _ List(List(List(int)))
|
|||
type T3(type P) List(P)
|
||||
|
||||
var _ T3(int) = T3(int)(List(int){1, 2, 3})
|
||||
|
||||
|
||||
// TODO
|
||||
// type map maps to unique name found in scopes?
|
||||
|
|
|
|||
|
|
@ -32,5 +32,5 @@ type T3(type P) T1(T2(P, P))
|
|||
func _() {
|
||||
var x1 T3(int)
|
||||
var x2 T2(int, int)
|
||||
x1.f1.f2.f2 = x2
|
||||
x1.f1.f2 = x2
|
||||
}
|
||||
|
|
@ -556,7 +556,7 @@ func (t *Interface) Underlying() Type { return t }
|
|||
func (m *Map) Underlying() Type { return m }
|
||||
func (c *Chan) Underlying() Type { return c }
|
||||
func (t *Named) Underlying() Type { return t.underlying }
|
||||
func (p *Parameterized) Underlying() Type { return p } // TODO(gri) is this correct?
|
||||
func (p *Parameterized) Underlying() Type { return p.tname.typ.Underlying() }
|
||||
func (c *Contract) Underlying() Type { return c }
|
||||
func (c *TypeParam) Underlying() Type { return c }
|
||||
|
||||
|
|
|
|||
|
|
@ -275,7 +275,11 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type {
|
|||
case *ast.CallExpr:
|
||||
typ := new(Parameterized)
|
||||
def.setUnderlying(typ)
|
||||
check.parameterizedType(typ, e)
|
||||
if check.parameterizedType(typ, e) {
|
||||
return typ
|
||||
}
|
||||
// TODO(gri) If we have a cycle and we reach here, "leafs" of
|
||||
// the cycle may refer to a not fully set up Parameterized typ.
|
||||
|
||||
case *ast.ParenExpr:
|
||||
return check.definedType(e.X, def)
|
||||
|
|
@ -447,18 +451,18 @@ func (check *Checker) typeList(list []ast.Expr) []Type {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (check *Checker) parameterizedType(typ *Parameterized, e *ast.CallExpr) {
|
||||
func (check *Checker) parameterizedType(typ *Parameterized, e *ast.CallExpr) bool {
|
||||
// TODO(gri) This code cannot handle type aliases at the moment.
|
||||
// Probably need to do the name lookup here.
|
||||
t := check.typ(e.Fun)
|
||||
if t == Typ[Invalid] {
|
||||
return // error already reported
|
||||
return false // error already reported
|
||||
}
|
||||
|
||||
named, _ := t.(*Named)
|
||||
if named == nil || named.obj == nil || !named.obj.IsParameterized() {
|
||||
check.errorf(e.Pos(), "%s is not a parametrized type", t)
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
// the number of supplied types must match the number of type parameters
|
||||
|
|
@ -467,13 +471,13 @@ func (check *Checker) parameterizedType(typ *Parameterized, e *ast.CallExpr) {
|
|||
if len(e.Args) != len(tname.tparams) {
|
||||
// TODO(gri) provide better error message
|
||||
check.errorf(e.Pos(), "got %d arguments but %d type parameters", len(e.Args), len(tname.tparams))
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
// evaluate arguments
|
||||
args := check.typeList(e.Args)
|
||||
if args == nil {
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO(gri) If none of the arguments is parameterized than we can instantiate the type.
|
||||
|
|
@ -484,6 +488,7 @@ func (check *Checker) parameterizedType(typ *Parameterized, e *ast.CallExpr) {
|
|||
// complete parameterized type
|
||||
typ.tname = tname
|
||||
typ.targs = args
|
||||
return true
|
||||
}
|
||||
|
||||
func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicOk bool) (params []*Var, variadic bool) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue