Robert Griesemer has uploaded this change for review.
go/types, types2: fix string to type parameter conversions
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
---
M src/cmd/compile/internal/types2/conversions.go
A src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2
M src/go/types/conversions.go
A src/go/types/testdata/fixedbugs/issue51386.go2
4 files changed, 61 insertions(+), 2 deletions(-)
diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go
index 7fe1d50..f3e95fd 100644
--- a/src/cmd/compile/internal/types2/conversions.go
+++ b/src/cmd/compile/internal/types2/conversions.go
@@ -19,8 +19,10 @@
constConvertibleTo := func(T Type, val *constant.Value) bool {
switch t, _ := under(T).(*Basic); {
+ case isString(x.typ) && isBytesOrRunes(T):
+ return true
case t == nil:
- // nothing to do
+ return false // exit early: T is not a basic type
case representableConst(x.val, check, t, val):
return true
case isInteger(x.typ) && isString(t):
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
index 0000000..ef622392
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2
@@ -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("")
+}
diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go
index 8474135..058adab 100644
--- a/src/go/types/conversions.go
+++ b/src/go/types/conversions.go
@@ -18,8 +18,10 @@
constConvertibleTo := func(T Type, val *constant.Value) bool {
switch t, _ := under(T).(*Basic); {
+ case isString(x.typ) && isBytesOrRunes(T):
+ return true
case t == nil:
- // nothing to do
+ return false // exit early: T is not a basic type
case representableConst(x.val, check, t, val):
return true
case isInteger(x.typ) && isString(t):
diff --git a/src/go/types/testdata/fixedbugs/issue51386.go2 b/src/go/types/testdata/fixedbugs/issue51386.go2
new file mode 100644
index 0000000..ef622392
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51386.go2
@@ -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("")
+}
To view, visit change 388254. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Robert Griesemer.
Patch set 1:Code-Review +2
2 comments:
File src/go/types/conversions.go:
case isString(x.typ) && isBytesOrRunes(T):
return true
This looks out of place here, since the rest of this function is about representability.
But I agree it fixes the bug.
Patch Set #1, Line 58: if !constConvertibleTo(u, nil)
I don't quite recall why we wouldn't just call x.convertibleTo here, based on the description above. Could use some explanation.
To view, visit change 388254. To unsubscribe, or for help writing mail filters, visit settings.
2 comments:
File src/go/types/conversions.go:
case isString(x.typ) && isBytesOrRunes(T):
return true
This looks out of place here, since the rest of this function is about representability. […]
Agreed. But it was the easiest change to make. I'll see if I can make this clearer.
(Also note that this case is not reachable when we convert to a constant type (byte and rune slices are not constant types.)
Patch Set #1, Line 58: if !constConvertibleTo(u, nil)
I don't quite recall why we wouldn't just call x.convertibleTo here, based on the description above. […]
The explanation is on line 47ff. Without that requirement - which is written down in the spec and which we need because upon monomorphization we have a single type - we could simply drop this entire case in the switch and the code would type-check.
To view, visit change 388254. To unsubscribe, or for help writing mail filters, visit settings.
Robert Griesemer uploaded patch set #2 to this change.
go/types, types2: fix string to type parameter conversions
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
---
M src/cmd/compile/internal/types2/conversions.go
A src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2
M src/go/types/conversions.go
A src/go/types/testdata/fixedbugs/issue51386.go2
4 files changed, 63 insertions(+), 2 deletions(-)
To view, visit change 388254. To unsubscribe, or for help writing mail filters, visit settings.
1 comment:
Patchset:
PTAL
To view, visit change 388254. To unsubscribe, or for help writing mail filters, visit settings.
Attention is currently required from: Robert Griesemer.
Patch set 2:Code-Review +2
2 comments:
File src/go/types/conversions.go:
case isString(x.typ) && isBytesOrRunes(T):
return true
(Also note that this case is not reachable when we convert to a constant type (byte and rune slices are not constant types.)
Yep, I observed that, but it looked fragile. New patchset looks better to me.
Patch Set #1, Line 58: if !constConvertibleTo(u, nil)
The explanation is on line 47ff. […]
Ack, thanks for the additional explanation.
To view, visit change 388254. To unsubscribe, or for help writing mail filters, visit settings.
Robert Griesemer submitted this change.
2 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
go/types, types2: fix string to type parameter conversions
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 <g...@golang.org>
Reviewed-by: Robert Findley <rfin...@google.com>
---
M src/cmd/compile/internal/types2/conversions.go
A src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2
M src/go/types/conversions.go
A src/go/types/testdata/fixedbugs/issue51386.go2
4 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go
index 7fe1d50..08b3cbf 100644
--- a/src/cmd/compile/internal/types2/conversions.go
+++ b/src/cmd/compile/internal/types2/conversions.go
@@ -49,11 +49,14 @@
// 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
index 0000000..ef622392
--- /dev/null
+++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2
@@ -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("")
+}
diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go
index 8474135..c5a69cd 100644
--- a/src/go/types/conversions.go
+++ b/src/go/types/conversions.go
@@ -48,11 +48,14 @@
// 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
index 0000000..ef622392
--- /dev/null
+++ b/src/go/types/testdata/fixedbugs/issue51386.go2
@@ -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("")
+}
To view, visit change 388254. To unsubscribe, or for help writing mail filters, visit settings.