]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile/internal/types2: more consistent handling of predeclared...
authorRobert Griesemer <gri@golang.org>
Thu, 15 Jul 2021 23:42:25 +0000 (16:42 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 16 Jul 2021 04:41:47 +0000 (04:41 +0000)
Rather than removing "any" from the universe scope, keep it predeclared
but provide a better error message.

While at it, remove some unnecessary type assertions.

Change-Id: I10603274282ea6afc107f703ab194f32bd334dd1
Reviewed-on: https://go-review.googlesource.com/c/go/+/334911
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/decl.go
src/cmd/compile/internal/types2/object_test.go
src/cmd/compile/internal/types2/testdata/check/typeparams.go2
src/cmd/compile/internal/types2/typexpr.go
src/cmd/compile/internal/types2/universe.go
test/fixedbugs/issue14652.go
test/typeparam/tparam1.go

index 9fb9815f4dbf1340eae028557d0d08c12faf08b1..4f656e374aff3c8fd75125f7d210fd407bcecf1f 100644 (file)
@@ -617,8 +617,9 @@ func (check *Checker) declareTypeParam(index int, name *syntax.Name) *TypeName {
 // The type must be an interface, including the predeclared type "any".
 func (check *Checker) boundType(e syntax.Expr) Type {
        // The predeclared identifier "any" is visible only as a type bound in a type parameter list.
-       if name, _ := unparen(e).(*syntax.Name); name != nil && name.Value == "any" && check.lookup("any") == nil {
-               return universeAny
+       // If we allow "any" for general use, this if-statement can be removed (issue #33232).
+       if name, _ := unparen(e).(*syntax.Name); name != nil && name.Value == "any" && check.lookup("any") == universeAny {
+               return universeAny.Type()
        }
 
        bound := check.typ(e)
index 7f63c793325721dca1512a4628d970e31f523892..a86733a5c99a12824f36121d9a8f935910eb8599 100644 (file)
@@ -25,7 +25,7 @@ func TestIsAlias(t *testing.T) {
        check(Unsafe.Scope().Lookup("Pointer").(*TypeName), false)
        for _, name := range Universe.Names() {
                if obj, _ := Universe.Lookup(name).(*TypeName); obj != nil {
-                       check(obj, name == "byte" || name == "rune")
+                       check(obj, name == "any" || name == "byte" || name == "rune")
                }
        }
 
index 8a7f6eb2c251aadf64ed95a4ce1982370c2b3e45..2755a539e527193a73ae4aac43dd24476bf283b9 100644 (file)
@@ -6,11 +6,11 @@ package p
 
 // import "io" // for type assertion tests
 
-// The predeclared identifier "any" is only visible as a constraint
+// The predeclared identifier "any" can only be used as a constraint
 // in a type parameter list.
-var _ any // ERROR undeclared
-func _[_ any /* ok here */ , _ interface{any /* ERROR undeclared */ }](any /* ERROR undeclared */ ) {
-        var _ any /* ERROR undeclared */
+var _ any // ERROR cannot use any outside constraint position
+func _[_ any /* ok here */ , _ interface{any /* ERROR constraint */ }](any /* ERROR constraint */ ) {
+        var _ any /* ERROR constraint */
 }
 
 func identity[T any](x T) T { return x }
index a14d498cec0d2f1422944207c46c71ebad19e9e6..83cefa19bae47ce988bca4a3035ff216daa7ad17 100644 (file)
@@ -25,7 +25,8 @@ 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 || obj == universeComparable && !check.allowVersion(check.pkg, 1, 18) {
+       switch obj {
+       case nil:
                if e.Value == "_" {
                        check.error(e, "cannot use _ as value or type")
                } else {
@@ -36,6 +37,16 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *Named, wantType boo
                        }
                }
                return
+       case universeAny, universeComparable:
+               if !check.allowVersion(check.pkg, 1, 18) {
+                       check.errorf(e, "undeclared name: %s (requires version go1.18 or later)", e.Value)
+                       return
+               }
+               // If we allow "any" for general use, this if-statement can be removed (issue #33232).
+               if obj == universeAny {
+                       check.error(e, "cannot use any outside constraint position")
+                       return
+               }
        }
        check.recordUse(e, obj)
 
index d328b13a8e1b708a5ef9b868dee658e92c83b6be..e2dd0df69e85fc6b22e53a5a6cfc2698c71fe890 100644 (file)
@@ -20,11 +20,11 @@ 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       Object
+       universeByte       Type // uint8 alias, but has name "byte"
+       universeRune       Type // int32 alias, but has name "rune"
+       universeAny        Object
+       universeError      Type
        universeComparable Object
 )
 
@@ -79,9 +79,6 @@ func defPredeclaredTypes() {
        }
 
        // 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))
 
        // type error interface{ Error() string }
@@ -224,15 +221,12 @@ func init() {
        defPredeclaredNil()
        defPredeclaredFuncs()
 
-       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)
+       universeIota = Universe.Lookup("iota")
+       universeByte = Universe.Lookup("byte").Type()
+       universeRune = Universe.Lookup("rune").Type()
+       universeAny = Universe.Lookup("any")
+       universeError = Universe.Lookup("error").Type()
        universeComparable = Universe.Lookup("comparable")
-
-       // "any" is only visible as constraint in a type parameter list
-       delete(Universe.elems, "any")
 }
 
 // Objects with names containing blanks are internal and not entered into
index d53b412668314822423427c98711bb0731041b83..14a223977b4a1ddd1952d063f97e6bcd27517bc8 100644 (file)
@@ -6,4 +6,4 @@
 
 package p
 
-var x any // ERROR "undefined: any|undefined type .*any.*"
+var x any // ERROR "undefined: any|undefined type .*any.*|cannot use any outside constraint position"
index 70439333269a704bc5f911bf7d68ac41be17ca92..2bcc4af3dbabbdf5700298644d73e4de47ba11f2 100644 (file)
@@ -10,8 +10,8 @@ package tparam1
 
 // The predeclared identifier "any" is only visible as a constraint
 // in a type parameter list.
-var _ any // ERROR "undefined"
-func _(_ any) // ERROR "undefined"
+var _ any // ERROR "cannot use any outside constraint position"
+func _(_ any) // ERROR "cannot use any outside constraint position"
 type _[_ any /* ok here */ ] struct{}
 
 const N = 10