// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.// Source: ../../cmd/compile/internal/types2/literals.go// Copyright 2024 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.// This file implements typechecking of literals.package typesimport (.)// langCompat reports an error if the representation of a numeric// literal is not compatible with the current language version.func ( *Checker) ( *ast.BasicLit) { := .Valueiflen() <= 2 || .allowVersion(go1_13) {return }// len(s) > 2ifstrings.Contains(, "_") { .versionErrorf(, go1_13, "underscore in numeric literal")return }if [0] != '0' {return } := [1]if == 'b' || == 'B' { .versionErrorf(, go1_13, "binary literal")return }if == 'o' || == 'O' { .versionErrorf(, go1_13, "0o/0O-style octal literal")return }if .Kind != token.INT && ( == 'x' || == 'X') { .versionErrorf(, go1_13, "hexadecimal floating-point literal") }}func ( *Checker) ( *operand, *ast.BasicLit) {switch .Kind {casetoken.INT, token.FLOAT, token.IMAG: .langCompat()// The max. mantissa precision for untyped numeric values // is 512 bits, or 4048 bits for each of the two integer // parts of a fraction for floating-point numbers that are // represented accurately in the go/constant package. // Constant literals that are longer than this many bits // are not meaningful; and excessively long constants may // consume a lot of space and time for a useless conversion. // Cap constant length with a generous upper limit that also // allows for separators between all digits.const = 10000iflen(.Value) > { .errorf(, InvalidConstVal, "excessively long constant: %s... (%d chars)", .Value[:10], len(.Value)) .mode = invalidreturn } } .setConst(.Kind, .Value)if .mode == invalid {// The parser already establishes syntactic correctness. // If we reach here it's because of number under-/overflow. // TODO(gri) setConst (and in turn the go/constant package) // should return an error describing the issue. .errorf(, InvalidConstVal, "malformed constant: %s", .Value) .mode = invalidreturn }// Ensure that integer values don't overflow (go.dev/issue/54280). .expr = // make sure that check.overflow below has an error position .overflow(, opPos(.expr))}func ( *Checker) ( *operand, *ast.FuncLit) {if , := .typ(.Type).(*Signature); {// Set the Scope's extent to the complete "func (...) {...}" // so that Scope.Innermost works correctly. .scope.pos = .Pos() .scope.end = endPos()if !.conf.IgnoreFuncBodies && .Body != nil {// Anonymous functions are considered part of the // init expression/func declaration which contains // them: use existing package-level declaration info. := .decl// capture for use in closure below := .iota// capture for use in closure below (go.dev/issue/22345)// Don't type-check right away because the function may // be part of a type definition to which the function // body refers. Instead, type-check as soon as possible, // but before the enclosing scope contents changes (go.dev/issue/22992). .later(func() { .funcBody(, "<function literal>", , .Body, ) }).describef(, "func literal") } .mode = value .typ = } else { .errorf(, InvalidSyntaxTree, "invalid function literal %v", ) .mode = invalid }}func ( *Checker) ( *operand, *ast.CompositeLit, Type) {var , Typevarbool// true if composite literal is an element of an enclosing composite literalswitch {case .Type != nil:// composite literal type present - use it // [...]T array types may only appear with composite literals. // Check for them here so we don't have to handle ... in general.if , := .Type.(*ast.ArrayType); != nil && isdddArray() {// We have an "open" [...]T array type. // Create a new ArrayType with unknown length (-1) // and finish setting it up after analyzing the literal. = &Array{len: -1, elem: .varType(.Elt)} = break } = .typ(.Type) = case != nil:// no composite literal type present - use hint (element type of enclosing type) = = // *T implies &T{}if , := deref(coreType()); { = } = truedefault:// TODO(gri) provide better error messages depending on context .error(, UntypedLit, "missing type in composite literal")// continue with invalid type so that elements are "used" (go.dev/issue/69092) = Typ[Invalid] = }switch utyp := coreType().(type) {case *Struct:// Prevent crash if the struct referred to is not yet set up. // See analogous comment for *Array.if .fields == nil { .error(, InvalidTypeCycle, "invalid recursive type") .mode = invalidreturn }iflen(.Elts) == 0 {break }// Convention for error messages on invalid struct literals: // we mention the struct type only if it clarifies the error // (e.g., a duplicate field error doesn't need the struct type). := .fieldsif , := .Elts[0].(*ast.KeyValueExpr); {// all elements must have keys := make([]bool, len())for , := range .Elts { , := .(*ast.KeyValueExpr)if == nil { .error(, MixedStructLit, "mixture of field:value and value elements in struct literal")continue } , := .Key.(*ast.Ident)// do all possible checks early (before exiting due to errors) // so we don't drop information on the floor .expr(nil, , .Value)if == nil { .errorf(, InvalidLitField, "invalid field name %s in struct literal", .Key)continue } := fieldIndex(, .pkg, .Name, false)if < 0 {varObjectif := fieldIndex(, .pkg, .Name, true); >= 0 { = [] } := .lookupError(, .Name, , true) .error(.Key, MissingLitField, )continue } := [] .recordUse(, ) := .typ .assignment(, , "struct literal")// 0 <= i < len(fields)if [] { .errorf(, DuplicateLitField, "duplicate field name %s in struct literal", .Name)continue } [] = true } } else {// no element must have a keyfor , := range .Elts {if , := .(*ast.KeyValueExpr); != nil { .error(, MixedStructLit, "mixture of field:value and value elements in struct literal")continue } .expr(nil, , )if >= len() { .errorf(, InvalidStructLit, "too many values in struct literal of type %s", )break// cannot continue }// i < len(fields) := []if !.Exported() && .pkg != .pkg { .errorf(, UnexportedLitField, "implicit assignment to unexported field %s in struct literal of type %s", .name, )continue } := .typ .assignment(, , "struct literal") }iflen(.Elts) < len() { .errorf(inNode(, .Rbrace), InvalidStructLit, "too few values in struct literal of type %s", )// ok to continue } }case *Array:// Prevent crash if the array referred to is not yet set up. Was go.dev/issue/18643. // This is a stop-gap solution. Should use Checker.objPath to report entire // path starting with earliest declaration in the source. TODO(gri) fix this.if .elem == nil { .error(, InvalidTypeCycle, "invalid recursive type") .mode = invalidreturn } := .indexedElts(.Elts, .elem, .len)// If we have an array of unknown length (usually [...]T arrays, but also // arrays [n]T where n is invalid) set the length now that we know it and // record the type for the array (usually done by check.typ which is not // called for [...]T). We handle [...]T arrays and arrays with invalid // length the same here because it makes sense to "guess" the length for // the latter if we have a composite literal; e.g. for [n]int{1, 2, 3} // where n is invalid for some reason, it seems fair to assume it should // be 3 (see also Checked.arrayLength and go.dev/issue/27346).if .len < 0 { .len = // e.Type is missing if we have a composite literal element // that is itself a composite literal with omitted type. In // that case there is nothing to record (there is no type in // the source at that point).if .Type != nil { .recordTypeAndValue(.Type, typexpr, , nil) } }case *Slice:// Prevent crash if the slice referred to is not yet set up. // See analogous comment for *Array.if .elem == nil { .error(, InvalidTypeCycle, "invalid recursive type") .mode = invalidreturn } .indexedElts(.Elts, .elem, -1)case *Map:// Prevent crash if the map referred to is not yet set up. // See analogous comment for *Array.if .key == nil || .elem == nil { .error(, InvalidTypeCycle, "invalid recursive type") .mode = invalidreturn }// If the map key type is an interface (but not a type parameter), // the type of a constant key must be considered when checking for // duplicates. := isNonTypeParamInterface(.key) := make(map[any][]Type, len(.Elts))for , := range .Elts { , := .(*ast.KeyValueExpr)if == nil { .error(, MissingLitKey, "missing key in map literal")continue } .exprWithHint(, .Key, .key) .assignment(, .key, "map literal")if .mode == invalid {continue }if .mode == constant_ { := false := keyVal(.val)if {for , := range [] {ifIdentical(, .typ) { = truebreak } } [] = append([], .typ) } else { _, = [] [] = nil }if { .errorf(, DuplicateLitKey, "duplicate key %s in map literal", .val)continue } } .exprWithHint(, .Value, .elem) .assignment(, .elem, "map literal") }default:// when "using" all elements unpack KeyValueExpr // explicitly because check.use doesn't accept themfor , := range .Elts {if , := .(*ast.KeyValueExpr); != nil {// Ideally, we should also "use" kv.Key but we can't know // if it's an externally defined struct key or not. Going // forward anyway can lead to other errors. Give up instead. = .Value } .use() }// if utyp is invalid, an error was reported beforeifisValid() {varstringif { = " element" }varstringif == nil { = " (no core type)" } .errorf(, InvalidLit, "invalid composite literal%s type %s%s", , , ) .mode = invalidreturn } } .mode = value .typ = }// indexedElts checks the elements (elts) of an array or slice composite literal// against the literal's element type (typ), and the element indices against// the literal length if known (length >= 0). It returns the length of the// literal (maximum index value + 1).func ( *Checker) ( []ast.Expr, Type, int64) int64 { := make(map[int64]bool, len())var , int64for , := range {// determine and check index := false := if , := .(*ast.KeyValueExpr); != nil {if , := .index(.Key, ); isValid() {if >= 0 { = = true } else { .errorf(, InvalidLitIndex, "index %s must be integer constant", .Key) } } = .Value } elseif >= 0 && >= { .errorf(, OversizeArrayLit, "index %d is out of bounds (>= %d)", , ) } else { = true }// if we have a valid index, check for duplicate entriesif {if [] { .errorf(, DuplicateLitKey, "duplicate index %d in array or slice literal", ) } [] = true } ++if > { = }// check element against composite literal element typevaroperand .exprWithHint(&, , ) .assignment(&, , "array or slice literal") }return}
The pages are generated with Goldsv0.7.3-preview. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.