mirror of
https://github.com/golang/go
synced 2024-11-25 07:07:57 -07:00
go/types, types2: implement slice-to-array conversions
For #46505. Change-Id: I9bc9da5dd4b76cb2d8ff41390e1567678e72d88d Reviewed-on: https://go-review.googlesource.com/c/go/+/428938 Run-TryBot: Robert Griesemer <gri@google.com> Reviewed-by: Robert Findley <rfindley@google.com> Auto-Submit: Robert Griesemer <gri@google.com> Reviewed-by: Robert Griesemer <gri@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
0e50bf0e40
commit
cd8aa40149
@ -1876,8 +1876,9 @@ func TestConvertibleTo(t *testing.T) {
|
||||
{newDefined(new(Struct)), new(Struct), true},
|
||||
{newDefined(Typ[Int]), new(Struct), false},
|
||||
{Typ[UntypedInt], Typ[Int], true},
|
||||
{NewSlice(Typ[Int]), NewArray(Typ[Int], 10), true},
|
||||
{NewSlice(Typ[Int]), NewArray(Typ[Uint], 10), false},
|
||||
{NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Int], 10)), true},
|
||||
{NewSlice(Typ[Int]), NewArray(Typ[Int], 10), false},
|
||||
{NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Uint], 10)), false},
|
||||
// Untyped string values are not permitted by the spec, so the behavior below is undefined.
|
||||
{Typ[UntypedString], Typ[String], true},
|
||||
|
@ -188,11 +188,27 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// "V a slice, T is a pointer-to-array type,
|
||||
// "V is a slice, T is an array or pointer-to-array type,
|
||||
// and the slice and array types have identical element types."
|
||||
if s, _ := Vu.(*Slice); s != nil {
|
||||
if p, _ := Tu.(*Pointer); p != nil {
|
||||
if a, _ := under(p.Elem()).(*Array); a != nil {
|
||||
switch a := Tu.(type) {
|
||||
case *Array:
|
||||
if Identical(s.Elem(), a.Elem()) {
|
||||
if check == nil || check.allowVersion(check.pkg, 1, 20) {
|
||||
return true
|
||||
}
|
||||
// check != nil
|
||||
if cause != nil {
|
||||
// TODO(gri) consider restructuring versionErrorf so we can use it here and below
|
||||
*cause = "conversion of slices to arrays requires go1.20 or later"
|
||||
if check.conf.CompilerErrorMessages {
|
||||
*cause += fmt.Sprintf(" (-lang was set to %s; check go.mod)", check.conf.GoVersion)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
case *Pointer:
|
||||
if a, _ := under(a.Elem()).(*Array); a != nil {
|
||||
if Identical(s.Elem(), a.Elem()) {
|
||||
if check == nil || check.allowVersion(check.pkg, 1, 17) {
|
||||
return true
|
||||
|
@ -1873,8 +1873,9 @@ func TestConvertibleTo(t *testing.T) {
|
||||
{newDefined(new(Struct)), new(Struct), true},
|
||||
{newDefined(Typ[Int]), new(Struct), false},
|
||||
{Typ[UntypedInt], Typ[Int], true},
|
||||
{NewSlice(Typ[Int]), NewArray(Typ[Int], 10), true},
|
||||
{NewSlice(Typ[Int]), NewArray(Typ[Uint], 10), false},
|
||||
{NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Int], 10)), true},
|
||||
{NewSlice(Typ[Int]), NewArray(Typ[Int], 10), false},
|
||||
{NewSlice(Typ[Int]), NewPointer(NewArray(Typ[Uint], 10)), false},
|
||||
// Untyped string values are not permitted by the spec, so the behavior below is undefined.
|
||||
{Typ[UntypedString], Typ[String], true},
|
||||
|
@ -7,6 +7,7 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
"unicode"
|
||||
@ -187,18 +188,39 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// "V a slice, T is a pointer-to-array type,
|
||||
// "V is a slice, T is an array or pointer-to-array type,
|
||||
// and the slice and array types have identical element types."
|
||||
if s, _ := Vu.(*Slice); s != nil {
|
||||
if p, _ := Tu.(*Pointer); p != nil {
|
||||
if a, _ := under(p.Elem()).(*Array); a != nil {
|
||||
switch a := Tu.(type) {
|
||||
case *Array:
|
||||
if Identical(s.Elem(), a.Elem()) {
|
||||
if check == nil || check.allowVersion(check.pkg, 1, 20) {
|
||||
return true
|
||||
}
|
||||
// check != nil
|
||||
if cause != nil {
|
||||
// TODO(gri) consider restructuring versionErrorf so we can use it here and below
|
||||
*cause = "conversion of slices to arrays requires go1.20 or later"
|
||||
if compilerErrorMessages {
|
||||
*cause += fmt.Sprintf(" (-lang was set to %s; check go.mod)", check.conf.GoVersion)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
case *Pointer:
|
||||
if a, _ := under(a.Elem()).(*Array); a != nil {
|
||||
if Identical(s.Elem(), a.Elem()) {
|
||||
if check == nil || check.allowVersion(check.pkg, 1, 17) {
|
||||
return true
|
||||
}
|
||||
// check != nil
|
||||
if cause != nil {
|
||||
*cause = "conversion of slices to array pointers requires go1.17 or later"
|
||||
if compilerErrorMessages {
|
||||
*cause += fmt.Sprintf(" (-lang was set to %s; check go.mod)", check.conf.GoVersion)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
15
src/internal/types/testdata/check/go1_19.go
vendored
Normal file
15
src/internal/types/testdata/check/go1_19.go
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
// -lang=go1.19
|
||||
|
||||
// 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.
|
||||
|
||||
// Check Go language version-specific errors.
|
||||
|
||||
package p
|
||||
|
||||
type Slice []byte
|
||||
type Array [8]byte
|
||||
|
||||
var s Slice
|
||||
var p = (Array)(s /* ERROR requires go1.20 or later */)
|
@ -176,13 +176,11 @@ func _[X unsafe.Pointer](x X) int64 {
|
||||
return int64(x /* ERROR cannot convert x \(variable of type X constrained by unsafe\.Pointer\) to int64\n\tcannot convert unsafe\.Pointer \(in X\) to int64 */)
|
||||
}
|
||||
|
||||
// "x is a slice, T is a pointer-to-array type,
|
||||
// "x is a slice, T is an array or pointer-to-array type,
|
||||
// and the slice and array types have identical element types."
|
||||
|
||||
func _[X ~[]E, T ~[10]E, E any](x X) T { return T(x) }
|
||||
func _[X ~[]E, T ~*[10]E, E any](x X) T { return T(x) }
|
||||
func _[X ~[]E, T ~[10]E, E any](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\[\]E\) to T\n\tcannot convert \[\]E \(in X\) to \[10\]E \(in T\) */)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// The following declarations can be replaced by the exported types of the
|
||||
|
@ -316,11 +316,11 @@ func _() {
|
||||
|
||||
func _() {
|
||||
var s []byte
|
||||
_ = ([4]byte)(s) // ERROR "cannot convert"
|
||||
_ = ([4]byte)(s)
|
||||
_ = (*[4]byte)(s)
|
||||
|
||||
type A [4]byte
|
||||
_ = (A)(s) // ERROR "cannot convert"
|
||||
_ = (A)(s)
|
||||
_ = (*A)(s)
|
||||
|
||||
type P *[4]byte
|
||||
|
Loading…
Reference in New Issue
Block a user