]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: bail early if we want a type but don't have one
authorRobert Griesemer <gri@golang.org>
Tue, 30 Jan 2024 00:34:16 +0000 (16:34 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 5 Feb 2024 18:13:11 +0000 (18:13 +0000)
If we do know whether we need a type or not, make use of the
information when we know that we don't have a type and bail out.

Fixes the issue at hand and also improves some other error messages
which now report that we don't have a type instead of reporting a cycle.

For #65344.

Change-Id: I11182efd452c485d89e6c09ead8a647ea05d7318
Reviewed-on: https://go-review.googlesource.com/c/go/+/559335
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
TryBot-Bypass: Robert Griesemer <gri@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
src/cmd/compile/internal/types2/typexpr.go
src/go/types/typexpr.go
src/internal/types/testdata/check/cycles5.go
src/internal/types/testdata/check/cycles5a.go
src/internal/types/testdata/check/decls1.go
src/internal/types/testdata/check/issues0.go
src/internal/types/testdata/fixedbugs/issue39634.go
src/internal/types/testdata/fixedbugs/issue65344.go [new file with mode: 0644]

index 81adcbd9cfd0105d26eff12c3bbdcf24d2780148..d131306a142c6921002ee1e4ffc15c93ac40b622 100644 (file)
@@ -48,6 +48,20 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType
        }
        check.recordUse(e, obj)
 
+       // If we want a type but don't have one, stop right here and avoid potential problems
+       // with missing underlying types. This also gives better error messages in some cases
+       // (see go.dev/issue/65344).
+       _, gotType := obj.(*TypeName)
+       if !gotType && wantType {
+               check.errorf(e, NotAType, "%s is not a type", obj.Name())
+               // avoid "declared but not used" errors
+               // (don't use Checker.use - we don't want to evaluate too much)
+               if v, _ := obj.(*Var); v != nil && v.pkg == check.pkg /* see Checker.use1 */ {
+                       v.used = true
+               }
+               return
+       }
+
        // Type-check the object.
        // Only call Checker.objDecl if the object doesn't have a type yet
        // (in which case we must actually determine it) or the object is a
@@ -57,7 +71,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType
        // informative "not a type/value" error that this function's caller
        // will issue (see go.dev/issue/25790).
        typ := obj.Type()
-       if _, gotType := obj.(*TypeName); typ == nil || gotType && wantType {
+       if typ == nil || gotType && wantType {
                check.objDecl(obj, def)
                typ = obj.Type() // type must have been assigned by Checker.objDecl
        }
index c887b5115a2ab13183698a40d5b1e533f219df59..afb94b90261a498f20e50809dd21918cb0c2ae41 100644 (file)
@@ -49,6 +49,20 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *TypeName, wantType bo
        }
        check.recordUse(e, obj)
 
+       // If we want a type but don't have one, stop right here and avoid potential problems
+       // with missing underlying types. This also gives better error messages in some cases
+       // (see go.dev/issue/65344).
+       _, gotType := obj.(*TypeName)
+       if !gotType && wantType {
+               check.errorf(e, NotAType, "%s is not a type", obj.Name())
+               // avoid "declared but not used" errors
+               // (don't use Checker.use - we don't want to evaluate too much)
+               if v, _ := obj.(*Var); v != nil && v.pkg == check.pkg /* see Checker.use1 */ {
+                       v.used = true
+               }
+               return
+       }
+
        // Type-check the object.
        // Only call Checker.objDecl if the object doesn't have a type yet
        // (in which case we must actually determine it) or the object is a
@@ -58,7 +72,7 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *TypeName, wantType bo
        // informative "not a type/value" error that this function's caller
        // will issue (see go.dev/issue/25790).
        typ := obj.Type()
-       if _, gotType := obj.(*TypeName); typ == nil || gotType && wantType {
+       if typ == nil || gotType && wantType {
                check.objDecl(obj, def)
                typ = obj.Type() // type must have been assigned by Checker.objDecl
        }
index a6145058bba9a2a72083c6f7e6e742315a174fc7..de85c03d8a3d9f4324455d9048bb85bc2af34746 100644 (file)
@@ -161,8 +161,8 @@ var a12 = makeArray()
 func makeArray() (res T12) { return }
 
 // issue #20770
-var r /* ERROR "invalid cycle in declaration of r" */ = newReader()
-func newReader() r
+var r = newReader()
+func newReader() r // ERROR "r is not a type"
 
 // variations of the theme of #8699 and #20770
 var arr /* ERROR "cycle" */ = f()
index ed5853e3f239321581375d7bf315b7968a021e10..e10f554e5c0120fe5d307c5ccfbe329aa0d96631 100644 (file)
@@ -161,8 +161,8 @@ var a12 = makeArray()
 func makeArray() (res T12) { return }
 
 // issue #20770
-var r /* ERROR "invalid cycle in declaration of r" */ = newReader()
-func newReader() r
+var r = newReader()
+func newReader() r // ERROR "r is not a type"
 
 // variations of the theme of #8699 and #20770
 var arr /* ERROR "cycle" */ = f()
index 06f3b2e6cbf8fdd741b71f2ccd299f757e7d3468..6cdbf27f4c2c18c4ffffd30c2fe9fecdd7ffa189 100644 (file)
@@ -63,7 +63,7 @@ var (
        t12 complex64 = -(u + *t11) / *&v
        t13 int = a /* ERROR "shifted operand" */ << d
        t14 int = i << j
-       t15 math /* ERROR "not in selector" */
+       t15 math /* ERROR "math is not a type" */
        t16 math.xxx /* ERROR "undefined" */
        t17 math /* ERROR "not a type" */ .Pi
        t18 float64 = math.Pi * 10.0
index dc6e0b0b2238250a9e88c0c2704e45ca98d40aa8..3bf4a3144656edb5048aa9a21d65b7af413650ce 100644 (file)
@@ -104,7 +104,7 @@ func issue10979() {
 
 // issue11347
 // These should not crash.
-var a1, b1 /* ERROR "cycle" */ , c1 /* ERROR "cycle" */ b1 = 0 > 0<<""[""[c1]]>c1
+var a1, b1, c1 /* ERROR "cycle" */ b1 /* ERROR "b1 is not a type" */ = 0 > 0<<""[""[c1]]>c1
 var a2, b2 /* ERROR "cycle" */ = 0 /* ERROR "assignment mismatch" */ /* ERROR "assignment mismatch" */ > 0<<""[b2]
 var a3, b3 /* ERROR "cycle" */ = int /* ERROR "assignment mismatch" */ /* ERROR "assignment mismatch" */ (1<<""[b3])
 
index 591b00e40463338e60660cb5079d10f34a1fbe28..6fbc7cd7bc72986b64375bdbfae9957c38e84f33 100644 (file)
@@ -2,9 +2,13 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Examples adjusted to match new [T any] syntax for type parameters.
+// Examples from the issue adjusted to match new [T any] syntax for type parameters.
 // Also, previously permitted empty type parameter lists and instantiations
 // are now syntax errors.
+//
+// The primary concern here is that these tests shouldn't crash the type checker.
+// The quality of the error messages is secondary as these are all pretty esoteric
+// or artificial test cases.
 
 package p
 
@@ -39,7 +43,7 @@ type foo9[A any] interface { foo9 /* ERROR "invalid recursive type" */ [A] }
 func _() { var _ = new(foo9[int]) }
 
 // crash 12
-var u /* ERROR "cycle" */ , i [func /* ERROR "used as value" */ /* ERROR "used as value" */ (u, c /* ERROR "undefined" */ /* ERROR "undefined" */ ) {}(0, len /* ERROR "must be called" */ /* ERROR "must be called" */ )]c /* ERROR "undefined" */ /* ERROR "undefined" */
+var u, i [func /* ERROR "used as value" */ /* ERROR "used as value" */ (u /* ERROR "u is not a type" */ /* ERROR "u is not a type" */ , c /* ERROR "undefined" */ /* ERROR "undefined" */ ) {}(0, len /* ERROR "must be called" */ /* ERROR "must be called" */ )]c /* ERROR "undefined" */ /* ERROR "undefined" */
 
 // crash 15
 func y15() { var a /* ERROR "declared and not used" */ interface{ p() } = G15[string]{} }
diff --git a/src/internal/types/testdata/fixedbugs/issue65344.go b/src/internal/types/testdata/fixedbugs/issue65344.go
new file mode 100644 (file)
index 0000000..9f8337c
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2024 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.
+
+package p
+
+type T1 C /* ERROR "C is not a type" */
+
+// TODO(gri) try to avoid this follow-on error
+const C = T1(0 /* ERROR "cannot convert 0 (untyped int constant) to type T1" */)
+
+type T2 V /* ERROR "V is not a type" */
+
+var V T2
+
+func _() {
+       // don't produce errors here
+       _ = C + V
+}