]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: fix string to type parameter conversions
authorRobert Griesemer <gri@golang.org>
Mon, 28 Feb 2022 02:13:23 +0000 (18:13 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 28 Feb 2022 21:50:54 +0000 (21:50 +0000)
Converting an untyped constant to a type parameter results
in a non-constant value; but the constant must still be
representable by all specific types of the type parameter.

Adjust the special handling for constant-to-type parameter
conversions to also include string-to-[]byte and []rune
conversions, which are handled separately for conversions
to types that are not type parameters because those are not
constant conversions in non-generic code.

Fixes #51386.

Change-Id: I15e5a0fd281efd15af387280cd3dee320a1ac5e1
Reviewed-on: https://go-review.googlesource.com/c/go/+/388254
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/conversions.go
src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2 [new file with mode: 0644]
src/go/types/conversions.go
src/go/types/testdata/fixedbugs/issue51386.go2 [new file with mode: 0644]

index 7fe1d5056b0241b0087e1ea64c9edda37f9a5fa9..08b3cbff29607d3814c50e1995fb2c1d0150dba3 100644 (file)
@@ -49,11 +49,14 @@ func (check *Checker) conversion(x *operand, T Type) {
                // have specific types, constant x cannot be
                // converted.
                ok = T.(*TypeParam).underIs(func(u Type) bool {
-                       // t is nil if there are no specific type terms
+                       // u is nil if there are no specific type terms
                        if u == nil {
                                cause = check.sprintf("%s does not contain specific types", T)
                                return false
                        }
+                       if isString(x.typ) && isBytesOrRunes(u) {
+                               return true
+                       }
                        if !constConvertibleTo(u, nil) {
                                cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T)
                                return false
diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2
new file mode 100644 (file)
index 0000000..ef62239
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2022 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 p
+
+type myString string
+
+func _[P ~string | ~[]byte | ~[]rune]() {
+       _ = P("")
+       const s myString = ""
+       _ = P(s)
+}
+
+func _[P myString]() {
+       _ = P("")
+}
index 84741359c0ffe762a1f9bc46a69519a944bbacfb..c5a69cddf48502b4e909e6ade91777e4507a8885 100644 (file)
@@ -48,11 +48,14 @@ func (check *Checker) conversion(x *operand, T Type) {
                // have specific types, constant x cannot be
                // converted.
                ok = T.(*TypeParam).underIs(func(u Type) bool {
-                       // t is nil if there are no specific type terms
+                       // u is nil if there are no specific type terms
                        if u == nil {
                                cause = check.sprintf("%s does not contain specific types", T)
                                return false
                        }
+                       if isString(x.typ) && isBytesOrRunes(u) {
+                               return true
+                       }
                        if !constConvertibleTo(u, nil) {
                                cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T)
                                return false
diff --git a/src/go/types/testdata/fixedbugs/issue51386.go2 b/src/go/types/testdata/fixedbugs/issue51386.go2
new file mode 100644 (file)
index 0000000..ef62239
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2022 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 p
+
+type myString string
+
+func _[P ~string | ~[]byte | ~[]rune]() {
+       _ = P("")
+       const s myString = ""
+       _ = P(s)
+}
+
+func _[P myString]() {
+       _ = P("")
+}