// 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
}
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) {
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())
code = IncompatibleAssign
}
check.error(x, code, msg)
- x.mode_ = invalid
+ x.invalidate()
return
}
if val != nil {
} else {
check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context)
}
- x.mode_ = invalid
+ x.invalidate()
}
}
if lhs.typ == nil {
lhs.typ = Typ[Invalid]
}
- x.mode_ = invalid
+ x.invalidate()
return
}
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)
T := check.lhsVar(lhs) // nil if lhs is _
if !isValid(T) {
if x != nil {
- x.mode_ = invalid
+ x.invalidate()
} else {
check.use(rhs)
}
xlist = syntax.UnpackListExpr(inst.Index)
targs = check.typeList(xlist)
if targs == nil {
- x.mode_ = invalid
+ x.invalidate()
return nil
}
assert(len(targs) == len(xlist))
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
}
if !err.empty() {
err.report()
}
- x.mode_ = invalid
+ x.invalidate()
return nil
}
got = len(targs)
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
// 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
})
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
}
targs = check.typeList(xlist)
if targs == nil {
check.use(call.ArgList...)
- x.mode_ = invalid
+ x.invalidate()
x.expr = call
return statement
}
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
}
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
}
// 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
return
Error:
- x.mode_ = invalid
+ x.invalidate()
x.typ_ = Typ[Invalid]
x.expr = e
}
v, code := check.representation(x, typ)
if code != 0 {
check.invalidConversion(code, x, typ)
- x.mode_ = invalid
+ x.invalidate()
return
}
assert(v != nil)
t = safeUnderlying(target)
}
check.invalidConversion(code, x, t)
- x.mode_ = invalid
+ x.invalidate()
return
}
if val != nil {
// (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):
} else {
check.errorf(x, InvalidConversion, "cannot convert %s to type %s", x, T)
}
- x.mode_ = invalid
+ x.invalidate()
return
}
// 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
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)")
}
if !check.op(unaryOpPredicates, x, op) {
- x.mode_ = invalid
+ x.invalidate()
return
}
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
}
} 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.
} else {
// shift has no chance
check.errorf(x, InvalidShiftOperand, invalidOp+"shifted operand %s must be integer", x)
- x.mode_ = invalid
+ x.invalidate()
return
}
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
}
// 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
}
}
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()):
// 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
}
}
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
// 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
}
return
}
if y.mode() == invalid {
- x.mode_ = invalid
+ x.invalidate()
x.expr = y.expr
return
}
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
}
// 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
}
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
}
}
}
check.convertUntyped(y, x.typ())
if y.mode() == invalid {
- x.mode_ = invalid
+ x.invalidate()
return
}
}
}
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]
}
}
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) {
return expression
Error:
- x.mode_ = invalid
+ x.invalidate()
x.expr = e
return statement // avoid follow-up errors
}
panic("unreachable")
}
check.errorf(x, code, msg, x)
- x.mode_ = invalid
+ x.invalidate()
}
}
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()
}
}
}
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()) {
// 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) {
// 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
}
}
case *Map:
index := check.singleIndex(e)
if index == nil {
- x.mode_ = invalid
+ x.invalidate()
return false
}
var key operand
if key != nil {
index := check.singleIndex(e)
if index == nil {
- x.mode_ = invalid
+ x.invalidate()
return false
}
var k operand
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
}
// 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
}
switch u := cu.(type) {
case nil:
// error reported above
- x.mode_ = invalid
+ x.invalidate()
return
case *Basic:
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
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}
if !valid {
check.errorf(x, NonSliceableOperand, "cannot slice %s", x)
- x.mode_ = invalid
+ x.invalidate()
return
}
// 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
}
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
}
}
// 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).
x.typ_ = sig
} else {
check.errorf(e, InvalidSyntaxTree, "invalid function literal %v", e)
- x.mode_ = invalid
+ x.invalidate()
}
}
// We cannot create a literal of an incomplete type; make sure it's complete.
if !check.isComplete(base) {
- x.mode_ = invalid
+ x.invalidate()
return
}
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
}
}
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 {
val := makeFromLiteral(lit, k)
if val.Kind() == constant.Unknown {
- x.mode_ = invalid
+ x.invalidate()
x.typ_ = Typ[Invalid]
return
}
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
// 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)
// 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
}
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) {
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())
code = IncompatibleAssign
}
check.error(x, code, msg)
- x.mode_ = invalid
+ x.invalidate()
return
}
if val != nil {
} else {
check.errorf(x, code, "cannot use %s as %s value in %s", x, T, context)
}
- x.mode_ = invalid
+ x.invalidate()
}
}
if lhs.typ == nil {
lhs.typ = Typ[Invalid]
}
- x.mode_ = invalid
+ x.invalidate()
return
}
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)
T := check.lhsVar(lhs) // nil if lhs is _
if !isValid(T) {
if x != nil {
- x.mode_ = invalid
+ x.invalidate()
} else {
check.use(rhs)
}
xlist = ix.indices
targs = check.typeList(xlist)
if targs == nil {
- x.mode_ = invalid
+ x.invalidate()
return nil
}
assert(len(targs) == len(xlist))
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
}
if !err.empty() {
err.report()
}
- x.mode_ = invalid
+ x.invalidate()
return nil
}
got = len(targs)
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
// 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
})
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
}
targs = check.typeList(xlist)
if targs == nil {
check.use(call.Args...)
- x.mode_ = invalid
+ x.invalidate()
x.expr = call
return statement
}
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
}
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
}
// 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
return
Error:
- x.mode_ = invalid
+ x.invalidate()
x.typ_ = Typ[Invalid]
x.expr = e
}
v, code := check.representation(x, typ)
if code != 0 {
check.invalidConversion(code, x, typ)
- x.mode_ = invalid
+ x.invalidate()
return
}
assert(v != nil)
t = safeUnderlying(target)
}
check.invalidConversion(code, x, t)
- x.mode_ = invalid
+ x.invalidate()
return
}
if val != nil {
// (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):
} else {
check.errorf(x, InvalidConversion, "cannot convert %s to type %s", x, T)
}
- x.mode_ = invalid
+ x.invalidate()
return
}
// 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
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)")
}
if !check.op(unaryOpPredicates, x, op) {
- x.mode_ = invalid
+ x.invalidate()
return
}
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
}
} 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.
} else {
// shift has no chance
check.errorf(x, InvalidShiftOperand, invalidOp+"shifted operand %s must be integer", x)
- x.mode_ = invalid
+ x.invalidate()
return
}
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
}
// 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
}
}
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()):
// 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
}
}
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
// 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
}
return
}
if y.mode() == invalid {
- x.mode_ = invalid
+ x.invalidate()
x.expr = y.expr
return
}
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
}
// 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
}
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
}
}
}
check.convertUntyped(y, x.typ())
if y.mode() == invalid {
- x.mode_ = invalid
+ x.invalidate()
return
}
}
}
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]
}
}
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) {
return expression
Error:
- x.mode_ = invalid
+ x.invalidate()
x.expr = e
return statement // avoid follow-up errors
}
panic("unreachable")
}
check.errorf(x, code, msg, x)
- x.mode_ = invalid
+ x.invalidate()
}
}
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()
}
}
}
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()) {
// 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) {
// 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
}
}
case *Map:
index := check.singleIndex(e)
if index == nil {
- x.mode_ = invalid
+ x.invalidate()
return false
}
var key operand
if key != nil {
index := check.singleIndex(e)
if index == nil {
- x.mode_ = invalid
+ x.invalidate()
return false
}
var k operand
// 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
}
// 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
}
switch u := cu.(type) {
case nil:
// error reported above
- x.mode_ = invalid
+ x.invalidate()
return
case *Basic:
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
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}
if !valid {
check.errorf(x, NonSliceableOperand, "cannot slice %s", x)
- x.mode_ = invalid
+ x.invalidate()
return
}
// 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
}
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
}
}
// 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).
x.typ_ = sig
} else {
check.errorf(e, InvalidSyntaxTree, "invalid function literal %v", e)
- x.mode_ = invalid
+ x.invalidate()
}
}
// We cannot create a literal of an incomplete type; make sure it's complete.
if !check.isComplete(base) {
- x.mode_ = invalid
+ x.invalidate()
return
}
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
}
}
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 {
val := makeFromLiteral(lit, k)
if val.Kind() == constant.Unknown {
- x.mode_ = invalid
+ x.invalidate()
x.typ_ = Typ[Invalid]
return
}
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
// 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)