github.com/lovishpuri/go-40569/src@v0.0.0-20230519171745-f8623e7c56cf/go/types/const.go (about) 1 // Code generated by "go test -run=Generate -write=all"; DO NOT EDIT. 2 3 // Copyright 2023 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 // This file implements functions for untyped constant operands. 8 9 package types 10 11 import ( 12 "go/constant" 13 "go/token" 14 . "internal/types/errors" 15 "math" 16 ) 17 18 // overflow checks that the constant x is representable by its type. 19 // For untyped constants, it checks that the value doesn't become 20 // arbitrarily large. 21 func (check *Checker) overflow(x *operand, opPos token.Pos) { 22 assert(x.mode == constant_) 23 24 if x.val.Kind() == constant.Unknown { 25 // TODO(gri) We should report exactly what went wrong. At the 26 // moment we don't have the (go/constant) API for that. 27 // See also TODO in go/constant/value.go. 28 check.error(atPos(opPos), InvalidConstVal, "constant result is not representable") 29 return 30 } 31 32 // Typed constants must be representable in 33 // their type after each constant operation. 34 // x.typ cannot be a type parameter (type 35 // parameters cannot be constant types). 36 if isTyped(x.typ) { 37 check.representable(x, under(x.typ).(*Basic)) 38 return 39 } 40 41 // Untyped integer values must not grow arbitrarily. 42 const prec = 512 // 512 is the constant precision 43 if x.val.Kind() == constant.Int && constant.BitLen(x.val) > prec { 44 op := opName(x.expr) 45 if op != "" { 46 op += " " 47 } 48 check.errorf(atPos(opPos), InvalidConstVal, "constant %soverflow", op) 49 x.val = constant.MakeUnknown() 50 } 51 } 52 53 // representableConst reports whether x can be represented as 54 // value of the given basic type and for the configuration 55 // provided (only needed for int/uint sizes). 56 // 57 // If rounded != nil, *rounded is set to the rounded value of x for 58 // representable floating-point and complex values, and to an Int 59 // value for integer values; it is left alone otherwise. 60 // It is ok to provide the addressof the first argument for rounded. 61 // 62 // The check parameter may be nil if representableConst is invoked 63 // (indirectly) through an exported API call (AssignableTo, ConvertibleTo) 64 // because we don't need the Checker's config for those calls. 65 func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *constant.Value) bool { 66 if x.Kind() == constant.Unknown { 67 return true // avoid follow-up errors 68 } 69 70 var conf *Config 71 if check != nil { 72 conf = check.conf 73 } 74 75 sizeof := func(T Type) int64 { 76 s := conf.sizeof(T) 77 assert(s == 4 || s == 8) 78 return s 79 } 80 81 switch { 82 case isInteger(typ): 83 x := constant.ToInt(x) 84 if x.Kind() != constant.Int { 85 return false 86 } 87 if rounded != nil { 88 *rounded = x 89 } 90 if x, ok := constant.Int64Val(x); ok { 91 switch typ.kind { 92 case Int: 93 var s = uint(sizeof(typ)) * 8 94 return int64(-1)<<(s-1) <= x && x <= int64(1)<<(s-1)-1 95 case Int8: 96 const s = 8 97 return -1<<(s-1) <= x && x <= 1<<(s-1)-1 98 case Int16: 99 const s = 16 100 return -1<<(s-1) <= x && x <= 1<<(s-1)-1 101 case Int32: 102 const s = 32 103 return -1<<(s-1) <= x && x <= 1<<(s-1)-1 104 case Int64, UntypedInt: 105 return true 106 case Uint, Uintptr: 107 if s := uint(sizeof(typ)) * 8; s < 64 { 108 return 0 <= x && x <= int64(1)<<s-1 109 } 110 return 0 <= x 111 case Uint8: 112 const s = 8 113 return 0 <= x && x <= 1<<s-1 114 case Uint16: 115 const s = 16 116 return 0 <= x && x <= 1<<s-1 117 case Uint32: 118 const s = 32 119 return 0 <= x && x <= 1<<s-1 120 case Uint64: 121 return 0 <= x 122 default: 123 unreachable() 124 } 125 } 126 // x does not fit into int64 127 switch n := constant.BitLen(x); typ.kind { 128 case Uint, Uintptr: 129 var s = uint(sizeof(typ)) * 8 130 return constant.Sign(x) >= 0 && n <= int(s) 131 case Uint64: 132 return constant.Sign(x) >= 0 && n <= 64 133 case UntypedInt: 134 return true 135 } 136 137 case isFloat(typ): 138 x := constant.ToFloat(x) 139 if x.Kind() != constant.Float { 140 return false 141 } 142 switch typ.kind { 143 case Float32: 144 if rounded == nil { 145 return fitsFloat32(x) 146 } 147 r := roundFloat32(x) 148 if r != nil { 149 *rounded = r 150 return true 151 } 152 case Float64: 153 if rounded == nil { 154 return fitsFloat64(x) 155 } 156 r := roundFloat64(x) 157 if r != nil { 158 *rounded = r 159 return true 160 } 161 case UntypedFloat: 162 return true 163 default: 164 unreachable() 165 } 166 167 case isComplex(typ): 168 x := constant.ToComplex(x) 169 if x.Kind() != constant.Complex { 170 return false 171 } 172 switch typ.kind { 173 case Complex64: 174 if rounded == nil { 175 return fitsFloat32(constant.Real(x)) && fitsFloat32(constant.Imag(x)) 176 } 177 re := roundFloat32(constant.Real(x)) 178 im := roundFloat32(constant.Imag(x)) 179 if re != nil && im != nil { 180 *rounded = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) 181 return true 182 } 183 case Complex128: 184 if rounded == nil { 185 return fitsFloat64(constant.Real(x)) && fitsFloat64(constant.Imag(x)) 186 } 187 re := roundFloat64(constant.Real(x)) 188 im := roundFloat64(constant.Imag(x)) 189 if re != nil && im != nil { 190 *rounded = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) 191 return true 192 } 193 case UntypedComplex: 194 return true 195 default: 196 unreachable() 197 } 198 199 case isString(typ): 200 return x.Kind() == constant.String 201 202 case isBoolean(typ): 203 return x.Kind() == constant.Bool 204 } 205 206 return false 207 } 208 209 func fitsFloat32(x constant.Value) bool { 210 f32, _ := constant.Float32Val(x) 211 f := float64(f32) 212 return !math.IsInf(f, 0) 213 } 214 215 func roundFloat32(x constant.Value) constant.Value { 216 f32, _ := constant.Float32Val(x) 217 f := float64(f32) 218 if !math.IsInf(f, 0) { 219 return constant.MakeFloat64(f) 220 } 221 return nil 222 } 223 224 func fitsFloat64(x constant.Value) bool { 225 f, _ := constant.Float64Val(x) 226 return !math.IsInf(f, 0) 227 } 228 229 func roundFloat64(x constant.Value) constant.Value { 230 f, _ := constant.Float64Val(x) 231 if !math.IsInf(f, 0) { 232 return constant.MakeFloat64(f) 233 } 234 return nil 235 } 236 237 // representable checks that a constant operand is representable in the given 238 // basic type. 239 func (check *Checker) representable(x *operand, typ *Basic) { 240 v, code := check.representation(x, typ) 241 if code != 0 { 242 check.invalidConversion(code, x, typ) 243 x.mode = invalid 244 return 245 } 246 assert(v != nil) 247 x.val = v 248 } 249 250 // representation returns the representation of the constant operand x as the 251 // basic type typ. 252 // 253 // If no such representation is possible, it returns a non-zero error code. 254 func (check *Checker) representation(x *operand, typ *Basic) (constant.Value, Code) { 255 assert(x.mode == constant_) 256 v := x.val 257 if !representableConst(x.val, check, typ, &v) { 258 if isNumeric(x.typ) && isNumeric(typ) { 259 // numeric conversion : error msg 260 // 261 // integer -> integer : overflows 262 // integer -> float : overflows (actually not possible) 263 // float -> integer : truncated 264 // float -> float : overflows 265 // 266 if !isInteger(x.typ) && isInteger(typ) { 267 return nil, TruncatedFloat 268 } else { 269 return nil, NumericOverflow 270 } 271 } 272 return nil, InvalidConstVal 273 } 274 return v, 0 275 } 276 277 func (check *Checker) invalidConversion(code Code, x *operand, target Type) { 278 msg := "cannot convert %s to type %s" 279 switch code { 280 case TruncatedFloat: 281 msg = "%s truncated to %s" 282 case NumericOverflow: 283 msg = "%s overflows %s" 284 } 285 check.errorf(x, code, msg, x, target) 286 } 287 288 // convertUntyped attempts to set the type of an untyped value to the target type. 289 func (check *Checker) convertUntyped(x *operand, target Type) { 290 newType, val, code := check.implicitTypeAndValue(x, target) 291 if code != 0 { 292 t := target 293 if !isTypeParam(target) { 294 t = safeUnderlying(target) 295 } 296 check.invalidConversion(code, x, t) 297 x.mode = invalid 298 return 299 } 300 if val != nil { 301 x.val = val 302 check.updateExprVal(x.expr, val) 303 } 304 if newType != x.typ { 305 x.typ = newType 306 check.updateExprType(x.expr, newType, false) 307 } 308 }