]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] go/types: "comparable" must not be visible before Go 1.18
authorRob Findley <rfindley@google.com>
Fri, 16 Jul 2021 13:44:08 +0000 (09:44 -0400)
committerRobert Findley <rfindley@google.com>
Fri, 16 Jul 2021 23:07:17 +0000 (23:07 +0000)
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>
src/go/types/testdata/fixedbugs/issue46090.go2 [new file with mode: 0644]
src/go/types/typexpr.go
src/go/types/universe.go

diff --git a/src/go/types/testdata/fixedbugs/issue46090.go2 b/src/go/types/testdata/fixedbugs/issue46090.go2
new file mode 100644 (file)
index 0000000..81b3197
--- /dev/null
@@ -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
index 070b0ade3e8220fcbeb27c8efed43fffd093b7f9..64a1b37cef9cd52ac34ebd1f546428f847ab4b74 100644 (file)
@@ -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
        // may be different from obj.Parent(). See also Scope.LookupParent doc.
        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 == "_" {
                        check.errorf(e, _InvalidBlank, "cannot use _ as value or type")
                } else {
index 7ce401827e35a62412a8c4aec9d7b5b08c0dff27..540b0ac1189eb8dde607c0f8ba13bb87c1c72b3e 100644 (file)
@@ -8,7 +8,6 @@ package types
 
 import (
        "go/constant"
-       "go/internal/typeparams"
        "go/token"
        "strings"
 )
@@ -22,11 +21,12 @@ var Universe *Scope
 var Unsafe *Package
 
 var (
-       universeIota  *Const
-       universeByte  *Basic // uint8 alias, but has name "byte"
-       universeRune  *Basic // int32 alias, but has name "rune"
-       universeAny   *Interface
-       universeError *Named
+       universeIota       *Const
+       universeByte       *Basic // uint8 alias, but has name "byte"
+       universeRune       *Basic // int32 alias, but has name "rune"
+       universeAny        *Interface
+       universeError      *Named
+       universeComparable Object
 )
 
 // Typ contains the predeclared *Basic types indexed by their
@@ -79,21 +79,30 @@ func defPredeclaredTypes() {
                def(NewTypeName(token.NoPos, nil, t.name, t))
        }
 
-       // any
-       // (Predeclared and entered into universe scope so we do all the
-       // usual checks; but removed again from scope later since it's
-       // only visible as constraint in a type parameter list.)
+       // type any = interface{}
+       // Entered into universe scope so we do all the usual checks;
+       // but removed again from scope later since it's only visible
+       // as constraint in a type parameter list.
        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])
-               sig := &Signature{results: NewTuple(res)}
+               sig := NewSignature(nil, nil, NewTuple(res), false)
                err := NewFunc(token.NoPos, nil, "Error", sig)
                typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil)}
                sig.recv = NewVar(token.NoPos, nil, "", 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 {
@@ -202,33 +211,6 @@ func DefPredeclaredTestFuncs() {
        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() {
        Universe = NewScope(nil, token.NoPos, token.NoPos, "universe")
        Unsafe = NewPackage("unsafe", "unsafe")
@@ -238,15 +220,13 @@ func init() {
        defPredeclaredConsts()
        defPredeclaredNil()
        defPredeclaredFuncs()
-       if typeparams.Enabled {
-               defPredeclaredComparable()
-       }
 
        universeIota = Universe.Lookup("iota").(*Const)
        universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic)
        universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic)
        universeAny = Universe.Lookup("any").(*TypeName).typ.(*Interface)
        universeError = Universe.Lookup("error").(*TypeName).typ.(*Named)
+       universeComparable = Universe.Lookup("comparable")
 
        // "any" is only visible as constraint in a type parameter list
        delete(Universe.elems, "any")