Source file src/cmd/compile/internal/typecheck/const.go

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package typecheck
     6  
     7  import (
     8  	"fmt"
     9  	"go/constant"
    10  	"go/token"
    11  	"math"
    12  	"math/big"
    13  	"unicode"
    14  
    15  	"cmd/compile/internal/base"
    16  	"cmd/compile/internal/ir"
    17  	"cmd/compile/internal/types"
    18  )
    19  
    20  func roundFloat(v constant.Value, sz int64) constant.Value {
    21  	switch sz {
    22  	case 4:
    23  		f, _ := constant.Float32Val(v)
    24  		return makeFloat64(float64(f))
    25  	case 8:
    26  		f, _ := constant.Float64Val(v)
    27  		return makeFloat64(f)
    28  	}
    29  	base.Fatalf("unexpected size: %v", sz)
    30  	panic("unreachable")
    31  }
    32  
    33  // truncate float literal fv to 32-bit or 64-bit precision
    34  // according to type; return truncated value.
    35  func truncfltlit(v constant.Value, t *types.Type) constant.Value {
    36  	if t.IsUntyped() {
    37  		return v
    38  	}
    39  
    40  	return roundFloat(v, t.Size())
    41  }
    42  
    43  // truncate Real and Imag parts of Mpcplx to 32-bit or 64-bit
    44  // precision, according to type; return truncated value. In case of
    45  // overflow, calls Errorf but does not truncate the input value.
    46  func trunccmplxlit(v constant.Value, t *types.Type) constant.Value {
    47  	if t.IsUntyped() {
    48  		return v
    49  	}
    50  
    51  	fsz := t.Size() / 2
    52  	return makeComplex(roundFloat(constant.Real(v), fsz), roundFloat(constant.Imag(v), fsz))
    53  }
    54  
    55  // TODO(mdempsky): Replace these with better APIs.
    56  func convlit(n ir.Node, t *types.Type) ir.Node    { return convlit1(n, t, false, nil) }
    57  func DefaultLit(n ir.Node, t *types.Type) ir.Node { return convlit1(n, t, false, nil) }
    58  
    59  // convlit1 converts an untyped expression n to type t. If n already
    60  // has a type, convlit1 has no effect.
    61  //
    62  // For explicit conversions, t must be non-nil, and integer-to-string
    63  // conversions are allowed.
    64  //
    65  // For implicit conversions (e.g., assignments), t may be nil; if so,
    66  // n is converted to its default type.
    67  //
    68  // If there's an error converting n to t, context is used in the error
    69  // message.
    70  func convlit1(n ir.Node, t *types.Type, explicit bool, context func() string) ir.Node {
    71  	if explicit && t == nil {
    72  		base.Fatalf("explicit conversion missing type")
    73  	}
    74  	if t != nil && t.IsUntyped() {
    75  		base.Fatalf("bad conversion to untyped: %v", t)
    76  	}
    77  
    78  	if n == nil || n.Type() == nil {
    79  		// Allow sloppy callers.
    80  		return n
    81  	}
    82  	if !n.Type().IsUntyped() {
    83  		// Already typed; nothing to do.
    84  		return n
    85  	}
    86  
    87  	// Nil is technically not a constant, so handle it specially.
    88  	if n.Type().Kind() == types.TNIL {
    89  		if n.Op() != ir.ONIL {
    90  			base.Fatalf("unexpected op: %v (%v)", n, n.Op())
    91  		}
    92  		n = ir.Copy(n)
    93  		if t == nil {
    94  			base.Fatalf("use of untyped nil")
    95  		}
    96  
    97  		if !t.HasNil() {
    98  			// Leave for caller to handle.
    99  			return n
   100  		}
   101  
   102  		n.SetType(t)
   103  		return n
   104  	}
   105  
   106  	if t == nil || !ir.OKForConst[t.Kind()] {
   107  		t = defaultType(n.Type())
   108  	}
   109  
   110  	switch n.Op() {
   111  	default:
   112  		base.Fatalf("unexpected untyped expression: %v", n)
   113  
   114  	case ir.OLITERAL:
   115  		v := ConvertVal(n.Val(), t, explicit)
   116  		if v.Kind() == constant.Unknown {
   117  			n = ir.NewConstExpr(n.Val(), n)
   118  			break
   119  		}
   120  		n = ir.NewConstExpr(v, n)
   121  		n.SetType(t)
   122  		return n
   123  
   124  	case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.OREAL, ir.OIMAG:
   125  		ot := operandType(n.Op(), t)
   126  		if ot == nil {
   127  			n = DefaultLit(n, nil)
   128  			break
   129  		}
   130  
   131  		n := n.(*ir.UnaryExpr)
   132  		n.X = convlit(n.X, ot)
   133  		if n.X.Type() == nil {
   134  			n.SetType(nil)
   135  			return n
   136  		}
   137  		n.SetType(t)
   138  		return n
   139  
   140  	case ir.OADD, ir.OSUB, ir.OMUL, ir.ODIV, ir.OMOD, ir.OOR, ir.OXOR, ir.OAND, ir.OANDNOT, ir.OOROR, ir.OANDAND, ir.OCOMPLEX:
   141  		ot := operandType(n.Op(), t)
   142  		if ot == nil {
   143  			n = DefaultLit(n, nil)
   144  			break
   145  		}
   146  
   147  		var l, r ir.Node
   148  		switch n := n.(type) {
   149  		case *ir.BinaryExpr:
   150  			n.X = convlit(n.X, ot)
   151  			n.Y = convlit(n.Y, ot)
   152  			l, r = n.X, n.Y
   153  		case *ir.LogicalExpr:
   154  			n.X = convlit(n.X, ot)
   155  			n.Y = convlit(n.Y, ot)
   156  			l, r = n.X, n.Y
   157  		}
   158  
   159  		if l.Type() == nil || r.Type() == nil {
   160  			n.SetType(nil)
   161  			return n
   162  		}
   163  		if !types.Identical(l.Type(), r.Type()) {
   164  			base.Errorf("invalid operation: %v (mismatched types %v and %v)", n, l.Type(), r.Type())
   165  			n.SetType(nil)
   166  			return n
   167  		}
   168  
   169  		n.SetType(t)
   170  		return n
   171  
   172  	case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
   173  		n := n.(*ir.BinaryExpr)
   174  		if !t.IsBoolean() {
   175  			break
   176  		}
   177  		n.SetType(t)
   178  		return n
   179  
   180  	case ir.OLSH, ir.ORSH:
   181  		n := n.(*ir.BinaryExpr)
   182  		n.X = convlit1(n.X, t, explicit, nil)
   183  		n.SetType(n.X.Type())
   184  		if n.Type() != nil && !n.Type().IsInteger() {
   185  			base.Errorf("invalid operation: %v (shift of type %v)", n, n.Type())
   186  			n.SetType(nil)
   187  		}
   188  		return n
   189  	}
   190  
   191  	if explicit {
   192  		base.Fatalf("cannot convert %L to type %v", n, t)
   193  	} else if context != nil {
   194  		base.Fatalf("cannot use %L as type %v in %s", n, t, context())
   195  	} else {
   196  		base.Fatalf("cannot use %L as type %v", n, t)
   197  	}
   198  
   199  	n.SetType(nil)
   200  	return n
   201  }
   202  
   203  func operandType(op ir.Op, t *types.Type) *types.Type {
   204  	switch op {
   205  	case ir.OCOMPLEX:
   206  		if t.IsComplex() {
   207  			return types.FloatForComplex(t)
   208  		}
   209  	case ir.OREAL, ir.OIMAG:
   210  		if t.IsFloat() {
   211  			return types.ComplexForFloat(t)
   212  		}
   213  	default:
   214  		if okfor[op][t.Kind()] {
   215  			return t
   216  		}
   217  	}
   218  	return nil
   219  }
   220  
   221  // ConvertVal converts v into a representation appropriate for t. If
   222  // no such representation exists, it returns constant.MakeUnknown()
   223  // instead.
   224  //
   225  // If explicit is true, then conversions from integer to string are
   226  // also allowed.
   227  func ConvertVal(v constant.Value, t *types.Type, explicit bool) constant.Value {
   228  	switch ct := v.Kind(); ct {
   229  	case constant.Bool:
   230  		if t.IsBoolean() {
   231  			return v
   232  		}
   233  
   234  	case constant.String:
   235  		if t.IsString() {
   236  			return v
   237  		}
   238  
   239  	case constant.Int:
   240  		if explicit && t.IsString() {
   241  			return tostr(v)
   242  		}
   243  		fallthrough
   244  	case constant.Float, constant.Complex:
   245  		switch {
   246  		case t.IsInteger():
   247  			v = toint(v)
   248  			return v
   249  		case t.IsFloat():
   250  			v = toflt(v)
   251  			v = truncfltlit(v, t)
   252  			return v
   253  		case t.IsComplex():
   254  			v = tocplx(v)
   255  			v = trunccmplxlit(v, t)
   256  			return v
   257  		}
   258  	}
   259  
   260  	return constant.MakeUnknown()
   261  }
   262  
   263  func tocplx(v constant.Value) constant.Value {
   264  	return constant.ToComplex(v)
   265  }
   266  
   267  func toflt(v constant.Value) constant.Value {
   268  	if v.Kind() == constant.Complex {
   269  		v = constant.Real(v)
   270  	}
   271  
   272  	return constant.ToFloat(v)
   273  }
   274  
   275  func toint(v constant.Value) constant.Value {
   276  	if v.Kind() == constant.Complex {
   277  		v = constant.Real(v)
   278  	}
   279  
   280  	if v := constant.ToInt(v); v.Kind() == constant.Int {
   281  		return v
   282  	}
   283  
   284  	// The value of v cannot be represented as an integer;
   285  	// so we need to print an error message.
   286  	// Unfortunately some float values cannot be
   287  	// reasonably formatted for inclusion in an error
   288  	// message (example: 1 + 1e-100), so first we try to
   289  	// format the float; if the truncation resulted in
   290  	// something that looks like an integer we omit the
   291  	// value from the error message.
   292  	// (See issue #11371).
   293  	f := ir.BigFloat(v)
   294  	if f.MantExp(nil) > 2*ir.ConstPrec {
   295  		base.Errorf("integer too large")
   296  	} else {
   297  		var t big.Float
   298  		t.Parse(fmt.Sprint(v), 0)
   299  		if t.IsInt() {
   300  			base.Errorf("constant truncated to integer")
   301  		} else {
   302  			base.Errorf("constant %v truncated to integer", v)
   303  		}
   304  	}
   305  
   306  	// Prevent follow-on errors.
   307  	return constant.MakeUnknown()
   308  }
   309  
   310  func tostr(v constant.Value) constant.Value {
   311  	if v.Kind() == constant.Int {
   312  		r := unicode.ReplacementChar
   313  		if x, ok := constant.Uint64Val(v); ok && x <= unicode.MaxRune {
   314  			r = rune(x)
   315  		}
   316  		v = constant.MakeString(string(r))
   317  	}
   318  	return v
   319  }
   320  
   321  func makeFloat64(f float64) constant.Value {
   322  	if math.IsInf(f, 0) {
   323  		base.Fatalf("infinity is not a valid constant")
   324  	}
   325  	return constant.MakeFloat64(f)
   326  }
   327  
   328  func makeComplex(real, imag constant.Value) constant.Value {
   329  	return constant.BinaryOp(constant.ToFloat(real), token.ADD, constant.MakeImag(constant.ToFloat(imag)))
   330  }
   331  
   332  // DefaultLit on both nodes simultaneously;
   333  // if they're both ideal going in they better
   334  // get the same type going out.
   335  // force means must assign concrete (non-ideal) type.
   336  // The results of defaultlit2 MUST be assigned back to l and r, e.g.
   337  //
   338  //	n.Left, n.Right = defaultlit2(n.Left, n.Right, force)
   339  func defaultlit2(l ir.Node, r ir.Node, force bool) (ir.Node, ir.Node) {
   340  	if l.Type() == nil || r.Type() == nil {
   341  		return l, r
   342  	}
   343  
   344  	if !l.Type().IsInterface() && !r.Type().IsInterface() {
   345  		// Can't mix bool with non-bool, string with non-string.
   346  		if l.Type().IsBoolean() != r.Type().IsBoolean() {
   347  			return l, r
   348  		}
   349  		if l.Type().IsString() != r.Type().IsString() {
   350  			return l, r
   351  		}
   352  	}
   353  
   354  	if !l.Type().IsUntyped() {
   355  		r = convlit(r, l.Type())
   356  		return l, r
   357  	}
   358  
   359  	if !r.Type().IsUntyped() {
   360  		l = convlit(l, r.Type())
   361  		return l, r
   362  	}
   363  
   364  	if !force {
   365  		return l, r
   366  	}
   367  
   368  	// Can't mix nil with anything untyped.
   369  	if ir.IsNil(l) || ir.IsNil(r) {
   370  		return l, r
   371  	}
   372  	t := defaultType(mixUntyped(l.Type(), r.Type()))
   373  	l = convlit(l, t)
   374  	r = convlit(r, t)
   375  	return l, r
   376  }
   377  
   378  func mixUntyped(t1, t2 *types.Type) *types.Type {
   379  	if t1 == t2 {
   380  		return t1
   381  	}
   382  
   383  	rank := func(t *types.Type) int {
   384  		switch t {
   385  		case types.UntypedInt:
   386  			return 0
   387  		case types.UntypedRune:
   388  			return 1
   389  		case types.UntypedFloat:
   390  			return 2
   391  		case types.UntypedComplex:
   392  			return 3
   393  		}
   394  		base.Fatalf("bad type %v", t)
   395  		panic("unreachable")
   396  	}
   397  
   398  	if rank(t2) > rank(t1) {
   399  		return t2
   400  	}
   401  	return t1
   402  }
   403  
   404  func defaultType(t *types.Type) *types.Type {
   405  	if !t.IsUntyped() || t.Kind() == types.TNIL {
   406  		return t
   407  	}
   408  
   409  	switch t {
   410  	case types.UntypedBool:
   411  		return types.Types[types.TBOOL]
   412  	case types.UntypedString:
   413  		return types.Types[types.TSTRING]
   414  	case types.UntypedInt:
   415  		return types.Types[types.TINT]
   416  	case types.UntypedRune:
   417  		return types.RuneType
   418  	case types.UntypedFloat:
   419  		return types.Types[types.TFLOAT64]
   420  	case types.UntypedComplex:
   421  		return types.Types[types.TCOMPLEX128]
   422  	}
   423  
   424  	base.Fatalf("bad type %v", t)
   425  	return nil
   426  }
   427  
   428  // IndexConst returns the index value of constant Node n.
   429  func IndexConst(n ir.Node) int64 {
   430  	return ir.IntVal(types.Types[types.TINT], toint(n.Val()))
   431  }
   432  
   433  // callOrChan reports whether n is a call or channel operation.
   434  func callOrChan(n ir.Node) bool {
   435  	switch n.Op() {
   436  	case ir.OAPPEND,
   437  		ir.OCALL,
   438  		ir.OCALLFUNC,
   439  		ir.OCALLINTER,
   440  		ir.OCALLMETH,
   441  		ir.OCAP,
   442  		ir.OCLEAR,
   443  		ir.OCLOSE,
   444  		ir.OCOMPLEX,
   445  		ir.OCOPY,
   446  		ir.ODELETE,
   447  		ir.OIMAG,
   448  		ir.OLEN,
   449  		ir.OMAKE,
   450  		ir.OMAX,
   451  		ir.OMIN,
   452  		ir.ONEW,
   453  		ir.OPANIC,
   454  		ir.OPRINT,
   455  		ir.OPRINTLN,
   456  		ir.OREAL,
   457  		ir.ORECOVER,
   458  		ir.ORECOVERFP,
   459  		ir.ORECV,
   460  		ir.OUNSAFEADD,
   461  		ir.OUNSAFESLICE,
   462  		ir.OUNSAFESLICEDATA,
   463  		ir.OUNSAFESTRING,
   464  		ir.OUNSAFESTRINGDATA:
   465  		return true
   466  	}
   467  	return false
   468  }
   469  

View as plain text