]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: handle ++/-- in noder2 for operands with generic type
authorDan Scales <danscales@google.com>
Mon, 19 Jul 2021 05:10:13 +0000 (22:10 -0700)
committerDan Scales <danscales@google.com>
Wed, 21 Jul 2021 21:30:48 +0000 (21:30 +0000)
types2 will have already proved the expression's type is compatible, so
just assign the one const to have the same type as the operand.

Fixes #47258.

Change-Id: If0844e6bf6d0a5e6b11453b87df71353863ccc5d
Reviewed-on: https://go-review.googlesource.com/c/go/+/336009
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Trust: Dan Scales <danscales@google.com>

src/cmd/compile/internal/noder/helpers.go
test/typeparam/issue47258.go [new file with mode: 0644]

index 7da5aa3102ed5e86f27eda01bef7dff2019c254b..15b32779080d57e722996db5d2905504f79980cc 100644 (file)
@@ -337,5 +337,15 @@ var one = constant.MakeInt64(1)
 
 func IncDec(pos src.XPos, op ir.Op, x ir.Node) *ir.AssignOpStmt {
        assert(x.Type() != nil)
-       return ir.NewAssignOpStmt(pos, op, x, typecheck.DefaultLit(ir.NewBasicLit(pos, one), x.Type()))
+       bl := ir.NewBasicLit(pos, one)
+       if x.Type().HasTParam() {
+               // If the operand is generic, then types2 will have proved it must be
+               // a type that fits with increment/decrement, so just set the type of
+               // "one" to n.Type(). This works even for types that are eventually
+               // float or complex.
+               typed(x.Type(), bl)
+       } else {
+               bl = typecheck.DefaultLit(bl, x.Type())
+       }
+       return ir.NewAssignOpStmt(pos, op, x, bl)
 }
diff --git a/test/typeparam/issue47258.go b/test/typeparam/issue47258.go
new file mode 100644 (file)
index 0000000..76629f7
--- /dev/null
@@ -0,0 +1,32 @@
+// run -gcflags=-G=3
+
+// Copyright 2021 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"
+)
+
+type Numeric interface {
+       int32|int64|float64|complex64
+}
+
+//go:noline
+func inc[T Numeric](x T) T {
+       x++
+       return x
+}
+func main() {
+       if got, want := inc(int32(5)), int32(6); got != want {
+               panic(fmt.Sprintf("got %d, want %d", got, want))
+       }
+       if got, want := inc(float64(5)), float64(6.0); got != want {
+               panic(fmt.Sprintf("got %d, want %d", got, want))
+       }
+       if got, want := inc(complex64(5)), complex64(6.0); got != want {
+               panic(fmt.Sprintf("got %d, want %d", got, want))
+       }
+}