Skip to content

Commit 2c6f24c

Browse files
committed
go/types, types2: bail early if we want a type but don't have one
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 <[email protected]> Auto-Submit: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]> Reviewed-by: Robert Griesemer <[email protected]> TryBot-Bypass: Robert Griesemer <[email protected]> Reviewed-by: Cuong Manh Le <[email protected]>
1 parent 10a6564 commit 2c6f24c

File tree

8 files changed

+61
-10
lines changed

8 files changed

+61
-10
lines changed

src/cmd/compile/internal/types2/typexpr.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,20 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType
4848
}
4949
check.recordUse(e, obj)
5050

51+
// If we want a type but don't have one, stop right here and avoid potential problems
52+
// with missing underlying types. This also gives better error messages in some cases
53+
// (see go.dev/issue/65344).
54+
_, gotType := obj.(*TypeName)
55+
if !gotType && wantType {
56+
check.errorf(e, NotAType, "%s is not a type", obj.Name())
57+
// avoid "declared but not used" errors
58+
// (don't use Checker.use - we don't want to evaluate too much)
59+
if v, _ := obj.(*Var); v != nil && v.pkg == check.pkg /* see Checker.use1 */ {
60+
v.used = true
61+
}
62+
return
63+
}
64+
5165
// Type-check the object.
5266
// Only call Checker.objDecl if the object doesn't have a type yet
5367
// (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
5771
// informative "not a type/value" error that this function's caller
5872
// will issue (see go.dev/issue/25790).
5973
typ := obj.Type()
60-
if _, gotType := obj.(*TypeName); typ == nil || gotType && wantType {
74+
if typ == nil || gotType && wantType {
6175
check.objDecl(obj, def)
6276
typ = obj.Type() // type must have been assigned by Checker.objDecl
6377
}

src/go/types/typexpr.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,20 @@ func (check *Checker) ident(x *operand, e *ast.Ident, def *TypeName, wantType bo
4949
}
5050
check.recordUse(e, obj)
5151

52+
// If we want a type but don't have one, stop right here and avoid potential problems
53+
// with missing underlying types. This also gives better error messages in some cases
54+
// (see go.dev/issue/65344).
55+
_, gotType := obj.(*TypeName)
56+
if !gotType && wantType {
57+
check.errorf(e, NotAType, "%s is not a type", obj.Name())
58+
// avoid "declared but not used" errors
59+
// (don't use Checker.use - we don't want to evaluate too much)
60+
if v, _ := obj.(*Var); v != nil && v.pkg == check.pkg /* see Checker.use1 */ {
61+
v.used = true
62+
}
63+
return
64+
}
65+
5266
// Type-check the object.
5367
// Only call Checker.objDecl if the object doesn't have a type yet
5468
// (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
5872
// informative "not a type/value" error that this function's caller
5973
// will issue (see go.dev/issue/25790).
6074
typ := obj.Type()
61-
if _, gotType := obj.(*TypeName); typ == nil || gotType && wantType {
75+
if typ == nil || gotType && wantType {
6276
check.objDecl(obj, def)
6377
typ = obj.Type() // type must have been assigned by Checker.objDecl
6478
}

src/internal/types/testdata/check/cycles5.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ var a12 = makeArray()
161161
func makeArray() (res T12) { return }
162162

163163
// issue #20770
164-
var r /* ERROR "invalid cycle in declaration of r" */ = newReader()
165-
func newReader() r
164+
var r = newReader()
165+
func newReader() r // ERROR "r is not a type"
166166

167167
// variations of the theme of #8699 and #20770
168168
var arr /* ERROR "cycle" */ = f()

src/internal/types/testdata/check/cycles5a.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ var a12 = makeArray()
161161
func makeArray() (res T12) { return }
162162

163163
// issue #20770
164-
var r /* ERROR "invalid cycle in declaration of r" */ = newReader()
165-
func newReader() r
164+
var r = newReader()
165+
func newReader() r // ERROR "r is not a type"
166166

167167
// variations of the theme of #8699 and #20770
168168
var arr /* ERROR "cycle" */ = f()

src/internal/types/testdata/check/decls1.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ var (
6363
t12 complex64 = -(u + *t11) / *&v
6464
t13 int = a /* ERROR "shifted operand" */ << d
6565
t14 int = i << j
66-
t15 math /* ERROR "not in selector" */
66+
t15 math /* ERROR "math is not a type" */
6767
t16 math.xxx /* ERROR "undefined" */
6868
t17 math /* ERROR "not a type" */ .Pi
6969
t18 float64 = math.Pi * 10.0

src/internal/types/testdata/check/issues0.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func issue10979() {
104104

105105
// issue11347
106106
// These should not crash.
107-
var a1, b1 /* ERROR "cycle" */ , c1 /* ERROR "cycle" */ b1 = 0 > 0<<""[""[c1]]>c1
107+
var a1, b1, c1 /* ERROR "cycle" */ b1 /* ERROR "b1 is not a type" */ = 0 > 0<<""[""[c1]]>c1
108108
var a2, b2 /* ERROR "cycle" */ = 0 /* ERROR "assignment mismatch" */ /* ERROR "assignment mismatch" */ > 0<<""[b2]
109109
var a3, b3 /* ERROR "cycle" */ = int /* ERROR "assignment mismatch" */ /* ERROR "assignment mismatch" */ (1<<""[b3])
110110

src/internal/types/testdata/fixedbugs/issue39634.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// Examples adjusted to match new [T any] syntax for type parameters.
5+
// Examples from the issue adjusted to match new [T any] syntax for type parameters.
66
// Also, previously permitted empty type parameter lists and instantiations
77
// are now syntax errors.
8+
//
9+
// The primary concern here is that these tests shouldn't crash the type checker.
10+
// The quality of the error messages is secondary as these are all pretty esoteric
11+
// or artificial test cases.
812

913
package p
1014

@@ -39,7 +43,7 @@ type foo9[A any] interface { foo9 /* ERROR "invalid recursive type" */ [A] }
3943
func _() { var _ = new(foo9[int]) }
4044

4145
// crash 12
42-
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" */
46+
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" */
4347

4448
// crash 15
4549
func y15() { var a /* ERROR "declared and not used" */ interface{ p() } = G15[string]{} }
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
type T1 C /* ERROR "C is not a type" */
8+
9+
// TODO(gri) try to avoid this follow-on error
10+
const C = T1(0 /* ERROR "cannot convert 0 (untyped int constant) to type T1" */)
11+
12+
type T2 V /* ERROR "V is not a type" */
13+
14+
var V T2
15+
16+
func _() {
17+
// don't produce errors here
18+
_ = C + V
19+
}

0 commit comments

Comments
 (0)