diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index fd164a9099..f4e332d07a 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -62,8 +62,13 @@ func isUntyped(typ Type) bool { } func isOrdered(typ Type) bool { - t, ok := typ.Underlying().(*Basic) - return ok && t.info&IsOrdered != 0 + switch t := typ.Underlying().(type) { + case *Basic: + return t.info&IsOrdered != 0 + case *TypeParam: + return t.contr.ifaceAt(t.index).is(isOrdered) + } + return false } func isConstType(typ Type) bool { diff --git a/src/go/types/testdata/contracts.go2 b/src/go/types/testdata/contracts.go2 index 8265fbd0e3..ed19849031 100644 --- a/src/go/types/testdata/contracts.go2 +++ b/src/go/types/testdata/contracts.go2 @@ -116,3 +116,16 @@ var _ T2(int32) var _ T2 /* ERROR not satisfied */ (int64) var _ T2(int) var _ T2(struct{x int}) + +// Use of contracts in parameterized functions + +contract SignedInteger(T) { + T int8, int16, int32, int64, int +} + +func min(type T SignedInteger)(x, y T) T { + if x < y { + return x + } + return y +} \ No newline at end of file diff --git a/src/go/types/type.go b/src/go/types/type.go index 13ab290a27..0b50fd6f31 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -254,6 +254,16 @@ type Interface struct { types []Type // for contracts } +// is reports whether interface t represents types that all satisfy pred. +func (t *Interface) is(pred func(Type) bool) bool { + for _, t := range t.types { + if !pred(t) { + return false + } + } + return true +} + // emptyInterface represents the empty (completed) interface var emptyInterface = Interface{allMethods: markComplete}