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  }