1
0
mirror of https://github.com/golang/go synced 2024-11-11 22:20:22 -07:00

go/types: slice-to-array-pointer conversion requires go1.17

This is a port of CL 315169 to go/types. It uses a slightly different
mechanism for evaluating the convertibility error message, to be
consistent with operand.assignableTo.

Change-Id: Iea2e2a9fbb4cf17d472b2b7392786118e079528a
Reviewed-on: https://go-review.googlesource.com/c/go/+/315809
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Rob Findley 2021-04-30 14:49:40 -04:00 committed by Robert Findley
parent 8e91458b19
commit ffc38d8ab4
4 changed files with 29 additions and 6 deletions

View File

@ -406,7 +406,7 @@ func AssignableTo(V, T Type) bool {
// ConvertibleTo reports whether a value of type V is convertible to a value of type T.
func ConvertibleTo(V, T Type) bool {
x := operand{mode: value, typ: V}
return x.convertibleTo(nil, T) // check not needed for non-constant x
return x.convertibleTo(nil, T, nil) // check not needed for non-constant x
}
// Implements reports whether type V implements interface T.

View File

@ -17,6 +17,7 @@ func (check *Checker) conversion(x *operand, T Type) {
constArg := x.mode == constant_
var ok bool
var reason string
switch {
case constArg && isConstType(T):
// constant conversion
@ -31,14 +32,18 @@ func (check *Checker) conversion(x *operand, T Type) {
x.val = constant.MakeString(string(codepoint))
ok = true
}
case x.convertibleTo(check, T):
case x.convertibleTo(check, T, &reason):
// non-constant conversion
x.mode = value
ok = true
}
if !ok {
check.errorf(x, _InvalidConversion, "cannot convert %s to %s", x, T)
if reason != "" {
check.errorf(x, _InvalidConversion, "cannot convert %s to %s (%s)", x, T, reason)
} else {
check.errorf(x, _InvalidConversion, "cannot convert %s to %s", x, T)
}
x.mode = invalid
return
}
@ -79,7 +84,7 @@ func (check *Checker) conversion(x *operand, T Type) {
// convertibleTo reports whether T(x) is valid.
// The check parameter may be nil if convertibleTo is invoked through an
// exported API call, i.e., when all methods have been type-checked.
func (x *operand) convertibleTo(check *Checker, T Type) bool {
func (x *operand) convertibleTo(check *Checker, T Type, reason *string) bool {
// "x is assignable to T"
if ok, _ := x.assignableTo(check, T, nil); ok {
return true
@ -139,7 +144,12 @@ func (x *operand) convertibleTo(check *Checker, T Type) bool {
if p := asPointer(T); p != nil {
if a := asArray(p.Elem()); a != nil {
if check.identical(s.Elem(), a.Elem()) {
return true
if check == nil || check.allowVersion(check.pkg, 1, 17) {
return true
}
if reason != nil {
*reason = "conversion of slices to array pointers requires go1.17 or later"
}
}
}
}

View File

@ -655,7 +655,7 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *ast.TypeSpec, def *Named) {
if alias {
// type alias declaration
if !check.allowVersion(obj.pkg, 1, 9) {
if !check.allowVersion(check.pkg, 1, 9) {
check.errorf(atPos(tdecl.Assign), _BadDecl, "type aliases requires go1.9 or later")
}

13
src/go/types/testdata/check/go1_16.src vendored Normal file
View File

@ -0,0 +1,13 @@
// 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.
// Check Go language version-specific errors.
package go1_16 // go1.16
type Slice []byte
type Array [8]byte
var s Slice
var p = (*Array)(s /* ERROR requires go1.17 or later */ )