diff options
| author | Robert Findley <rfindley@google.com> | 2023-01-11 14:41:03 -0500 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2023-01-11 22:29:34 +0000 |
| commit | 245e95dfabd77f337373bf2d6bb47cd353ad8d74 (patch) | |
| tree | 051d706f3319c8ee7bd1680505d26c5bde357c82 /src/cmd | |
| parent | 18625d9becc559e65ab5b39aa5d27ae6eb7b00aa (diff) | |
| download | go-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.go | 21 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/expr.go | 2 | ||||
| -rw-r--r-- | src/cmd/compile/internal/types2/typexpr.go | 2 |
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: |
