mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
[dev.typeparams] go/types: "comparable" must not be visible before Go 1.18
This is a straightforward port of CL 331517 to go/types. Change-Id: Id00761fd5dffb4d09e19f086d18ddc20f11528d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/335032 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:
parent
79955155e9
commit
726ffce659
9
src/go/types/testdata/fixedbugs/issue46090.go2
vendored
Normal file
9
src/go/types/testdata/fixedbugs/issue46090.go2
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright 2020 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.
|
||||||
|
|
||||||
|
// The predeclared type comparable is not visible before Go 1.18.
|
||||||
|
|
||||||
|
package go1_17
|
||||||
|
|
||||||
|
type _ comparable // ERROR undeclared
|
|
@ -27,7 +27,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *Named, wantType bool)
|
||||||
// Note that we cannot use check.lookup here because the returned scope
|
// Note that we cannot use check.lookup here because the returned scope
|
||||||
// may be different from obj.Parent(). See also Scope.LookupParent doc.
|
// may be different from obj.Parent(). See also Scope.LookupParent doc.
|
||||||
scope, obj := check.scope.LookupParent(e.Name, check.pos)
|
scope, obj := check.scope.LookupParent(e.Name, check.pos)
|
||||||
if obj == nil {
|
if obj == nil || obj == universeComparable && !check.allowVersion(check.pkg, 1, 18) {
|
||||||
if e.Name == "_" {
|
if e.Name == "_" {
|
||||||
check.errorf(e, _InvalidBlank, "cannot use _ as value or type")
|
check.errorf(e, _InvalidBlank, "cannot use _ as value or type")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,7 +8,6 @@ package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/constant"
|
"go/constant"
|
||||||
"go/internal/typeparams"
|
|
||||||
"go/token"
|
"go/token"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -22,11 +21,12 @@ var Universe *Scope
|
||||||
var Unsafe *Package
|
var Unsafe *Package
|
||||||
|
|
||||||
var (
|
var (
|
||||||
universeIota *Const
|
universeIota *Const
|
||||||
universeByte *Basic // uint8 alias, but has name "byte"
|
universeByte *Basic // uint8 alias, but has name "byte"
|
||||||
universeRune *Basic // int32 alias, but has name "rune"
|
universeRune *Basic // int32 alias, but has name "rune"
|
||||||
universeAny *Interface
|
universeAny *Interface
|
||||||
universeError *Named
|
universeError *Named
|
||||||
|
universeComparable Object
|
||||||
)
|
)
|
||||||
|
|
||||||
// Typ contains the predeclared *Basic types indexed by their
|
// Typ contains the predeclared *Basic types indexed by their
|
||||||
|
@ -79,21 +79,30 @@ func defPredeclaredTypes() {
|
||||||
def(NewTypeName(token.NoPos, nil, t.name, t))
|
def(NewTypeName(token.NoPos, nil, t.name, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
// any
|
// type any = interface{}
|
||||||
// (Predeclared and entered into universe scope so we do all the
|
// Entered into universe scope so we do all the usual checks;
|
||||||
// usual checks; but removed again from scope later since it's
|
// but removed again from scope later since it's only visible
|
||||||
// only visible as constraint in a type parameter list.)
|
// as constraint in a type parameter list.
|
||||||
def(NewTypeName(token.NoPos, nil, "any", &emptyInterface))
|
def(NewTypeName(token.NoPos, nil, "any", &emptyInterface))
|
||||||
|
|
||||||
// Error has a nil package in its qualified name since it is in no package
|
// type error interface{ Error() string }
|
||||||
{
|
{
|
||||||
res := NewVar(token.NoPos, nil, "", Typ[String])
|
res := NewVar(token.NoPos, nil, "", Typ[String])
|
||||||
sig := &Signature{results: NewTuple(res)}
|
sig := NewSignature(nil, nil, NewTuple(res), false)
|
||||||
err := NewFunc(token.NoPos, nil, "Error", sig)
|
err := NewFunc(token.NoPos, nil, "Error", sig)
|
||||||
typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil)}
|
typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil)}
|
||||||
sig.recv = NewVar(token.NoPos, nil, "", typ)
|
sig.recv = NewVar(token.NoPos, nil, "", typ)
|
||||||
def(NewTypeName(token.NoPos, nil, "error", typ))
|
def(NewTypeName(token.NoPos, nil, "error", typ))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// type comparable interface{ ==() }
|
||||||
|
{
|
||||||
|
sig := NewSignature(nil, nil, nil, false)
|
||||||
|
eql := NewFunc(token.NoPos, nil, "==", sig)
|
||||||
|
typ := &Named{underlying: NewInterfaceType([]*Func{eql}, nil)}
|
||||||
|
sig.recv = NewVar(token.NoPos, nil, "", typ)
|
||||||
|
def(NewTypeName(token.NoPos, nil, "comparable", typ))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var predeclaredConsts = [...]struct {
|
var predeclaredConsts = [...]struct {
|
||||||
|
@ -202,33 +211,6 @@ func DefPredeclaredTestFuncs() {
|
||||||
def(newBuiltin(_Trace))
|
def(newBuiltin(_Trace))
|
||||||
}
|
}
|
||||||
|
|
||||||
func defPredeclaredComparable() {
|
|
||||||
// The "comparable" interface can be imagined as defined like
|
|
||||||
//
|
|
||||||
// type comparable interface {
|
|
||||||
// == () untyped bool
|
|
||||||
// != () untyped bool
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// == and != cannot be user-declared but we can declare
|
|
||||||
// a magic method == and check for its presence when needed.
|
|
||||||
|
|
||||||
// Define interface { == () }. We don't care about the signature
|
|
||||||
// for == so leave it empty except for the receiver, which is
|
|
||||||
// set up later to match the usual interface method assumptions.
|
|
||||||
sig := new(Signature)
|
|
||||||
eql := NewFunc(token.NoPos, nil, "==", sig)
|
|
||||||
iface := NewInterfaceType([]*Func{eql}, nil)
|
|
||||||
|
|
||||||
// set up the defined type for the interface
|
|
||||||
obj := NewTypeName(token.NoPos, nil, "comparable", nil)
|
|
||||||
named := NewNamed(obj, iface, nil)
|
|
||||||
obj.color_ = black
|
|
||||||
sig.recv = NewVar(token.NoPos, nil, "", named) // complete == signature
|
|
||||||
|
|
||||||
def(obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
Universe = NewScope(nil, token.NoPos, token.NoPos, "universe")
|
Universe = NewScope(nil, token.NoPos, token.NoPos, "universe")
|
||||||
Unsafe = NewPackage("unsafe", "unsafe")
|
Unsafe = NewPackage("unsafe", "unsafe")
|
||||||
|
@ -238,15 +220,13 @@ func init() {
|
||||||
defPredeclaredConsts()
|
defPredeclaredConsts()
|
||||||
defPredeclaredNil()
|
defPredeclaredNil()
|
||||||
defPredeclaredFuncs()
|
defPredeclaredFuncs()
|
||||||
if typeparams.Enabled {
|
|
||||||
defPredeclaredComparable()
|
|
||||||
}
|
|
||||||
|
|
||||||
universeIota = Universe.Lookup("iota").(*Const)
|
universeIota = Universe.Lookup("iota").(*Const)
|
||||||
universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic)
|
universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic)
|
||||||
universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic)
|
universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic)
|
||||||
universeAny = Universe.Lookup("any").(*TypeName).typ.(*Interface)
|
universeAny = Universe.Lookup("any").(*TypeName).typ.(*Interface)
|
||||||
universeError = Universe.Lookup("error").(*TypeName).typ.(*Named)
|
universeError = Universe.Lookup("error").(*TypeName).typ.(*Named)
|
||||||
|
universeComparable = Universe.Lookup("comparable")
|
||||||
|
|
||||||
// "any" is only visible as constraint in a type parameter list
|
// "any" is only visible as constraint in a type parameter list
|
||||||
delete(Universe.elems, "any")
|
delete(Universe.elems, "any")
|
||||||
|
|
Loading…
Reference in a new issue