From 312a8ea57c9a13774c3a7b2e6cbb90629dd178ad Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 8 Jan 2020 21:56:21 -0800 Subject: [PATCH] go/types: initial code to handle instantiated contract expressions New code not yet used. Snapshot. Change-Id: Id3f9172d5ebd198d34b66707eaf429b791374ea1 --- src/go/types/decl.go | 52 +++++++++++++++++++++++++++++++++++ src/go/types/testdata/tmp.go2 | 11 +++----- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/go/types/decl.go b/src/go/types/decl.go index 849560ffaa..f8e2bf2d7b 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -682,6 +682,58 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeNam return } +func (check *Checker) unpackContractExpr(x ast.Expr) (obj *Contract, targs []Type) { + // permit any parenthesized expression + x = unparen(x) + + // a call expression might be an instantiated contract => unpack arguments + var call *ast.CallExpr + if call, _ = x.(*ast.CallExpr); call != nil { + x = call.Fun + } + + // check if x denotes a contract + if ident, _ := x.(*ast.Ident); ident != nil { + if obj, _ = check.lookup(ident.Name).(*Contract); obj != nil { + // set up contract if not yet done + if obj.typ == nil { + check.objDecl(obj, nil) + if obj.typ == Typ[Invalid] { + goto Error // we have a contract but it's broken + } + } + if call != nil { + // collect type arguments + if len(call.Args) != len(obj.TParams) { + check.errorf(call.Pos(), "%d type parameters but contract expects %d", len(call.Args), len(obj.TParams)) + goto Error + } + for _, arg := range call.Args { + if targ := check.typ(arg); targ != Typ[Invalid] { + targs = append(targs, targ) + } + } + if len(targs) != len(call.Args) { + // some arguments were invalid + obj.typ = Typ[Invalid] + return + } + } + } + } + + return + +Error: + if call != nil { + check.use(call.Args...) + } + if obj != nil { + obj.typ = Typ[Invalid] + } + return +} + func (check *Checker) declareTypeParams(tparams []*TypeName, names []*ast.Ident, bound Type) []*TypeName { for _, name := range names { tpar := NewTypeName(name.Pos(), check.pkg, name.Name, nil) diff --git a/src/go/types/testdata/tmp.go2 b/src/go/types/testdata/tmp.go2 index 3076e96ed2..97242bb0d7 100644 --- a/src/go/types/testdata/tmp.go2 +++ b/src/go/types/testdata/tmp.go2 @@ -27,11 +27,8 @@ type II interface{ var _ I = II(nil) */ -type T(type P) int - -func (_ T(P)) m() int - -func _() { - // var x T(int) - // _ = x.m() +contract C(T) { + T op(T) T } + +func f(type T ((C)))(x, y T) T //{ return x.op(y) }