aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorRobert Findley <rfindley@google.com>2023-01-11 14:41:03 -0500
committerGopher Robot <gobot@golang.org>2023-01-11 22:29:34 +0000
commit245e95dfabd77f337373bf2d6bb47cd353ad8d74 (patch)
tree051d706f3319c8ee7bd1680505d26c5bde357c82 /src/cmd
parent18625d9becc559e65ab5b39aa5d27ae6eb7b00aa (diff)
downloadgo-245e95dfabd77f337373bf2d6bb47cd353ad8d74.tar.xz
go/types, types2: don't look up fields or methods when expecting a type
As we have seen many times, the type checker must be careful to avoid accessing named type information before the type is fully set up. We need a more systematic solution to this problem, but for now avoid one case that causes a crash: checking a selector expression on an incomplete type when a type expression is expected. For golang/go#57522 Change-Id: I7ed31b859cca263276e3a0647d1f1b49670023a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/461577 Run-TryBot: Robert Findley <rfindley@google.com> Auto-Submit: Robert Findley <rfindley@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@google.com>
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/compile/internal/types2/call.go21
-rw-r--r--src/cmd/compile/internal/types2/expr.go2
-rw-r--r--src/cmd/compile/internal/types2/typexpr.go2
3 files changed, 22 insertions, 3 deletions
diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go
index 50343bf77a..7d660ca772 100644
--- a/src/cmd/compile/internal/types2/call.go
+++ b/src/cmd/compile/internal/types2/call.go
@@ -447,7 +447,7 @@ var cgoPrefixes = [...]string{
"_Cmacro_", // function to evaluate the expanded expression
}
-func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *Named) {
+func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *Named, wantType bool) {
// these must be declared before the "goto Error" statements
var (
obj Object
@@ -559,6 +559,25 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *Named) {
goto Error
}
+ // Avoid crashing when checking an invalid selector in a method declaration
+ // (i.e., where def is not set):
+ //
+ // type S[T any] struct{}
+ // type V = S[any]
+ // func (fs *S[T]) M(x V.M) {}
+ //
+ // All codepaths below return a non-type expression. If we get here while
+ // expecting a type expression, it is an error.
+ //
+ // See issue #57522 for more details.
+ //
+ // TODO(rfindley): We should do better by refusing to check selectors in all cases where
+ // x.typ is incomplete.
+ if wantType {
+ check.errorf(e.Sel, NotAType, "%s is not a type", syntax.Expr(e))
+ goto Error
+ }
+
obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
if obj == nil {
// Don't report another error if the underlying type was invalid (issue #49541).
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index 9a0348e025..a3abbb9532 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -1587,7 +1587,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
return kind
case *syntax.SelectorExpr:
- check.selector(x, e, nil)
+ check.selector(x, e, nil, false)
case *syntax.IndexExpr:
if check.indexExpr(x, e) {
diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go
index 4de658b0c4..0f3106d70a 100644
--- a/src/cmd/compile/internal/types2/typexpr.go
+++ b/src/cmd/compile/internal/types2/typexpr.go
@@ -256,7 +256,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
case *syntax.SelectorExpr:
var x operand
- check.selector(&x, e, def)
+ check.selector(&x, e, def, true)
switch x.mode {
case typexpr: