diff --git a/src/go/types/call.go b/src/go/types/call.go index b312c58946..35a0a6c6c6 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -81,13 +81,32 @@ func (check *Checker) call(x *operand, e *ast.CallExpr) exprKind { args, _ := check.exprOrTypeList(e.Args) // instantiate function if needed - if n := len(args); len(sig.tparams) > 0 && n > 0 && args[0].mode == typexpr { + if n := len(args); n > 0 && len(sig.tparams) > 0 && args[0].mode == typexpr { // if the first argument is a type, assume we have explicit type arguments - x.mode = value - x.typ = check.instantiate(sig, sig.tparams, args) - if x.typ == nil { + + // we must have the correct number of type parameters + if n != len(sig.tparams) { + check.errorf(args[n-1].pos(), "got %d type arguments but want %d", n, len(sig.tparams)) x.mode = invalid + x.expr = e + return expression } + + // collect types + targs := make([]Type, n) + for i, a := range args { + if a.mode != typexpr { + // error was reported earlier + x.mode = invalid + x.expr = e + return expression + } + targs[i] = a.typ + } + + // instantiate function signature + x.typ = check.subst(x.pos(), sig, sig.tparams, targs) + x.mode = value x.expr = e return expression } @@ -172,26 +191,6 @@ func (check *Checker) exprOrTypeList(elist []ast.Expr) (xlist []*operand, ok boo return } -func (check *Checker) instantiate(typ Type, tparams []*TypeName, args []*operand) Type { - assert(typ != nil) - n := len(args) - if n != len(tparams) { - check.errorf(args[n-1].pos(), "got %d type arguments but want %d", n, len(tparams)) - return nil - } - // collect types - targs := make([]Type, n) - for i, a := range args { - if a.mode != typexpr { - // error was reported earlier - return nil - } - targs[i] = a.typ - } - // result is instantiated typ - return check.subst(token.NoPos, typ, tparams, targs) -} - func (check *Checker) exprList(elist []ast.Expr, allowCommaOk bool) (xlist []*operand, commaOk bool) { switch len(elist) { case 0: diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 9ea48ea657..2f3ce2eddf 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -14,7 +14,7 @@ import ( "strings" ) -func (check *Checker) instantiate2(pos token.Pos, named *Named, targs []Type) (res Type) { +func (check *Checker) instantiate(pos token.Pos, named *Named, targs []Type) (res Type) { tname := named.obj if check.conf.Trace { check.trace(pos, "-- instantiating %s with %s", tname, typeListString(targs)) diff --git a/src/go/types/testdata/tmp.go2 b/src/go/types/testdata/tmp.go2 index 54cabf9ba7..bcba30a448 100644 --- a/src/go/types/testdata/tmp.go2 +++ b/src/go/types/testdata/tmp.go2 @@ -4,6 +4,16 @@ package p +type T(type P) struct {} + +func (_ T(P)) m1() T(P) + +func (m T(P)) m2() { + // TODO(gri) this should be valid + var _ T(P) = m /* ERROR cannot use */ .m1() +} + +/* type Pair(type K) struct { key K } @@ -16,7 +26,6 @@ type Iterator(type K) struct { r Receiver(Pair(K)) } -/* func (r Receiver(T)) Values() T { return r.values } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 325ee3b429..77f96b7344 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -302,7 +302,7 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { } // instantiate parameterized type - typ = check.instantiate2(e.Pos(), named, targs) + typ = check.instantiate(e.Pos(), named, targs) def.setUnderlying(typ) return typ