mirror of https://github.com/golang/go.git
go/types: first steps towards contract embedding
Incomplete but all the major steps are outlined now. Change-Id: I05c0357072d8b2c9f85154d3dd14984d2134de62
This commit is contained in:
parent
af12458327
commit
b6a8a0a86f
|
|
@ -12,6 +12,7 @@ TODO
|
|||
- use []*TypeParam for tparams in subst? (unclear)
|
||||
|
||||
OPEN ISSUES
|
||||
- a contract that is used earlier than its declaration may not be set up yet
|
||||
- instantiating a parameterized function type w/o value or result parameters may have unexpected side-effects
|
||||
(we don't make a copy of the signature in some cases) - investigate
|
||||
- using a contract and enumerating type arguments currently leads to an error (e.g. func f(type T C(T)) (x T) ... )
|
||||
|
|
|
|||
|
|
@ -126,10 +126,42 @@ func (check *Checker) contractDecl(obj *Contract, cdecl *ast.ContractSpec) {
|
|||
if econtr == nil {
|
||||
check.invalidAST(c.Types[0].Pos(), "invalid embedded contract %s", econtr)
|
||||
}
|
||||
etyp := check.typ(c.Types[0])
|
||||
_ = etyp
|
||||
// TODO(gri) complete this
|
||||
check.errorf(c.Types[0].Pos(), "%s: contract embedding not yet implemented", c.Types[0])
|
||||
// Handle contract lookup so we don't need to set up a special contract mode
|
||||
// for operands just to carry its information through in form of some contract Type.
|
||||
// TODO(gri) this code is also in collectTypeParams (decl.go) - factor out!
|
||||
if ident, ok := unparen(econtr.Fun).(*ast.Ident); ok {
|
||||
if eobj, _ := check.lookup(ident.Name).(*Contract); eobj != nil {
|
||||
// TODO(gri) must set up contract if not yet done!
|
||||
// eobj is a valid contract
|
||||
// TODO(gri) look for contract cycles!
|
||||
// contract arguments must match the embedded contract's parameters
|
||||
if len(econtr.Args) != len(eobj.TParams) {
|
||||
check.errorf(c.Types[0].Pos(), "%d type parameters but contract expects %d", len(econtr.Args), len(eobj.TParams))
|
||||
continue
|
||||
}
|
||||
// contract arguments must be type parameters
|
||||
// For now, they must be from the enclosing contract.
|
||||
// TODO(gri) can we allow any type parameter?
|
||||
targs := make([]Type, len(econtr.Args))
|
||||
for i, arg := range econtr.Args {
|
||||
targ := check.typ(arg)
|
||||
if parg, _ := targ.(*TypeParam); parg != nil {
|
||||
// TODO(gri) check that targ is a parameter from the enclosing contract
|
||||
targs[i] = targ
|
||||
} else {
|
||||
check.errorf(arg.Pos(), "%s is not a type parameter", arg)
|
||||
}
|
||||
}
|
||||
// TODO(gri) - implement the steps below
|
||||
// - for each eobj type parameter, determine its (interface) bound
|
||||
// - substitute that type parameter with the actual type argument in that interface
|
||||
// - add the interface as am embedded interface to the bound matching the actual type argument
|
||||
// - tests! (incl. overlapping methods, etc.)
|
||||
check.errorf(c.Types[0].Pos(), "%s: contract embedding not yet implemented", c.Types[0])
|
||||
continue
|
||||
}
|
||||
}
|
||||
check.errorf(c.Types[0].Pos(), "%s is not a contract", c.Types[0])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -636,6 +636,7 @@ func (check *Checker) collectTypeParams(list *ast.FieldList) (tparams []*TypeNam
|
|||
goto next
|
||||
}
|
||||
// obj is a valid contract
|
||||
// TODO(gri) must set up contract if not yet done!
|
||||
// Use contract's matching type parameter bound and
|
||||
// instantiate it with the actual type parameters
|
||||
// (== targs) present.
|
||||
|
|
|
|||
|
|
@ -3,3 +3,13 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
|
||||
contract C1(a, b, c) {
|
||||
a a()
|
||||
b b()
|
||||
c c()
|
||||
}
|
||||
|
||||
contract C2(a, b) {
|
||||
C1 /* ERROR contract embedding */ (a, b, a)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue