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 <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2022-02-27 18:13:23 -08:00
parent eb8198d2f6
commit f9285818b6
4 changed files with 42 additions and 2 deletions

View 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

View file

@ -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("")
}

View 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

View file

@ -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("")
}