go/types: initial code to handle instantiated contract expressions

New code not yet used. Snapshot.

Change-Id: Id3f9172d5ebd198d34b66707eaf429b791374ea1
This commit is contained in:
Robert Griesemer 2020-01-08 21:56:21 -08:00
parent 3c2505cae9
commit 312a8ea57c
2 changed files with 56 additions and 7 deletions

View File

@ -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)

View File

@ -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) }