diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 46ae273131..706c1f8374 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -644,7 +644,14 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeNam } if targs != nil { // obj denotes a valid contract that is instantiated with targs - check.errorf(f.Type.Pos(), "explicit contract instantiation not yet implemented") + // Use contract's matching type parameter bound and + // instantiate it with the actual type arguments targs. + // TODO(gri) this is not correct when arguments are permutated. Investigate! + for i, bound := range obj.Bounds { + pos := unparen(f.Type).(*ast.CallExpr).Args[i].Pos() // we must have an *ast.CallExpr + //check.dump("%v: bound %d = %v, under = %v, args = %v", pos, i, bound, bound.Underlying(), targs) + setBoundAt(index+i, check.instantiate(pos, bound, targs, nil)) + } } else { // obj denotes a valid uninstantiated contract => // use the declared type parameters as "arguments" @@ -653,8 +660,7 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeNam goto next } // Use contract's matching type parameter bound and - // instantiate it with the actual type parameters - // (== targs) present. + // instantiate it with the actual type arguments targs. targs := make([]Type, len(f.Names)) for i, tparam := range tparams[index : index+len(f.Names)] { targs[i] = tparam.typ diff --git a/src/go/types/testdata/contracts.go2 b/src/go/types/testdata/contracts.go2 index 43f228b471..2a566213a9 100644 --- a/src/go/types/testdata/contracts.go2 +++ b/src/go/types/testdata/contracts.go2 @@ -218,6 +218,32 @@ func _(type F, C FloatComplex)(c C) { c = C(complex(fre, fim)) } +// Use of instantiated contracts + +contract ABC(A, B, C) { + A a() + B b() + C int, float64 +} + +func fa(type A, B, C) (A, B, C) +func fb(type A, B, C ABC) (A, B, C) +func fc(type A, B, C ABC(A, B, C)) (A, B, C) +func fd(type A, B, C ABC(B, C, A)) (A, B, C) + +type tA int; func (tA) a() +type tB float64; func (tB) b() + +func _() { + var a tA + var b tB + fa(a, b, 0) + fb(a, b, 0) + fc(a, b, 0) + fd(a, b, 0) + fd(tA, tB, int)(a, b, 0) // TODO(gri) this should fail - investigate! +} + // -------------------------------------------------------------------------------------- // Parameterized interfaces as contracts diff --git a/src/go/types/testdata/tmp.go2 b/src/go/types/testdata/tmp.go2 index a7779ea8d3..2ca03ef732 100644 --- a/src/go/types/testdata/tmp.go2 +++ b/src/go/types/testdata/tmp.go2 @@ -27,8 +27,25 @@ type II interface{ var _ I = II(nil) */ -contract C(T) { - T op(T) T +contract C(A, B) { + A a() + B b() } -func f(type T C /* ERROR not yet implemented */ (T))(x, y T) T //{ return x.op(y) } +//func fa(type A, B, C) (A, B, C) +//func fb(type A, B, C ABC) (A, B, C) +//func fc(type A, B, C ABC(A, B, C)) (A, B, C) +func fd(type A, B C(B, A)) () + +type tA struct{}; func (tA) a() +type tB struct{}; func (tB) b() + +func _() { + //var a tA + //var b tB + //fa(a, b, 0) + //(a, b, 0) + //(a, b, 0) + //fd(a, b, 0) + fd(tA, tB)() // TODO(gri) this should fail +} \ No newline at end of file