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

View as plain text