mirror of https://github.com/golang/go.git
go/types: first steps towards collecting/recognizing type constraints
Change-Id: Ic0d70db24ad9fb76a5bb128df654c131f173247e
This commit is contained in:
parent
7b6471a756
commit
dc4f9fb373
|
|
@ -29,13 +29,13 @@ func (check *Checker) contractType(contr *Contract, e *ast.ContractType) {
|
|||
// each type parameter's constraints are represented by an interface
|
||||
ifaces := make(map[*TypeName]*Interface)
|
||||
|
||||
addMethod := func(tpar *TypeName, m *Func) {
|
||||
ifaceFor := func(tpar *TypeName) *Interface {
|
||||
iface := ifaces[tpar]
|
||||
if iface == nil {
|
||||
iface = new(Interface)
|
||||
ifaces[tpar] = iface
|
||||
}
|
||||
iface.methods = append(iface.methods, m)
|
||||
return iface
|
||||
}
|
||||
|
||||
// collect constraints
|
||||
|
|
@ -75,6 +75,7 @@ func (check *Checker) contractType(contr *Contract, e *ast.ContractType) {
|
|||
}
|
||||
|
||||
tpar := obj.(*TypeName)
|
||||
iface := ifaceFor(tpar)
|
||||
switch nmethods {
|
||||
case 0:
|
||||
// type constraints
|
||||
|
|
@ -92,7 +93,9 @@ func (check *Checker) contractType(contr *Contract, e *ast.ContractType) {
|
|||
check.errorf(texpr.Pos(), "invalid type constraint %s (%s)", typ, why)
|
||||
continue
|
||||
}
|
||||
// TODO(gri) add type
|
||||
// add type
|
||||
iface.types = append(iface.types, typ)
|
||||
|
||||
}
|
||||
|
||||
case 1:
|
||||
|
|
@ -115,7 +118,7 @@ func (check *Checker) contractType(contr *Contract, e *ast.ContractType) {
|
|||
// add the method
|
||||
mname := c.MNames[0]
|
||||
m := NewFunc(mname.Pos(), check.pkg, mname.Name, sig)
|
||||
addMethod(tpar, m)
|
||||
iface.methods = append(iface.methods, m)
|
||||
|
||||
default:
|
||||
// ignore (error was reported earlier)
|
||||
|
|
@ -243,6 +246,7 @@ func (check *Checker) satisfyContract(contr *Contract, targs []Type) bool {
|
|||
iface := contr.ifaceAt(i)
|
||||
// If iface is parameterized, we need to replace the type parameters
|
||||
// with the respective type arguments.
|
||||
// TODO(gri) fix this
|
||||
if IsParameterized(iface) {
|
||||
panic("unimplemented")
|
||||
}
|
||||
|
|
@ -252,6 +256,24 @@ func (check *Checker) satisfyContract(contr *Contract, targs []Type) bool {
|
|||
// check.dump("missing %s (%s, %s)", m, targ, iface)
|
||||
return false
|
||||
}
|
||||
// targ's underlying type must also be one of the interface types listed, if any
|
||||
if len(iface.types) > 0 {
|
||||
utyp := targ.Underlying()
|
||||
// TODO(gri) Cannot handle a type argument that is itself parameterized for now
|
||||
switch utyp.(type) {
|
||||
case *Interface, *Contract:
|
||||
panic("unimplemented")
|
||||
}
|
||||
ok := false
|
||||
for _, t := range iface.types {
|
||||
// if we find one matching type, we're ok
|
||||
if Identical(utyp, t) {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return ok
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -101,3 +101,18 @@ var _ List /* ERROR not satisfied */ (int)
|
|||
type MyData string
|
||||
|
||||
func (s MyData) String() string { return string(s) }
|
||||
|
||||
// Contracts that mention types can only be satisfied by similar types.
|
||||
|
||||
contract C3(T) {
|
||||
T int16, int32, int, struct{x int}
|
||||
}
|
||||
|
||||
type T2 (type _ C3) struct{}
|
||||
|
||||
var _ T2 /* ERROR not satisfied */ (int8)
|
||||
var _ T2(int16)
|
||||
var _ T2(int32)
|
||||
var _ T2 /* ERROR not satisfied */ (int64)
|
||||
var _ T2(int)
|
||||
var _ T2(struct{x int})
|
||||
|
|
|
|||
|
|
@ -249,6 +249,9 @@ type Interface struct {
|
|||
embeddeds []Type // ordered list of explicitly embedded types
|
||||
|
||||
allMethods []*Func // ordered list of methods declared with or embedded in this interface (TODO(gri): replace with mset)
|
||||
|
||||
// for contracts
|
||||
types []Type // for contracts
|
||||
}
|
||||
|
||||
// emptyInterface represents the empty (completed) interface
|
||||
|
|
|
|||
Loading…
Reference in New Issue