From 934a79ff2f25292798a5a0469fc8b4bddb6dcee7 Mon Sep 17 00:00:00 2001 From: Mark Freeman Date: Thu, 5 Feb 2026 15:58:52 -0500 Subject: [PATCH] go/types, types2: mechanically swap x.mode_ = invalid for x.invalidate() Change-Id: I7802b10f63a52e5f864d550a7ad7678d4581a796 Reviewed-on: https://go-review.googlesource.com/c/go/+/742500 Auto-Submit: Mark Freeman LUCI-TryBot-Result: Go LUCI Reviewed-by: Robert Griesemer --- .../compile/internal/types2/assignments.go | 16 +++--- src/cmd/compile/internal/types2/call.go | 22 ++++---- src/cmd/compile/internal/types2/const.go | 4 +- .../compile/internal/types2/conversions.go | 4 +- src/cmd/compile/internal/types2/expr.go | 50 +++++++++---------- src/cmd/compile/internal/types2/index.go | 28 +++++------ src/cmd/compile/internal/types2/literals.go | 10 ++-- src/cmd/compile/internal/types2/operand.go | 6 ++- src/cmd/compile/internal/types2/stmt.go | 2 +- src/cmd/compile/internal/types2/typexpr.go | 2 +- src/go/types/assignments.go | 16 +++--- src/go/types/call.go | 22 ++++---- src/go/types/const.go | 4 +- src/go/types/conversions.go | 4 +- src/go/types/expr.go | 50 +++++++++---------- src/go/types/index.go | 28 +++++------ src/go/types/literals.go | 10 ++-- src/go/types/operand.go | 6 ++- src/go/types/stmt.go | 2 +- src/go/types/typexpr.go | 2 +- 20 files changed, 148 insertions(+), 140 deletions(-) diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index 5903a5a310..bd188d51da 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -33,7 +33,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { // we may get here because of other problems (go.dev/issue/39634, crash 12) // TODO(gri) do we need a new "generic" error code here? check.errorf(x, IncompatibleAssign, "cannot assign %s to %s in %s", x, T, context) - x.mode_ = invalid + x.invalidate() return } @@ -48,7 +48,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { if x.isNil() { if T == nil { check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context) - x.mode_ = invalid + x.invalidate() return } } else if T == nil || isNonTypeParamInterface(T) { @@ -58,7 +58,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { if T == nil || isNonTypeParamInterface(T) { if T == nil && x.typ() == Typ[UntypedNil] { check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context) - x.mode_ = invalid + x.invalidate() return } target = Default(x.typ()) @@ -76,7 +76,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { code = IncompatibleAssign } check.error(x, code, msg) - x.mode_ = invalid + x.invalidate() return } if val != nil { @@ -111,7 +111,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { } else { check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context) } - x.mode_ = invalid + x.invalidate() } } @@ -155,7 +155,7 @@ func (check *Checker) initVar(lhs *Var, x *operand, context string) { if lhs.typ == nil { lhs.typ = Typ[Invalid] } - x.mode_ = invalid + x.invalidate() return } @@ -167,7 +167,7 @@ func (check *Checker) initVar(lhs *Var, x *operand, context string) { if typ == Typ[UntypedNil] { check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context) lhs.typ = Typ[Invalid] - x.mode_ = invalid + x.invalidate() return } typ = Default(typ) @@ -250,7 +250,7 @@ func (check *Checker) assignVar(lhs, rhs syntax.Expr, x *operand, context string T := check.lhsVar(lhs) // nil if lhs is _ if !isValid(T) { if x != nil { - x.mode_ = invalid + x.invalidate() } else { check.use(rhs) } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 0e73c25f25..467dc37609 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -49,7 +49,7 @@ func (check *Checker) funcInst(T *target, pos syntax.Pos, x *operand, inst *synt xlist = syntax.UnpackListExpr(inst.Index) targs = check.typeList(xlist) if targs == nil { - x.mode_ = invalid + x.invalidate() return nil } assert(len(targs) == len(xlist)) @@ -63,7 +63,7 @@ func (check *Checker) funcInst(T *target, pos syntax.Pos, x *operand, inst *synt if got > want { // Providing too many type arguments is always an error. check.errorf(xlist[got-1], WrongTypeArgCount, "got %d type arguments but want %d", got, want) - x.mode_ = invalid + x.invalidate() return nil } @@ -113,7 +113,7 @@ func (check *Checker) funcInst(T *target, pos syntax.Pos, x *operand, inst *synt if !err.empty() { err.report() } - x.mode_ = invalid + x.invalidate() return nil } got = len(targs) @@ -198,7 +198,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { return conversion } T := x.typ() - x.mode_ = invalid + x.invalidate() // We cannot convert a value to an incomplete type; make sure it's complete. if !check.isComplete(T) { x.expr = call @@ -233,7 +233,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { // no need to check for non-genericity here id := x.id if !check.builtin(x, call, id) { - x.mode_ = invalid + x.invalidate() } x.expr = call // a non-constant result implies a function call @@ -257,7 +257,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { }) if err != nil { check.errorf(x, InvalidCall, invalidOp+"cannot call %s: %s", x, err.format(check)) - x.mode_ = invalid + x.invalidate() x.expr = call return statement } @@ -274,7 +274,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { targs = check.typeList(xlist) if targs == nil { check.use(call.ArgList...) - x.mode_ = invalid + x.invalidate() x.expr = call return statement } @@ -285,7 +285,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { if got > want { check.errorf(xlist[want], WrongTypeArgCount, "got %d type arguments but want %d", got, want) check.use(call.ArgList...) - x.mode_ = invalid + x.invalidate() x.expr = call return statement } @@ -327,7 +327,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { typ := sig.results.vars[0].typ // unpack tuple // We cannot return a value of an incomplete type; make sure it's complete. if !check.isComplete(typ) { - x.mode_ = invalid + x.invalidate() x.expr = call return statement } @@ -342,7 +342,7 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { // if type inference failed, a parameterized result must be invalidated // (operands cannot have a parameterized type) if x.mode() == value && sig.TypeParams().Len() > 0 && isParameterized(sig.TypeParams().list(), x.typ()) { - x.mode_ = invalid + x.invalidate() } return statement @@ -938,7 +938,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, wantType bool return Error: - x.mode_ = invalid + x.invalidate() x.typ_ = Typ[Invalid] x.expr = e } diff --git a/src/cmd/compile/internal/types2/const.go b/src/cmd/compile/internal/types2/const.go index 875386d6ba..74f45a6e8b 100644 --- a/src/cmd/compile/internal/types2/const.go +++ b/src/cmd/compile/internal/types2/const.go @@ -238,7 +238,7 @@ func (check *Checker) representable(x *operand, typ *Basic) { v, code := check.representation(x, typ) if code != 0 { check.invalidConversion(code, x, typ) - x.mode_ = invalid + x.invalidate() return } assert(v != nil) @@ -292,7 +292,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) { t = safeUnderlying(target) } check.invalidConversion(code, x, t) - x.mode_ = invalid + x.invalidate() return } if val != nil { diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 40f982c332..693ccd4b60 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -47,7 +47,7 @@ func (check *Checker) conversion(x *operand, T Type) { // (go.dev/issue/63563) if !ok && isInteger(x.typ()) && isInteger(T) { check.errorf(x, InvalidConversion, "constant %s overflows %s", x.val, T) - x.mode_ = invalid + x.invalidate() return } case constArg && isTypeParam(T): @@ -89,7 +89,7 @@ func (check *Checker) conversion(x *operand, T Type) { } else { check.errorf(x, InvalidConversion, "cannot convert %s to type %s", x, T) } - x.mode_ = invalid + x.invalidate() return } diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 7925dbfb05..b092e74b0f 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -140,7 +140,7 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) { // requirement x may also be a composite literal." if _, ok := syntax.Unparen(e.X).(*syntax.CompositeLit); !ok && x.mode() != variable { check.errorf(x, UnaddressableOperand, invalidOp+"cannot take address of %s", x) - x.mode_ = invalid + x.invalidate() return } x.mode_ = value @@ -155,14 +155,14 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) { check.hasCallOrRecv = true return } - x.mode_ = invalid + x.invalidate() return case syntax.Tilde: // Provide a better error position and message than what check.op below would do. if !allInteger(x.typ()) { check.error(e, UndefinedOp, "cannot use ~ outside of interface or type constraint") - x.mode_ = invalid + x.invalidate() return } check.error(e, UndefinedOp, "cannot use ~ outside of interface or type constraint (use ^ for bitwise complement)") @@ -170,7 +170,7 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) { } if !check.op(unaryOpPredicates, x, op) { - x.mode_ = invalid + x.invalidate() return } @@ -494,7 +494,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const func (check *Checker) comparison(x, y *operand, op syntax.Operator, switchCase bool) { // Avoid spurious errors if any of the operands has an invalid type (go.dev/issue/54405). if !isValid(x.typ()) || !isValid(y.typ()) { - x.mode_ = invalid + x.invalidate() return } @@ -611,7 +611,7 @@ Error: } else { check.errorf(errOp, code, invalidOp+"%s %s %s (%s)", x.expr, op, y.expr, cause) } - x.mode_ = invalid + x.invalidate() } // incomparableCause returns a more specific cause why typ is not comparable. @@ -640,7 +640,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { } else { // shift has no chance check.errorf(x, InvalidShiftOperand, invalidOp+"shifted operand %s must be integer", x) - x.mode_ = invalid + x.invalidate() return } @@ -655,7 +655,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { yval = constant.ToInt(y.val) // consider -1, 1.0, but not -1.1 if yval.Kind() == constant.Int && constant.Sign(yval) < 0 { check.errorf(y, InvalidShiftCount, invalidOp+"negative shift count %s", y) - x.mode_ = invalid + x.invalidate() return } @@ -664,7 +664,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { // below, because isInteger includes untyped integers (was bug go.dev/issue/43697). check.representable(y, Typ[Uint]) if y.mode() == invalid { - x.mode_ = invalid + x.invalidate() return } } @@ -673,7 +673,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { switch { case allInteger(y.typ()): if !allUnsigned(y.typ()) && !check.verifyVersionf(y, go1_13, invalidOp+"signed shift count %s", y) { - x.mode_ = invalid + x.invalidate() return } case isUntyped(y.typ()): @@ -681,12 +681,12 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { // See also go.dev/issue/47410. check.convertUntyped(y, Typ[Uint]) if y.mode() == invalid { - x.mode_ = invalid + x.invalidate() return } default: check.errorf(y, InvalidShiftCount, invalidOp+"shift count %s must be integer", y) - x.mode_ = invalid + x.invalidate() return } } @@ -707,7 +707,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { s, ok := constant.Uint64Val(yval) if !ok || s > shiftBound { check.errorf(y, InvalidShiftCount, invalidOp+"invalid shift count %s", y) - x.mode_ = invalid + x.invalidate() return } // The lhs is representable as an integer but may not be an integer @@ -758,7 +758,7 @@ func (check *Checker) shift(x, y *operand, e syntax.Expr, op syntax.Operator) { // non-constant shift - lhs must be an integer if !allInteger(x.typ()) { check.errorf(x, InvalidShiftOperand, invalidOp+"shifted operand %s must be integer", x) - x.mode_ = invalid + x.invalidate() return } @@ -798,7 +798,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op return } if y.mode() == invalid { - x.mode_ = invalid + x.invalidate() x.expr = y.expr return } @@ -828,12 +828,12 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op check.errorf(x, MismatchedTypes, invalidOp+"%s %s= %s (mismatched types %s and %s)", lhs, op, rhs, x.typ(), y.typ()) } } - x.mode_ = invalid + x.invalidate() return } if !check.op(binaryOpPredicates, x, op) { - x.mode_ = invalid + x.invalidate() return } @@ -841,7 +841,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op // check for zero divisor if (x.mode() == constant_ || allInteger(x.typ())) && y.mode() == constant_ && constant.Sign(y.val) == 0 { check.error(&y, DivByZero, invalidOp+"division by zero") - x.mode_ = invalid + x.invalidate() return } @@ -851,7 +851,7 @@ func (check *Checker) binary(x *operand, e syntax.Expr, lhs, rhs syntax.Expr, op re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im) if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 { check.error(&y, DivByZero, invalidOp+"division by zero") - x.mode_ = invalid + x.invalidate() return } } @@ -937,7 +937,7 @@ func (check *Checker) matchTypes(x, y *operand) { } check.convertUntyped(y, x.typ()) if y.mode() == invalid { - x.mode_ = invalid + x.invalidate() return } } @@ -1023,7 +1023,7 @@ func (check *Checker) nonGeneric(T *target, x *operand) { } if what != "" { check.errorf(x.expr, WrongTypeArgCount, "cannot use generic %s %s without instantiation", what, x.expr) - x.mode_ = invalid + x.invalidate() x.typ_ = Typ[Invalid] } } @@ -1034,7 +1034,7 @@ func (check *Checker) nonGeneric(T *target, x *operand) { func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Type) exprKind { // make sure x has a valid state in case of bailout // (was go.dev/issue/5770) - x.mode_ = invalid + x.invalidate() x.typ_ = Typ[Invalid] switch e := e.(type) { @@ -1243,7 +1243,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty return expression Error: - x.mode_ = invalid + x.invalidate() x.expr = e return statement // avoid follow-up errors } @@ -1400,7 +1400,7 @@ func (check *Checker) exclude(x *operand, modeset uint) { panic("unreachable") } check.errorf(x, code, msg, x) - x.mode_ = invalid + x.invalidate() } } @@ -1411,7 +1411,7 @@ func (check *Checker) singleValue(x *operand) { if t, ok := x.typ().(*Tuple); ok { assert(t.Len() != 1) check.errorf(x, TooManyValues, "multiple-value %s in single-value context", x) - x.mode_ = invalid + x.invalidate() } } } diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 68a7e62075..054def5402 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -26,7 +26,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo case typexpr: // type instantiation - x.mode_ = invalid + x.invalidate() // TODO(gri) here we re-evaluate e.X - try to avoid this x.typ_ = check.varType(e) if isValid(x.typ()) { @@ -49,7 +49,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo // We cannot index on an incomplete type; make sure it's complete. if !check.isComplete(x.typ()) { - x.mode_ = invalid + x.invalidate() return false } switch typ := x.typ().Underlying().(type) { @@ -57,14 +57,14 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo // Additionally, if x.typ is a pointer to an array type, indexing implicitly dereferences the value, meaning // its base type must also be complete. if !check.isComplete(typ.base) { - x.mode_ = invalid + x.invalidate() return false } case *Map: // Lastly, if x.typ is a map type, indexing must produce a value of a complete type, meaning // its element type must also be complete. if !check.isComplete(typ.elem) { - x.mode_ = invalid + x.invalidate() return false } } @@ -110,7 +110,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo case *Map: index := check.singleIndex(e) if index == nil { - x.mode_ = invalid + x.invalidate() return false } var key operand @@ -184,7 +184,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo if key != nil { index := check.singleIndex(e) if index == nil { - x.mode_ = invalid + x.invalidate() return false } var k operand @@ -207,13 +207,13 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo if !valid { check.errorf(e.Pos(), NonSliceableOperand, "cannot index %s", x) check.use(e.Index) - x.mode_ = invalid + x.invalidate() return false } index := check.singleIndex(e) if index == nil { - x.mode_ = invalid + x.invalidate() return false } @@ -277,7 +277,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { // However, if x.typ is a pointer to an array type, slicing implicitly dereferences the value, meaning // its base type must also be complete. if p, ok := x.typ().Underlying().(*Pointer); ok && !check.isComplete(p.base) { - x.mode_ = invalid + x.invalidate() return } @@ -286,7 +286,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { switch u := cu.(type) { case nil: // error reported above - x.mode_ = invalid + x.invalidate() return case *Basic: @@ -297,7 +297,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { at = e // e.Index[2] should be present but be careful } check.error(at, InvalidSliceExpr, invalidOp+"3-index slice of string") - x.mode_ = invalid + x.invalidate() return } valid = true @@ -316,7 +316,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { length = u.len if x.mode() != variable { check.errorf(x, NonSliceableOperand, "cannot slice unaddressable value %s", x) - x.mode_ = invalid + x.invalidate() return } x.typ_ = &Slice{elem: u.elem} @@ -335,7 +335,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { if !valid { check.errorf(x, NonSliceableOperand, "cannot slice %s", x) - x.mode_ = invalid + x.invalidate() return } @@ -344,7 +344,7 @@ func (check *Checker) sliceExpr(x *operand, e *syntax.SliceExpr) { // spec: "Only the first index may be omitted; it defaults to 0." if e.Full && (e.Index[1] == nil || e.Index[2] == nil) { check.error(e, InvalidSyntaxTree, "2nd and 3rd index required in 3-index slice") - x.mode_ = invalid + x.invalidate() return } diff --git a/src/cmd/compile/internal/types2/literals.go b/src/cmd/compile/internal/types2/literals.go index c52e070e44..e33efd93ea 100644 --- a/src/cmd/compile/internal/types2/literals.go +++ b/src/cmd/compile/internal/types2/literals.go @@ -57,7 +57,7 @@ func (check *Checker) basicLit(x *operand, e *syntax.BasicLit) { const limit = 10000 if len(e.Value) > limit { check.errorf(e, InvalidConstVal, "excessively long constant: %s... (%d chars)", e.Value[:10], len(e.Value)) - x.mode_ = invalid + x.invalidate() return } } @@ -68,7 +68,7 @@ func (check *Checker) basicLit(x *operand, e *syntax.BasicLit) { // TODO(gri) setConst (and in turn the go/constant package) // should return an error describing the issue. check.errorf(e, InvalidConstVal, "malformed constant: %s", e.Value) - x.mode_ = invalid + x.invalidate() return } // Ensure that integer values don't overflow (go.dev/issue/54280). @@ -100,7 +100,7 @@ func (check *Checker) funcLit(x *operand, e *syntax.FuncLit) { x.typ_ = sig } else { check.errorf(e, InvalidSyntaxTree, "invalid function literal %v", e) - x.mode_ = invalid + x.invalidate() } } @@ -145,7 +145,7 @@ func (check *Checker) compositeLit(x *operand, e *syntax.CompositeLit, hint Type // We cannot create a literal of an incomplete type; make sure it's complete. if !check.isComplete(base) { - x.mode_ = invalid + x.invalidate() return } @@ -311,7 +311,7 @@ func (check *Checker) compositeLit(x *operand, e *syntax.CompositeLit, hint Type cause = " (no common underlying type)" } check.errorf(e, InvalidLit, "invalid composite literal%s type %s%s", qualifier, typ, cause) - x.mode_ = invalid + x.invalidate() return } } diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index fe06fc7861..83066c0e30 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -72,6 +72,10 @@ func (x *operand) isValid() bool { return x.mode() != invalid } +func (x *operand) invalidate() { + x.mode_ = invalid +} + // Pos returns the position of the expression corresponding to x. // If x is invalid the position is nopos. func (x *operand) Pos() syntax.Pos { @@ -293,7 +297,7 @@ func (x *operand) setConst(k syntax.LitKind, lit string) { val := makeFromLiteral(lit, k) if val.Kind() == constant.Unknown { - x.mode_ = invalid + x.invalidate() x.typ_ = Typ[Invalid] return } diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index ecc202ddad..1da8afb238 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -723,7 +723,7 @@ func (check *Checker) switchStmt(inner stmtContext, s *syntax.SwitchStmt) { check.assignment(&x, nil, "switch expression") if x.mode() != invalid && !Comparable(x.typ()) && !hasNil(x.typ()) { check.errorf(&x, InvalidExprSwitch, "cannot switch on %s (%s is not comparable)", &x, x.typ()) - x.mode_ = invalid + x.invalidate() } } else { // spec: "A missing switch expression is diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index a9575230cf..8453e2d5eb 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -18,7 +18,7 @@ import ( // If an error occurred, x.mode is set to invalid. // If wantType is set, the identifier e is expected to denote a type. func (check *Checker) ident(x *operand, e *syntax.Name, wantType bool) { - x.mode_ = invalid + x.invalidate() x.expr = e scope, obj := check.lookupScope(e.Value) diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index 36413ff312..5655ea0b10 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -36,7 +36,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { // we may get here because of other problems (go.dev/issue/39634, crash 12) // TODO(gri) do we need a new "generic" error code here? check.errorf(x, IncompatibleAssign, "cannot assign %s to %s in %s", x, T, context) - x.mode_ = invalid + x.invalidate() return } @@ -51,7 +51,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { if x.isNil() { if T == nil { check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context) - x.mode_ = invalid + x.invalidate() return } } else if T == nil || isNonTypeParamInterface(T) { @@ -61,7 +61,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { if T == nil || isNonTypeParamInterface(T) { if T == nil && x.typ() == Typ[UntypedNil] { check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context) - x.mode_ = invalid + x.invalidate() return } target = Default(x.typ()) @@ -79,7 +79,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { code = IncompatibleAssign } check.error(x, code, msg) - x.mode_ = invalid + x.invalidate() return } if val != nil { @@ -114,7 +114,7 @@ func (check *Checker) assignment(x *operand, T Type, context string) { } else { check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context) } - x.mode_ = invalid + x.invalidate() } } @@ -158,7 +158,7 @@ func (check *Checker) initVar(lhs *Var, x *operand, context string) { if lhs.typ == nil { lhs.typ = Typ[Invalid] } - x.mode_ = invalid + x.invalidate() return } @@ -170,7 +170,7 @@ func (check *Checker) initVar(lhs *Var, x *operand, context string) { if typ == Typ[UntypedNil] { check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context) lhs.typ = Typ[Invalid] - x.mode_ = invalid + x.invalidate() return } typ = Default(typ) @@ -253,7 +253,7 @@ func (check *Checker) assignVar(lhs, rhs ast.Expr, x *operand, context string) { T := check.lhsVar(lhs) // nil if lhs is _ if !isValid(T) { if x != nil { - x.mode_ = invalid + x.invalidate() } else { check.use(rhs) } diff --git a/src/go/types/call.go b/src/go/types/call.go index d9368c618d..0b8ef351db 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -50,7 +50,7 @@ func (check *Checker) funcInst(T *target, pos token.Pos, x *operand, ix *indexed xlist = ix.indices targs = check.typeList(xlist) if targs == nil { - x.mode_ = invalid + x.invalidate() return nil } assert(len(targs) == len(xlist)) @@ -64,7 +64,7 @@ func (check *Checker) funcInst(T *target, pos token.Pos, x *operand, ix *indexed if got > want { // Providing too many type arguments is always an error. check.errorf(ix.indices[got-1], WrongTypeArgCount, "got %d type arguments but want %d", got, want) - x.mode_ = invalid + x.invalidate() return nil } @@ -115,7 +115,7 @@ func (check *Checker) funcInst(T *target, pos token.Pos, x *operand, ix *indexed if !err.empty() { err.report() } - x.mode_ = invalid + x.invalidate() return nil } got = len(targs) @@ -200,7 +200,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { return conversion } T := x.typ() - x.mode_ = invalid + x.invalidate() // We cannot convert a value to an incomplete type; make sure it's complete. if !check.isComplete(T) { x.expr = call @@ -235,7 +235,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { // no need to check for non-genericity here id := x.id if !check.builtin(x, call, id) { - x.mode_ = invalid + x.invalidate() } x.expr = call // a non-constant result implies a function call @@ -259,7 +259,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { }) if err != nil { check.errorf(x, InvalidCall, invalidOp+"cannot call %s: %s", x, err.format(check)) - x.mode_ = invalid + x.invalidate() x.expr = call return statement } @@ -276,7 +276,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { targs = check.typeList(xlist) if targs == nil { check.use(call.Args...) - x.mode_ = invalid + x.invalidate() x.expr = call return statement } @@ -287,7 +287,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { if got > want { check.errorf(xlist[want], WrongTypeArgCount, "got %d type arguments but want %d", got, want) check.use(call.Args...) - x.mode_ = invalid + x.invalidate() x.expr = call return statement } @@ -329,7 +329,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { typ := sig.results.vars[0].typ // unpack tuple // We cannot return a value of an incomplete type; make sure it's complete. if !check.isComplete(typ) { - x.mode_ = invalid + x.invalidate() x.expr = call return statement } @@ -344,7 +344,7 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { // if type inference failed, a parameterized result must be invalidated // (operands cannot have a parameterized type) if x.mode() == value && sig.TypeParams().Len() > 0 && isParameterized(sig.TypeParams().list(), x.typ()) { - x.mode_ = invalid + x.invalidate() } return statement @@ -986,7 +986,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr, wantType bool) { return Error: - x.mode_ = invalid + x.invalidate() x.typ_ = Typ[Invalid] x.expr = e } diff --git a/src/go/types/const.go b/src/go/types/const.go index 5162aac22c..f897df63a7 100644 --- a/src/go/types/const.go +++ b/src/go/types/const.go @@ -240,7 +240,7 @@ func (check *Checker) representable(x *operand, typ *Basic) { v, code := check.representation(x, typ) if code != 0 { check.invalidConversion(code, x, typ) - x.mode_ = invalid + x.invalidate() return } assert(v != nil) @@ -294,7 +294,7 @@ func (check *Checker) convertUntyped(x *operand, target Type) { t = safeUnderlying(target) } check.invalidConversion(code, x, t) - x.mode_ = invalid + x.invalidate() return } if val != nil { diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index 7f0bc8efb2..2794b55bf5 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -50,7 +50,7 @@ func (check *Checker) conversion(x *operand, T Type) { // (go.dev/issue/63563) if !ok && isInteger(x.typ()) && isInteger(T) { check.errorf(x, InvalidConversion, "constant %s overflows %s", x.val, T) - x.mode_ = invalid + x.invalidate() return } case constArg && isTypeParam(T): @@ -92,7 +92,7 @@ func (check *Checker) conversion(x *operand, T Type) { } else { check.errorf(x, InvalidConversion, "cannot convert %s to type %s", x, T) } - x.mode_ = invalid + x.invalidate() return } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 840452dcc0..344246e741 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -139,7 +139,7 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { // requirement x may also be a composite literal." if _, ok := ast.Unparen(e.X).(*ast.CompositeLit); !ok && x.mode() != variable { check.errorf(x, UnaddressableOperand, invalidOp+"cannot take address of %s", x) - x.mode_ = invalid + x.invalidate() return } x.mode_ = value @@ -154,14 +154,14 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { check.hasCallOrRecv = true return } - x.mode_ = invalid + x.invalidate() return case token.TILDE: // Provide a better error position and message than what check.op below would do. if !allInteger(x.typ()) { check.error(e, UndefinedOp, "cannot use ~ outside of interface or type constraint") - x.mode_ = invalid + x.invalidate() return } check.error(e, UndefinedOp, "cannot use ~ outside of interface or type constraint (use ^ for bitwise complement)") @@ -169,7 +169,7 @@ func (check *Checker) unary(x *operand, e *ast.UnaryExpr) { } if !check.op(unaryOpPredicates, x, op) { - x.mode_ = invalid + x.invalidate() return } @@ -483,7 +483,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const func (check *Checker) comparison(x, y *operand, op token.Token, switchCase bool) { // Avoid spurious errors if any of the operands has an invalid type (go.dev/issue/54405). if !isValid(x.typ()) || !isValid(y.typ()) { - x.mode_ = invalid + x.invalidate() return } @@ -600,7 +600,7 @@ Error: } else { check.errorf(errOp, code, invalidOp+"%s %s %s (%s)", x.expr, op, y.expr, cause) } - x.mode_ = invalid + x.invalidate() } // incomparableCause returns a more specific cause why typ is not comparable. @@ -629,7 +629,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { } else { // shift has no chance check.errorf(x, InvalidShiftOperand, invalidOp+"shifted operand %s must be integer", x) - x.mode_ = invalid + x.invalidate() return } @@ -644,7 +644,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { yval = constant.ToInt(y.val) // consider -1, 1.0, but not -1.1 if yval.Kind() == constant.Int && constant.Sign(yval) < 0 { check.errorf(y, InvalidShiftCount, invalidOp+"negative shift count %s", y) - x.mode_ = invalid + x.invalidate() return } @@ -653,7 +653,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { // below, because isInteger includes untyped integers (was bug go.dev/issue/43697). check.representable(y, Typ[Uint]) if y.mode() == invalid { - x.mode_ = invalid + x.invalidate() return } } @@ -662,7 +662,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { switch { case allInteger(y.typ()): if !allUnsigned(y.typ()) && !check.verifyVersionf(y, go1_13, invalidOp+"signed shift count %s", y) { - x.mode_ = invalid + x.invalidate() return } case isUntyped(y.typ()): @@ -670,12 +670,12 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { // See also go.dev/issue/47410. check.convertUntyped(y, Typ[Uint]) if y.mode() == invalid { - x.mode_ = invalid + x.invalidate() return } default: check.errorf(y, InvalidShiftCount, invalidOp+"shift count %s must be integer", y) - x.mode_ = invalid + x.invalidate() return } } @@ -696,7 +696,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { s, ok := constant.Uint64Val(yval) if !ok || s > shiftBound { check.errorf(y, InvalidShiftCount, invalidOp+"invalid shift count %s", y) - x.mode_ = invalid + x.invalidate() return } // The lhs is representable as an integer but may not be an integer @@ -747,7 +747,7 @@ func (check *Checker) shift(x, y *operand, e ast.Expr, op token.Token) { // non-constant shift - lhs must be an integer if !allInteger(x.typ()) { check.errorf(x, InvalidShiftOperand, invalidOp+"shifted operand %s must be integer", x) - x.mode_ = invalid + x.invalidate() return } @@ -787,7 +787,7 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token return } if y.mode() == invalid { - x.mode_ = invalid + x.invalidate() x.expr = y.expr return } @@ -821,12 +821,12 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token check.errorf(posn, MismatchedTypes, invalidOp+"%s %s= %s (mismatched types %s and %s)", lhs, op, rhs, x.typ(), y.typ()) } } - x.mode_ = invalid + x.invalidate() return } if !check.op(binaryOpPredicates, x, op) { - x.mode_ = invalid + x.invalidate() return } @@ -834,7 +834,7 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token // check for zero divisor if (x.mode() == constant_ || allInteger(x.typ())) && y.mode() == constant_ && constant.Sign(y.val) == 0 { check.error(&y, DivByZero, invalidOp+"division by zero") - x.mode_ = invalid + x.invalidate() return } @@ -844,7 +844,7 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im) if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 { check.error(&y, DivByZero, invalidOp+"division by zero") - x.mode_ = invalid + x.invalidate() return } } @@ -929,7 +929,7 @@ func (check *Checker) matchTypes(x, y *operand) { } check.convertUntyped(y, x.typ()) if y.mode() == invalid { - x.mode_ = invalid + x.invalidate() return } } @@ -1015,7 +1015,7 @@ func (check *Checker) nonGeneric(T *target, x *operand) { } if what != "" { check.errorf(x.expr, WrongTypeArgCount, "cannot use generic %s %s without instantiation", what, x.expr) - x.mode_ = invalid + x.invalidate() x.typ_ = Typ[Invalid] } } @@ -1026,7 +1026,7 @@ func (check *Checker) nonGeneric(T *target, x *operand) { func (check *Checker) exprInternal(T *target, x *operand, e ast.Expr, hint Type) exprKind { // make sure x has a valid state in case of bailout // (was go.dev/issue/5770) - x.mode_ = invalid + x.invalidate() x.typ_ = Typ[Invalid] switch e := e.(type) { @@ -1194,7 +1194,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e ast.Expr, hint Type) return expression Error: - x.mode_ = invalid + x.invalidate() x.expr = e return statement // avoid follow-up errors } @@ -1351,7 +1351,7 @@ func (check *Checker) exclude(x *operand, modeset uint) { panic("unreachable") } check.errorf(x, code, msg, x) - x.mode_ = invalid + x.invalidate() } } @@ -1362,7 +1362,7 @@ func (check *Checker) singleValue(x *operand) { if t, ok := x.typ().(*Tuple); ok { assert(t.Len() != 1) check.errorf(x, TooManyValues, "multiple-value %s in single-value context", x) - x.mode_ = invalid + x.invalidate() } } } diff --git a/src/go/types/index.go b/src/go/types/index.go index 8dc46f0783..8a540151cb 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -27,7 +27,7 @@ func (check *Checker) indexExpr(x *operand, e *indexedExpr) (isFuncInst bool) { case typexpr: // type instantiation - x.mode_ = invalid + x.invalidate() // TODO(gri) here we re-evaluate e.X - try to avoid this x.typ_ = check.varType(e.orig) if isValid(x.typ()) { @@ -50,7 +50,7 @@ func (check *Checker) indexExpr(x *operand, e *indexedExpr) (isFuncInst bool) { // We cannot index on an incomplete type; make sure it's complete. if !check.isComplete(x.typ()) { - x.mode_ = invalid + x.invalidate() return false } switch typ := x.typ().Underlying().(type) { @@ -58,14 +58,14 @@ func (check *Checker) indexExpr(x *operand, e *indexedExpr) (isFuncInst bool) { // Additionally, if x.typ is a pointer to an array type, indexing implicitly dereferences the value, meaning // its base type must also be complete. if !check.isComplete(typ.base) { - x.mode_ = invalid + x.invalidate() return false } case *Map: // Lastly, if x.typ is a map type, indexing must produce a value of a complete type, meaning // its element type must also be complete. if !check.isComplete(typ.elem) { - x.mode_ = invalid + x.invalidate() return false } } @@ -111,7 +111,7 @@ func (check *Checker) indexExpr(x *operand, e *indexedExpr) (isFuncInst bool) { case *Map: index := check.singleIndex(e) if index == nil { - x.mode_ = invalid + x.invalidate() return false } var key operand @@ -185,7 +185,7 @@ func (check *Checker) indexExpr(x *operand, e *indexedExpr) (isFuncInst bool) { if key != nil { index := check.singleIndex(e) if index == nil { - x.mode_ = invalid + x.invalidate() return false } var k operand @@ -209,13 +209,13 @@ func (check *Checker) indexExpr(x *operand, e *indexedExpr) (isFuncInst bool) { // types2 uses the position of '[' for the error check.errorf(x, NonIndexableOperand, "cannot index %s", x) check.use(e.indices...) - x.mode_ = invalid + x.invalidate() return false } index := check.singleIndex(e) if index == nil { - x.mode_ = invalid + x.invalidate() return false } @@ -282,7 +282,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { // However, if x.typ is a pointer to an array type, slicing implicitly dereferences the value, meaning // its base type must also be complete. if p, ok := x.typ().Underlying().(*Pointer); ok && !check.isComplete(p.base) { - x.mode_ = invalid + x.invalidate() return } @@ -291,7 +291,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { switch u := cu.(type) { case nil: // error reported above - x.mode_ = invalid + x.invalidate() return case *Basic: @@ -302,7 +302,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { at = e // e.Index[2] should be present but be careful } check.error(at, InvalidSliceExpr, invalidOp+"3-index slice of string") - x.mode_ = invalid + x.invalidate() return } valid = true @@ -321,7 +321,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { length = u.len if x.mode() != variable { check.errorf(x, NonSliceableOperand, "cannot slice unaddressable value %s", x) - x.mode_ = invalid + x.invalidate() return } x.typ_ = &Slice{elem: u.elem} @@ -340,7 +340,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { if !valid { check.errorf(x, NonSliceableOperand, "cannot slice %s", x) - x.mode_ = invalid + x.invalidate() return } @@ -349,7 +349,7 @@ func (check *Checker) sliceExpr(x *operand, e *ast.SliceExpr) { // spec: "Only the first index may be omitted; it defaults to 0." if e.Slice3 && (e.High == nil || e.Max == nil) { check.error(inNode(e, e.Rbrack), InvalidSyntaxTree, "2nd and 3rd index required in 3-index slice") - x.mode_ = invalid + x.invalidate() return } diff --git a/src/go/types/literals.go b/src/go/types/literals.go index 11366f1d45..bc98ae8db0 100644 --- a/src/go/types/literals.go +++ b/src/go/types/literals.go @@ -61,7 +61,7 @@ func (check *Checker) basicLit(x *operand, e *ast.BasicLit) { const limit = 10000 if len(e.Value) > limit { check.errorf(e, InvalidConstVal, "excessively long constant: %s... (%d chars)", e.Value[:10], len(e.Value)) - x.mode_ = invalid + x.invalidate() return } } @@ -72,7 +72,7 @@ func (check *Checker) basicLit(x *operand, e *ast.BasicLit) { // TODO(gri) setConst (and in turn the go/constant package) // should return an error describing the issue. check.errorf(e, InvalidConstVal, "malformed constant: %s", e.Value) - x.mode_ = invalid + x.invalidate() return } // Ensure that integer values don't overflow (go.dev/issue/54280). @@ -104,7 +104,7 @@ func (check *Checker) funcLit(x *operand, e *ast.FuncLit) { x.typ_ = sig } else { check.errorf(e, InvalidSyntaxTree, "invalid function literal %v", e) - x.mode_ = invalid + x.invalidate() } } @@ -149,7 +149,7 @@ func (check *Checker) compositeLit(x *operand, e *ast.CompositeLit, hint Type) { // We cannot create a literal of an incomplete type; make sure it's complete. if !check.isComplete(base) { - x.mode_ = invalid + x.invalidate() return } @@ -315,7 +315,7 @@ func (check *Checker) compositeLit(x *operand, e *ast.CompositeLit, hint Type) { cause = " (no common underlying type)" } check.errorf(e, InvalidLit, "invalid composite literal%s type %s%s", qualifier, typ, cause) - x.mode_ = invalid + x.invalidate() return } } diff --git a/src/go/types/operand.go b/src/go/types/operand.go index b5c24a802c..66850d67d6 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -76,6 +76,10 @@ func (x *operand) isValid() bool { return x.mode() != invalid } +func (x *operand) invalidate() { + x.mode_ = invalid +} + // Pos returns the position of the expression corresponding to x. // If x is invalid the position is nopos. func (x *operand) Pos() token.Pos { @@ -297,7 +301,7 @@ func (x *operand) setConst(k token.Token, lit string) { val := makeFromLiteral(lit, k) if val.Kind() == constant.Unknown { - x.mode_ = invalid + x.invalidate() x.typ_ = Typ[Invalid] return } diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index ee2f872577..773c2fd590 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -638,7 +638,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { check.assignment(&x, nil, "switch expression") if x.mode() != invalid && !Comparable(x.typ()) && !hasNil(x.typ()) { check.errorf(&x, InvalidExprSwitch, "cannot switch on %s (%s is not comparable)", &x, x.typ()) - x.mode_ = invalid + x.invalidate() } } else { // spec: "A missing switch expression is diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index 79b7f6b5ca..c718922572 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -18,7 +18,7 @@ import ( // If an error occurred, x.mode is set to invalid. // If wantType is set, the identifier e is expected to denote a type. func (check *Checker) ident(x *operand, e *ast.Ident, wantType bool) { - x.mode_ = invalid + x.invalidate() x.expr = e scope, obj := check.lookupScope(e.Name) -- 2.52.0