From cfbeecaabbeca6788b2ecc47e057f8118d71fc06 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 12 Sep 2019 17:28:57 -0700 Subject: [PATCH] go/types: first cut at type-checking type parameters with operators - implemented for comparisons for now - can type-check generic min - also: rebased on top of Go tip Change-Id: Id35582a59c4cddcb2b4ae9c7d7154ef8e41580ab --- src/go/types/predicates.go | 9 +++++++-- src/go/types/testdata/contracts.go2 | 13 +++++++++++++ src/go/types/type.go | 10 ++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) 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}