aboutsummaryrefslogtreecommitdiff
path: root/test/typeparam/absdiff.go
diff options
context:
space:
mode:
authorDan Scales <danscales@google.com>2021-03-05 22:07:56 -0800
committerDan Scales <danscales@google.com>2021-03-10 17:36:55 +0000
commit1811aeae66bee899317403c92c83b56673919775 (patch)
tree974c886e65d96e8785accb9a6161d123b0f7ca7c /test/typeparam/absdiff.go
parent5edab39f490dd3cff7bf02101b2d37a90827fa6d (diff)
downloadgo-1811aeae66bee899317403c92c83b56673919775.tar.gz
go-1811aeae66bee899317403c92c83b56673919775.zip
cmd/compile: deal with helper generic types that add methods to T
Deal with cases like: 'type P[T any] T' (used to add methods to an arbitrary type T), In this case, P[T] has kind types.TTYPEPARAM (as does T itself), but requires more code to substitute than a simple TTYPEPARAM T. See the comment near the beginning of subster.typ() in stencil.go. Add new test absdiff.go. This test has a case for complex types (which I've commented out) that will only work when we deal better with Go builtins in generic functions (like real and imag). Remove change in fmt.go for TTYPEPARAMS that is no longer needed (since all TTYPEPARAMS have a sym) and was sometimes causing an extra prefix when formatting method names. Separate out the setting of a TTYPEPARAM bound, since it can reference the TTYPEPARAM being defined, so must be done separately. Also, we don't currently (and may not ever) need bounds after types2 typechecking. Change-Id: Id173057e0c4563b309b95e665e9c1151ead4ba77 Reviewed-on: https://go-review.googlesource.com/c/go/+/300049 Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Dan Scales <danscales@google.com> Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'test/typeparam/absdiff.go')
-rw-r--r--test/typeparam/absdiff.go99
1 files changed, 99 insertions, 0 deletions
diff --git a/test/typeparam/absdiff.go b/test/typeparam/absdiff.go
new file mode 100644
index 0000000000..5dd58f14f7
--- /dev/null
+++ b/test/typeparam/absdiff.go
@@ -0,0 +1,99 @@
+// run -gcflags=-G=3
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "fmt"
+ //"math"
+)
+
+type Numeric interface {
+ type int, int8, int16, int32, int64,
+ uint, uint8, uint16, uint32, uint64, uintptr,
+ float32, float64,
+ complex64, complex128
+}
+
+// numericAbs matches numeric types with an Abs method.
+type numericAbs[T any] interface {
+ Numeric
+ Abs() T
+}
+
+// AbsDifference computes the absolute value of the difference of
+// a and b, where the absolute value is determined by the Abs method.
+func absDifference[T numericAbs[T]](a, b T) T {
+ d := a - b
+ return d.Abs()
+}
+
+// orderedNumeric matches numeric types that support the < operator.
+type orderedNumeric interface {
+ type int, int8, int16, int32, int64,
+ uint, uint8, uint16, uint32, uint64, uintptr,
+ float32, float64
+}
+
+// Complex matches the two complex types, which do not have a < operator.
+type Complex interface {
+ type complex64, complex128
+}
+
+// orderedAbs is a helper type that defines an Abs method for
+// ordered numeric types.
+type orderedAbs[T orderedNumeric] T
+
+func (a orderedAbs[T]) Abs() orderedAbs[T] {
+ // TODO(danscales): orderedAbs[T] conversion shouldn't be needed
+ if a < orderedAbs[T](0) {
+ return -a
+ }
+ return a
+}
+
+// complexAbs is a helper type that defines an Abs method for
+// complex types.
+// type complexAbs[T Complex] T
+
+// func (a complexAbs[T]) Abs() complexAbs[T] {
+// r := float64(real(a))
+// i := float64(imag(a))
+// d := math.Sqrt(r * r + i * i)
+// return complexAbs[T](complex(d, 0))
+// }
+
+// OrderedAbsDifference returns the absolute value of the difference
+// between a and b, where a and b are of an ordered type.
+func orderedAbsDifference[T orderedNumeric](a, b T) T {
+ return T(absDifference(orderedAbs[T](a), orderedAbs[T](b)))
+}
+
+// ComplexAbsDifference returns the absolute value of the difference
+// between a and b, where a and b are of a complex type.
+// func complexAbsDifference[T Complex](a, b T) T {
+// return T(absDifference(complexAbs[T](a), complexAbs[T](b)))
+// }
+
+func main() {
+ if got, want := orderedAbsDifference(1.0, -2.0), 3.0; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+ if got, want := orderedAbsDifference(-1.0, 2.0), 3.0; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+ if got, want := orderedAbsDifference(-20, 15), 35; got != want {
+ panic(fmt.Sprintf("got = %v, want = %v", got, want))
+ }
+
+ // Still have to handle built-ins real/abs to make this work
+ // if got, want := complexAbsDifference(5.0 + 2.0i, 2.0 - 2.0i), 5; got != want {
+ // panic(fmt.Sprintf("got = %v, want = %v", got, want)
+ // }
+ // if got, want := complexAbsDifference(2.0 - 2.0i, 5.0 + 2.0i), 5; got != want {
+ // panic(fmt.Sprintf("got = %v, want = %v", got, want)
+ // }
+}