overflow checks that the constant x is representable by its type. For untyped constants, it checks that the value doesn't become arbitrarily large.
(x *operand)
| 88 | // For untyped constants, it checks that the value doesn't become |
| 89 | // arbitrarily large. |
| 90 | func (check *Checker) overflow(x *operand) { |
| 91 | assert(x.mode == constant_) |
| 92 | |
| 93 | // If the corresponding expression is an operation, use the |
| 94 | // operator position rather than the start of the expression |
| 95 | // as error position. |
| 96 | pos := StartPos(x.expr) |
| 97 | what := "" // operator description, if any |
| 98 | if op, _ := x.expr.(*Operation); op != nil { |
| 99 | pos = op.Pos() |
| 100 | what = opName(op) |
| 101 | } |
| 102 | |
| 103 | if x.val.Kind() == constant.Unknown { |
| 104 | // TODO(gri) We should report exactly what went wrong. At the |
| 105 | // moment we don't have the (go/constant) API for that. |
| 106 | // See also TODO in go/constant/value.go. |
| 107 | check.error(pos, "constant result is not representable") |
| 108 | return |
| 109 | } |
| 110 | |
| 111 | // Typed constants must be representable in |
| 112 | // their type after each constant operation. |
| 113 | // x.typ cannot be a type parameter (type |
| 114 | // parameters cannot be constant types). |
| 115 | if isTyped(x.typ) { |
| 116 | check.representable(x, under(x.typ).(*Basic)) |
| 117 | return |
| 118 | } |
| 119 | |
| 120 | // Untyped integer values must not grow arbitrarily. |
| 121 | const prec = 512 // 512 is the constant precision |
| 122 | if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec { |
| 123 | check.errorf(pos, "constant %s overflow", what) |
| 124 | x.val = constant.MakeUnknown() |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | // opName returns the name of an operation, or the empty string. |
| 129 | // Only operations that might overflow are handled. |