From 150704f7388fd786d694a505da5668df323a1473 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 29 May 2019 20:34:27 -0700 Subject: [PATCH] go/types: implemented a few TODOs (minor progress) --- src/go/types/contracts.go | 29 ++++++++++++++++++++++++----- src/go/types/testdata/contracts.go2 | 4 ++-- src/go/types/typexpr.go | 4 ++++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/go/types/contracts.go b/src/go/types/contracts.go index 5c1c1620a0..84a03fa71b 100644 --- a/src/go/types/contracts.go +++ b/src/go/types/contracts.go @@ -95,8 +95,8 @@ func (check *Checker) contractType(contr *Contract, e *ast.ContractType) { if econtr == nil { check.invalidAST(c.Type.Pos(), "invalid embedded contract %s", econtr) } - // etyp := check.typ(c.Type) - // _ = etyp + etyp := check.typ(c.Type) + _ = etyp // TODO(gri) complete this check.errorf(c.Type.Pos(), "%s: contract embedding not yet implemented", c.Type) } @@ -129,6 +129,8 @@ func (check *Checker) contractType(contr *Contract, e *ast.ContractType) { } } +// TODO(gri) does this simply check for the absence of defined types? +// (if so, should choose a better name) func (check *Checker) typeConstraint(typ Type, why *string) bool { switch t := typ.(type) { case *Basic: @@ -146,11 +148,27 @@ func (check *Checker) typeConstraint(typ Type, why *string) bool { case *Pointer: return check.typeConstraint(t.base, why) case *Tuple: - panic("tuple type checking unimplemented") + if t == nil { + return true + } + for _, v := range t.vars { + if !check.typeConstraint(v.typ, why) { + return false + } + } case *Signature: - panic("signature type checking unimplemented") + if len(t.tparams) != 0 { + panic("type parameter in function type") + } + return (t.recv == nil || check.typeConstraint(t.recv.typ, why)) && + check.typeConstraint(t.params, why) && + check.typeConstraint(t.results, why) case *Interface: - panic("interface type checking unimplemented") + for _, m := range t.allMethods { + if !check.typeConstraint(m.typ, why) { + return false + } + } case *Map: return check.typeConstraint(t.key, why) && check.typeConstraint(t.elem, why) case *Chan: @@ -159,6 +177,7 @@ func (check *Checker) typeConstraint(typ Type, why *string) bool { *why = check.sprintf("%s is not a type literal", t) return false case *Contract: + // TODO(gri) we shouldn't reach here *why = check.sprintf("%s is not a type", t) return false case *TypeParam: diff --git a/src/go/types/testdata/contracts.go2 b/src/go/types/testdata/contracts.go2 index 930ba5ca23..28018111ea 100644 --- a/src/go/types/testdata/contracts.go2 +++ b/src/go/types/testdata/contracts.go2 @@ -37,7 +37,7 @@ contract _(A, B) { // type constraints // Types may be declared multiple times. // TODO(gri) The "correct" way of doing this is perhaps to allow multiple declarations -// only they appear though embedding (where they are harder to avoid), but not in general. +// only when they appear though embedding (where they are harder to avoid), but not in general. contract _(A) { A A } contract _(A) { A B /* ERROR undeclared name: B */ } contract _(A) { A int } @@ -50,5 +50,5 @@ contract _(A, B) { A B } // embedded contracts contract E() {} contract _() { - E /* ERROR embedding not yet implemented */ () + //E /* ERROR embedding not yet implemented */ () } diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 2bb42dd856..831dc9cb4a 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -263,6 +263,10 @@ func (check *Checker) typInternal(e ast.Expr, def *Named) Type { check.errorf(x.pos(), "%s is not a type", &x) } + // case *ast.CallExpr: + // check.typ(e.Fun) + // panic("type instantiation not yet implemented") + case *ast.ParenExpr: return check.definedType(e.X, def)