diff options
author | Dan Scales <danscales@google.com> | 2021-03-18 11:56:46 -0700 |
---|---|---|
committer | Dan Scales <danscales@google.com> | 2021-03-18 22:18:32 +0000 |
commit | 90b1ed1602ad8db08a5b1bde4aae5f8569b21915 (patch) | |
tree | 4a3356a6a99812a1961c05ce018bf8dc19c3575d /test/typeparam/list.go | |
parent | 095ba225973152734b0722e7c5758accb2639c15 (diff) | |
download | go-90b1ed1602ad8db08a5b1bde4aae5f8569b21915.tar.gz go-90b1ed1602ad8db08a5b1bde4aae5f8569b21915.zip |
cmd/compile: get untyped constants working in generic functions
types2 will give us a constant with a type T, if an untyped constant is
used with another operand of type T (in a provably correct way). When we
substitute in the type args during stenciling, we now know the real type
of the constant. We may then need to change the BasicLit.val to be the
correct type (e.g. convert an int64Val constant to a floatVal constant).
Otherwise, later parts of the compiler will be confused.
Updated tests list.go and double.go with uses of untyped constants.
Change-Id: I9966bbb0dea3a7de1c5a6420f8ad8af9ca84a33e
Reviewed-on: https://go-review.googlesource.com/c/go/+/303089
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/list.go')
-rw-r--r-- | test/typeparam/list.go | 78 |
1 files changed, 58 insertions, 20 deletions
diff --git a/test/typeparam/list.go b/test/typeparam/list.go index 64230060de..579078f02f 100644 --- a/test/typeparam/list.go +++ b/test/typeparam/list.go @@ -17,13 +17,13 @@ type Ordered interface { string } -// List is a linked list of ordered values of type T. -type list[T Ordered] struct { - next *list[T] +// _List is a linked list of ordered values of type T. +type _List[T Ordered] struct { + next *_List[T] val T } -func (l *list[T]) largest() T { +func (l *_List[T]) Largest() T { var max T for p := l; p != nil; p = p.next { if p.val > max { @@ -33,33 +33,71 @@ func (l *list[T]) largest() T { return max } +type OrderedNum interface { + type int, int8, int16, int32, int64, + uint, uint8, uint16, uint32, uint64, uintptr, + float32, float64 +} + +// _ListNum is a linked _List of ordered numeric values of type T. +type _ListNum[T OrderedNum] struct { + next *_ListNum[T] + val T +} + +const Clip = 5 + +// clippedLargest returns the largest in the list of OrderNums, but a max of 5. +// Test use of untyped constant in an expression with a generically-typed parameter +func (l *_ListNum[T]) ClippedLargest() T { + var max T + for p := l; p != nil; p = p.next { + if p.val > max && p.val < Clip { + max = p.val + } + } + return max +} func main() { - i3 := &list[int]{nil, 1} - i2 := &list[int]{i3, 3} - i1 := &list[int]{i2, 2} - if got, want := i1.largest(), 3; got != want { + i3 := &_List[int]{nil, 1} + i2 := &_List[int]{i3, 3} + i1 := &_List[int]{i2, 2} + if got, want := i1.Largest(), 3; got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } - b3 := &list[byte]{nil, byte(1)} - b2 := &list[byte]{b3, byte(3)} - b1 := &list[byte]{b2, byte(2)} - if got, want := b1.largest(), byte(3); got != want { + b3 := &_List[byte]{nil, byte(1)} + b2 := &_List[byte]{b3, byte(3)} + b1 := &_List[byte]{b2, byte(2)} + if got, want := b1.Largest(), byte(3); got != want { panic(fmt.Sprintf("got %d, want %d", got, want)) } - f3 := &list[float64]{nil, 13.5} - f2 := &list[float64]{f3, 1.2} - f1 := &list[float64]{f2, 4.5} - if got, want := f1.largest(), 13.5; got != want { + f3 := &_List[float64]{nil, 13.5} + f2 := &_List[float64]{f3, 1.2} + f1 := &_List[float64]{f2, 4.5} + if got, want := f1.Largest(), 13.5; got != want { panic(fmt.Sprintf("got %f, want %f", got, want)) } - s3 := &list[string]{nil, "dd"} - s2 := &list[string]{s3, "aa"} - s1 := &list[string]{s2, "bb"} - if got, want := s1.largest(), "dd"; got != want { + s3 := &_List[string]{nil, "dd"} + s2 := &_List[string]{s3, "aa"} + s1 := &_List[string]{s2, "bb"} + if got, want := s1.Largest(), "dd"; got != want { panic(fmt.Sprintf("got %s, want %s", got, want)) } + + j3 := &_ListNum[int]{nil, 1} + j2 := &_ListNum[int]{j3, 32} + j1 := &_ListNum[int]{j2, 2} + if got, want := j1.ClippedLargest(), 2; got != want { + panic(fmt.Sprintf("got %d, want %d", got, want)) + } + g3 := &_ListNum[float64]{nil, 13.5} + g2 := &_ListNum[float64]{g3, 1.2} + g1 := &_ListNum[float64]{g2, 4.5} + if got, want := g1.ClippedLargest(), 4.5; got != want { + panic(fmt.Sprintf("got %f, want %f", got, want)) + } } |