]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: "comparable" must not be visible before...
authorRobert Griesemer <gri@golang.org>
Tue, 29 Jun 2021 02:41:29 +0000 (19:41 -0700)
committerRobert Griesemer <gri@golang.org>
Thu, 1 Jul 2021 16:36:06 +0000 (16:36 +0000)
While at it, clean up the setup of comparable in universe.go.

Fixes #46090

Change-Id: I9655b3e137a03763d677d9a2a730c5570ccff6dc
Reviewed-on: https://go-review.googlesource.com/c/go/+/331517
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/testdata/fixedbugs/issue46090.go2 [new file with mode: 0644]
src/cmd/compile/internal/types2/typexpr.go
src/cmd/compile/internal/types2/universe.go

diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue46090.go2 b/src/cmd/compile/internal/types2/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 fe676be2efd1b53e5b1b01280ce82818d7a62ac2..5626fed7568bcc03d17e9a2d10ebdd5165e5246d 100644 (file)
@@ -25,7 +25,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo
        // 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.Value, check.pos)
-       if obj == nil {
+       if obj == nil || obj == universeComparable && !check.allowVersion(check.pkg, 1, 18) {
                if e.Value == "_" {
                        check.error(e, "cannot use _ as value or type")
                } else {
index 2bcc49778ef8a9a39f977bc610d010482bdf516f..c9b53bac921ece7d9bb4079c12b7cb0749a61f04 100644 (file)
@@ -20,11 +20,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
@@ -77,21 +78,30 @@ func defPredeclaredTypes() {
                def(NewTypeName(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(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(nopos, nil, "", Typ[String])
-               sig := &Signature{results: NewTuple(res)}
+               sig := NewSignature(nil, nil, NewTuple(res), false)
                err := NewFunc(nopos, nil, "Error", sig)
                typ := &Named{underlying: NewInterfaceType([]*Func{err}, nil)}
                sig.recv = NewVar(nopos, nil, "", typ)
                def(NewTypeName(nopos, nil, "error", typ))
        }
+
+       // type comparable interface{ ==() }
+       {
+               sig := NewSignature(nil, nil, nil, false)
+               eql := NewFunc(nopos, nil, "==", sig)
+               typ := &Named{underlying: NewInterfaceType([]*Func{eql}, nil)}
+               sig.recv = NewVar(nopos, nil, "", typ)
+               def(NewTypeName(nopos, nil, "comparable", typ))
+       }
 }
 
 var predeclaredConsts = [...]struct {
@@ -200,33 +210,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(nopos, nil, "==", sig)
-       iface := NewInterfaceType([]*Func{eql}, nil)
-
-       // set up the defined type for the interface
-       obj := NewTypeName(nopos, nil, "comparable", nil)
-       named := NewNamed(obj, iface, nil)
-       obj.color_ = black
-       sig.recv = NewVar(nopos, nil, "", named) // complete == signature
-
-       def(obj)
-}
-
 func init() {
        Universe = NewScope(nil, nopos, nopos, "universe")
        Unsafe = NewPackage("unsafe", "unsafe")
@@ -236,13 +219,13 @@ func init() {
        defPredeclaredConsts()
        defPredeclaredNil()
        defPredeclaredFuncs()
-       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")