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>
{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},
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
{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},
package types
import (
+ "fmt"
"go/constant"
"go/token"
"unicode"
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
}
}
}
--- /dev/null
+// -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 */)
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
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