mirror of https://github.com/golang/go.git
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:
parent
eb8198d2f6
commit
f9285818b6
|
|
@ -49,11 +49,14 @@ func (check *Checker) conversion(x *operand, T Type) {
|
||||||
// have specific types, constant x cannot be
|
// have specific types, constant x cannot be
|
||||||
// converted.
|
// converted.
|
||||||
ok = T.(*TypeParam).underIs(func(u Type) bool {
|
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 {
|
if u == nil {
|
||||||
cause = check.sprintf("%s does not contain specific types", T)
|
cause = check.sprintf("%s does not contain specific types", T)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if isString(x.typ) && isBytesOrRunes(u) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
if !constConvertibleTo(u, nil) {
|
if !constConvertibleTo(u, nil) {
|
||||||
cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T)
|
cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T)
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -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("")
|
||||||
|
}
|
||||||
|
|
@ -48,11 +48,14 @@ func (check *Checker) conversion(x *operand, T Type) {
|
||||||
// have specific types, constant x cannot be
|
// have specific types, constant x cannot be
|
||||||
// converted.
|
// converted.
|
||||||
ok = T.(*TypeParam).underIs(func(u Type) bool {
|
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 {
|
if u == nil {
|
||||||
cause = check.sprintf("%s does not contain specific types", T)
|
cause = check.sprintf("%s does not contain specific types", T)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if isString(x.typ) && isBytesOrRunes(u) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
if !constConvertibleTo(u, nil) {
|
if !constConvertibleTo(u, nil) {
|
||||||
cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T)
|
cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T)
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -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("")
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue