Help us shape the future of Go! Take the 2026 Go Developer Survey

Source file src/cmd/compile/internal/types2/literals.go

     1  // Copyright 2024 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  // This file implements typechecking of literals.
     6  
     7  package types2
     8  
     9  import (
    10  	"cmd/compile/internal/syntax"
    11  	"go/constant"
    12  	. "internal/types/errors"
    13  	"strings"
    14  )
    15  
    16  // langCompat reports an error if the representation of a numeric
    17  // literal is not compatible with the current language version.
    18  func (check *Checker) langCompat(lit *syntax.BasicLit) {
    19  	s := lit.Value
    20  	if len(s) <= 2 || check.allowVersion(go1_13) {
    21  		return
    22  	}
    23  	// len(s) > 2
    24  	if strings.Contains(s, "_") {
    25  		check.versionErrorf(lit, go1_13, "underscore in numeric literal")
    26  		return
    27  	}
    28  	if s[0] != '0' {
    29  		return
    30  	}
    31  	radix := s[1]
    32  	if radix == 'b' || radix == 'B' {
    33  		check.versionErrorf(lit, go1_13, "binary literal")
    34  		return
    35  	}
    36  	if radix == 'o' || radix == 'O' {
    37  		check.versionErrorf(lit, go1_13, "0o/0O-style octal literal")
    38  		return
    39  	}
    40  	if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
    41  		check.versionErrorf(lit, go1_13, "hexadecimal floating-point literal")
    42  	}
    43  }
    44  
    45  func (check *Checker) basicLit(x *operand, e *syntax.BasicLit) {
    46  	switch e.Kind {
    47  	case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
    48  		check.langCompat(e)
    49  		// The max. mantissa precision for untyped numeric values
    50  		// is 512 bits, or 4048 bits for each of the two integer
    51  		// parts of a fraction for floating-point numbers that are
    52  		// represented accurately in the go/constant package.
    53  		// Constant literals that are longer than this many bits
    54  		// are not meaningful; and excessively long constants may
    55  		// consume a lot of space and time for a useless conversion.
    56  		// Cap constant length with a generous upper limit that also
    57  		// allows for separators between all digits.
    58  		const limit = 10000
    59  		if len(e.Value) > limit {
    60  			check.errorf(e, InvalidConstVal, "excessively long constant: %s... (%d chars)", e.Value[:10], len(e.Value))
    61  			x.invalidate()
    62  			return
    63  		}
    64  	}
    65  	x.setConst(e.Kind, e.Value)
    66  	if !x.isValid() {
    67  		// The parser already establishes syntactic correctness.
    68  		// If we reach here it's because of number under-/overflow.
    69  		// TODO(gri) setConst (and in turn the go/constant package)
    70  		// should return an error describing the issue.
    71  		check.errorf(e, InvalidConstVal, "malformed constant: %s", e.Value)
    72  		x.invalidate()
    73  		return
    74  	}
    75  	// Ensure that integer values don't overflow (go.dev/issue/54280).
    76  	x.expr = e // make sure that check.overflow below has an error position
    77  	check.overflow(x, opPos(x.expr))
    78  }
    79  
    80  func (check *Checker) funcLit(x *operand, e *syntax.FuncLit) {
    81  	if sig, ok := check.typ(e.Type).(*Signature); ok {
    82  		// Set the Scope's extent to the complete "func (...) {...}"
    83  		// so that Scope.Innermost works correctly.
    84  		sig.scope.pos = e.Pos()
    85  		sig.scope.end = endPos(e)
    86  		if !check.conf.IgnoreFuncBodies && e.Body != nil {
    87  			// Anonymous functions are considered part of the
    88  			// init expression/func declaration which contains
    89  			// them: use existing package-level declaration info.
    90  			decl := check.decl // capture for use in closure below
    91  			iota := check.iota // capture for use in closure below (go.dev/issue/22345)
    92  			// Don't type-check right away because the function may
    93  			// be part of a type definition to which the function
    94  			// body refers. Instead, type-check as soon as possible,
    95  			// but before the enclosing scope contents changes (go.dev/issue/22992).
    96  			check.later(func() {
    97  				check.funcBody(decl, "<function literal>", sig, e.Body, iota)
    98  			}).describef(e, "func literal")
    99  		}
   100  		x.mode_ = value
   101  		x.typ_ = sig
   102  	} else {
   103  		check.errorf(e, InvalidSyntaxTree, "invalid function literal %v", e)
   104  		x.invalidate()
   105  	}
   106  }
   107  
   108  func (check *Checker) compositeLit(T *target, x *operand, e *syntax.CompositeLit) {
   109  	var typ, base Type
   110  	var isElem bool // true if composite literal is an untyped element of an enclosing composite literal
   111  
   112  	switch {
   113  	case e.Type != nil:
   114  		// composite literal type present - use it
   115  		// [...]T array types may only appear with composite literals.
   116  		// Check for them here so we don't have to handle ... in general.
   117  		if atyp, _ := e.Type.(*syntax.ArrayType); atyp != nil && isdddArray(atyp) {
   118  			// We have an "open" [...]T array type.
   119  			// Create a new ArrayType with unknown length (-1)
   120  			// and finish setting it up after analyzing the literal.
   121  			typ = &Array{len: -1, elem: check.varType(atyp.Elem)}
   122  		} else {
   123  			typ = check.typ(e.Type)
   124  		}
   125  		base = typ
   126  
   127  	case T != nil:
   128  		// no composite literal type present - use assignment context
   129  		assert(T.typ != nil)
   130  		// report a version error only if we have an inferred type that is not a hint
   131  		_ = T.hint || check.verifyVersionf(e, go1_28, "missing type in composite literal")
   132  		typ = T.typ
   133  		base = typ
   134  		// *T implies &T{}
   135  		u, _ := commonUnder(base, nil)
   136  		if b, ok := deref(u); ok {
   137  			base = b
   138  		}
   139  		isElem = T.hint
   140  
   141  	default:
   142  		// no composite literal type present
   143  		// TODO(gri) provide better error messages depending on context
   144  		check.error(e, UntypedLit, "missing type in composite literal")
   145  		// continue with invalid type so that elements are "used" (go.dev/issue/69092)
   146  		typ = Typ[Invalid]
   147  		base = typ
   148  	}
   149  
   150  	// We cannot create a literal of an incomplete type; make sure it's complete.
   151  	if !check.isComplete(base) {
   152  		x.invalidate()
   153  		return
   154  	}
   155  
   156  	switch u, _ := commonUnder(base, nil); utyp := u.(type) {
   157  	case *Struct:
   158  		if len(e.ElemList) == 0 {
   159  			break
   160  		}
   161  		// Convention for error messages on invalid struct literals:
   162  		// we mention the struct type only if it clarifies the error
   163  		// (e.g., a duplicate field error doesn't need the struct type).
   164  		fields := utyp.fields
   165  		if _, ok := e.ElemList[0].(*syntax.KeyValueExpr); ok {
   166  			// all elements must have keys
   167  			visited := make(trie[*Var])
   168  			for _, e := range e.ElemList {
   169  				kv, _ := e.(*syntax.KeyValueExpr)
   170  				if kv == nil {
   171  					check.error(e, MixedStructLit, "mixture of field:value and value elements in struct literal")
   172  					continue
   173  				}
   174  				key, _ := kv.Key.(*syntax.Name)
   175  				// do all possible checks early (before exiting due to errors)
   176  				// so we don't drop information on the floor
   177  				if key == nil {
   178  					check.genericExpr(nil, x, kv.Value)
   179  					check.errorf(kv, InvalidLitField, "invalid field name %s in struct literal", kv.Key)
   180  					continue
   181  				}
   182  				obj, index, indirect := lookupFieldOrMethod(utyp, false, check.pkg, key.Value, false)
   183  				if obj == nil {
   184  					check.genericExpr(nil, x, kv.Value)
   185  					alt, _, _ := lookupFieldOrMethod(utyp, false, check.pkg, key.Value, true)
   186  					msg := check.lookupError(base, key.Value, alt, true)
   187  					check.error(kv.Key, MissingLitField, msg)
   188  					continue
   189  				}
   190  				fld, _ := obj.(*Var)
   191  				if fld == nil {
   192  					check.genericExpr(nil, x, kv.Value)
   193  					check.errorf(kv.Key, MissingLitField, "%s is not a field", kv.Key)
   194  					continue
   195  				}
   196  				// we can now check the value using the field target type
   197  				etyp := fld.typ
   198  				check.genericExpr(newTarget(etyp, "struct field"), x, kv.Value)
   199  				if len(index) > 1 && !check.verifyVersionf(kv.Key, go1_27, "use of promoted field %s in struct literal of type %s", fieldPath(utyp, index), base) {
   200  					continue
   201  				}
   202  				if indirect {
   203  					check.errorf(kv.Key, InvalidLitField, "invalid implicit pointer indirection to reach %s", kv.Key)
   204  					continue
   205  				}
   206  				check.recordUse(key, fld)
   207  				check.assignment(x, etyp, "struct literal")
   208  				if alt, n := visited.insert(index, fld); n != 0 {
   209  					if fld == alt {
   210  						check.errorf(kv, DuplicateLitField, "duplicate field name %s in struct literal", fld.name)
   211  					} else if n < len(index) {
   212  						check.errorf(kv, DuplicateLitField, "cannot specify promoted field %s and enclosing embedded field %s", fld.name, alt.name)
   213  					} else { // n > len(index)
   214  						check.errorf(kv, DuplicateLitField, "cannot specify embedded field %s and enclosed promoted field %s", fld.name, alt.name)
   215  					}
   216  				}
   217  			}
   218  		} else {
   219  			// no element must have a key
   220  			for i, e := range e.ElemList {
   221  				if kv, _ := e.(*syntax.KeyValueExpr); kv != nil {
   222  					check.error(kv, MixedStructLit, "mixture of field:value and value elements in struct literal")
   223  					continue
   224  				}
   225  				if i >= len(fields) {
   226  					check.genericExpr(nil, x, e)
   227  					check.errorf(x, InvalidStructLit, "too many values in struct literal of type %s", base)
   228  					break // cannot continue
   229  				}
   230  				// i < len(fields)
   231  				fld := fields[i]
   232  				etyp := fld.typ
   233  				check.genericExpr(newTarget(etyp, "struct field"), x, e)
   234  				if !fld.Exported() && fld.pkg != check.pkg {
   235  					check.errorf(x, UnexportedLitField, "implicit assignment to unexported field %s in struct literal of type %s", fld.name, base)
   236  					continue
   237  				}
   238  				check.assignment(x, etyp, "struct literal")
   239  			}
   240  			if len(e.ElemList) < len(fields) {
   241  				var hint string
   242  				for _, fld := range fields {
   243  					if !fld.Exported() && fld.pkg != check.pkg {
   244  						hint = " (type has unexported fields - use key:value pairs)"
   245  						break
   246  					}
   247  				}
   248  				check.errorf(inNode(e, e.Rbrace), InvalidStructLit, "too few values in struct literal of type %s%s", base, hint)
   249  				// ok to continue
   250  			}
   251  		}
   252  
   253  	case *Array:
   254  		n := check.indexedElts(e.ElemList, utyp.elem, utyp.len)
   255  		// If we have an array of unknown length (usually [...]T arrays, but also
   256  		// arrays [n]T where n is invalid) set the length now that we know it and
   257  		// record the type for the array (usually done by check.typ which is not
   258  		// called for [...]T). We handle [...]T arrays and arrays with invalid
   259  		// length the same here because it makes sense to "guess" the length for
   260  		// the latter if we have a composite literal; e.g. for [n]int{1, 2, 3}
   261  		// where n is invalid for some reason, it seems fair to assume it should
   262  		// be 3 (see also Checked.arrayLength and go.dev/issue/27346).
   263  		if utyp.len < 0 {
   264  			utyp.len = n
   265  			// e.Type is missing if we have a composite literal element
   266  			// that is itself a composite literal with omitted type. In
   267  			// that case there is nothing to record (there is no type in
   268  			// the source at that point).
   269  			if e.Type != nil {
   270  				check.recordTypeAndValue(e.Type, typexpr, utyp, nil)
   271  			}
   272  		}
   273  
   274  	case *Slice:
   275  		check.indexedElts(e.ElemList, utyp.elem, -1)
   276  
   277  	case *Map:
   278  		// If the map key type is an interface (but not a type parameter),
   279  		// the type of a constant key must be considered when checking for
   280  		// duplicates.
   281  		keyIsInterface := isNonTypeParamInterface(utyp.key)
   282  		visited := make(map[any][]Type, len(e.ElemList))
   283  		for _, e := range e.ElemList {
   284  			kv, _ := e.(*syntax.KeyValueExpr)
   285  			if kv == nil {
   286  				check.error(e, MissingLitKey, "missing key in map literal")
   287  				continue
   288  			}
   289  			check.genericExpr(newHint(utyp.key, "map key"), x, kv.Key)
   290  			check.assignment(x, utyp.key, "map literal")
   291  			if !x.isValid() {
   292  				continue
   293  			}
   294  			if x.mode() == constant_ {
   295  				duplicate := false
   296  				xkey := keyVal(x.val)
   297  				if keyIsInterface {
   298  					for _, vtyp := range visited[xkey] {
   299  						if Identical(vtyp, x.typ()) {
   300  							duplicate = true
   301  							break
   302  						}
   303  					}
   304  					visited[xkey] = append(visited[xkey], x.typ())
   305  				} else {
   306  					_, duplicate = visited[xkey]
   307  					visited[xkey] = nil
   308  				}
   309  				if duplicate {
   310  					check.errorf(x, DuplicateLitKey, "duplicate key %s in map literal", x.val)
   311  					continue
   312  				}
   313  			}
   314  			check.genericExpr(newHint(utyp.elem, "map value"), x, kv.Value)
   315  			check.assignment(x, utyp.elem, "map literal")
   316  		}
   317  
   318  	default:
   319  		// when "using" all elements unpack KeyValueExpr
   320  		// explicitly because check.use doesn't accept them
   321  		for _, e := range e.ElemList {
   322  			if kv, _ := e.(*syntax.KeyValueExpr); kv != nil {
   323  				// Ideally, we should also "use" kv.Key but we can't know
   324  				// if it's an externally defined struct key or not. Going
   325  				// forward anyway can lead to other errors. Give up instead.
   326  				e = kv.Value
   327  			}
   328  			check.use(e)
   329  		}
   330  		// if utyp is invalid, an error was reported before
   331  		if isValid(utyp) {
   332  			var qualifier string
   333  			if isElem {
   334  				qualifier = " element"
   335  			}
   336  			var cause string
   337  			if utyp == nil {
   338  				cause = " (no common underlying type)"
   339  			}
   340  			check.errorf(e, InvalidLit, "invalid composite literal%s type %s%s", qualifier, typ, cause)
   341  			x.invalidate()
   342  			return
   343  		}
   344  	}
   345  
   346  	x.mode_ = value
   347  	x.typ_ = typ
   348  }
   349  
   350  // indexedElts checks the elements (elts) of an array or slice composite literal
   351  // against the literal's element type (typ), and the element indices against
   352  // the literal length if known (length >= 0). It returns the length of the
   353  // literal (maximum index value + 1).
   354  func (check *Checker) indexedElts(elts []syntax.Expr, typ Type, length int64) int64 {
   355  	visited := make(map[int64]bool, len(elts))
   356  	var index, max int64
   357  	for _, e := range elts {
   358  		// determine and check index
   359  		validIndex := false
   360  		eval := e
   361  		if kv, _ := e.(*syntax.KeyValueExpr); kv != nil {
   362  			if typ, i := check.index(kv.Key, length); isValid(typ) {
   363  				if i >= 0 {
   364  					index = i
   365  					validIndex = true
   366  				} else {
   367  					check.errorf(e, InvalidLitIndex, "index %s must be integer constant", kv.Key)
   368  				}
   369  			}
   370  			eval = kv.Value
   371  		} else if length >= 0 && index >= length {
   372  			check.errorf(e, OversizeArrayLit, "index %d is out of bounds (>= %d)", index, length)
   373  		} else {
   374  			validIndex = true
   375  		}
   376  
   377  		// if we have a valid index, check for duplicate entries
   378  		if validIndex {
   379  			if visited[index] {
   380  				check.errorf(e, DuplicateLitKey, "duplicate index %d in array or slice literal", index)
   381  			}
   382  			visited[index] = true
   383  		}
   384  		index++
   385  		if index > max {
   386  			max = index
   387  		}
   388  
   389  		// check element against composite literal element type
   390  		var x operand
   391  		check.genericExpr(newHint(typ, "array or slice element"), &x, eval)
   392  		check.assignment(&x, typ, "array or slice literal")
   393  	}
   394  	return max
   395  }
   396  
   397  // keyVal maps a complex, float, integer, string or boolean constant value
   398  // to the corresponding complex128, float64, int64, uint64, string, or bool
   399  // Go value if possible; otherwise it returns x.
   400  // A complex constant that can be represented as a float (such as 1.2 + 0i)
   401  // is returned as a floating point value; if a floating point value can be
   402  // represented as an integer (such as 1.0) it is returned as an integer value.
   403  // This ensures that constants of different kind but equal value (such as
   404  // 1.0 + 0i, 1.0, 1) result in the same value.
   405  func keyVal(x constant.Value) any {
   406  	switch x.Kind() {
   407  	case constant.Complex:
   408  		f := constant.ToFloat(x)
   409  		if f.Kind() != constant.Float {
   410  			r, _ := constant.Float64Val(constant.Real(x))
   411  			i, _ := constant.Float64Val(constant.Imag(x))
   412  			return complex(r, i)
   413  		}
   414  		x = f
   415  		fallthrough
   416  	case constant.Float:
   417  		i := constant.ToInt(x)
   418  		if i.Kind() != constant.Int {
   419  			v, _ := constant.Float64Val(x)
   420  			return v
   421  		}
   422  		x = i
   423  		fallthrough
   424  	case constant.Int:
   425  		if v, ok := constant.Int64Val(x); ok {
   426  			return v
   427  		}
   428  		if v, ok := constant.Uint64Val(x); ok {
   429  			return v
   430  		}
   431  	case constant.String:
   432  		return constant.StringVal(x)
   433  	case constant.Bool:
   434  		return constant.BoolVal(x)
   435  	}
   436  	return x
   437  }
   438  

View as plain text