]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: factor type checking of basic literals and generate go/types code
authorRobert Griesemer <gri@golang.org>
Thu, 5 Sep 2024 01:06:50 +0000 (18:06 -0700)
committerGopher Robot <gobot@golang.org>
Thu, 5 Sep 2024 22:12:04 +0000 (22:12 +0000)
Move the code for type checking of basic literals into literals.go.

In go/types, the respective code is now generated from the types2 source.

Change-Id: Ib21eb7a87e11b77bcb2469985f9844964d35df57
Reviewed-on: https://go-review.googlesource.com/c/go/+/610540
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Tim King <taking@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>

src/cmd/compile/internal/types2/expr.go
src/cmd/compile/internal/types2/literals.go
src/go/types/expr.go
src/go/types/generate_test.go
src/go/types/literals.go

index a1e3012bcb5f9674b150c1d318b44aba726b3d82..18524dde23783451020e46fb1fb9c9da969f98d1 100644 (file)
@@ -12,7 +12,6 @@ import (
        "go/constant"
        "go/token"
        . "internal/types/errors"
-       "strings"
 )
 
 /*
@@ -1033,35 +1032,6 @@ func (check *Checker) nonGeneric(T *target, x *operand) {
        }
 }
 
-// langCompat reports an error if the representation of a numeric
-// literal is not compatible with the current language version.
-func (check *Checker) langCompat(lit *syntax.BasicLit) {
-       s := lit.Value
-       if len(s) <= 2 || check.allowVersion(lit, go1_13) {
-               return
-       }
-       // len(s) > 2
-       if strings.Contains(s, "_") {
-               check.versionErrorf(lit, go1_13, "underscore in numeric literal")
-               return
-       }
-       if s[0] != '0' {
-               return
-       }
-       radix := s[1]
-       if radix == 'b' || radix == 'B' {
-               check.versionErrorf(lit, go1_13, "binary literal")
-               return
-       }
-       if radix == 'o' || radix == 'O' {
-               check.versionErrorf(lit, go1_13, "0o/0O-style octal literal")
-               return
-       }
-       if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
-               check.versionErrorf(lit, go1_13, "hexadecimal floating-point literal")
-       }
-}
-
 // exprInternal contains the core of type checking of expressions.
 // Must only be called by rawExpr.
 // (See rawExpr for an explanation of the parameters.)
@@ -1091,36 +1061,10 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty
                if e.Bad {
                        goto Error // error reported during parsing
                }
-               switch e.Kind {
-               case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
-                       check.langCompat(e)
-                       // 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 limit = 10000
-                       if len(e.Value) > limit {
-                               check.errorf(e, InvalidConstVal, "excessively long constant: %s... (%d chars)", e.Value[:10], len(e.Value))
-                               goto Error
-                       }
-               }
-               x.setConst(e.Kind, e.Value)
+               check.basicLit(x, e)
                if x.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.
-                       check.errorf(e, InvalidConstVal, "malformed constant: %s", e.Value)
                        goto Error
                }
-               // Ensure that integer values don't overflow (go.dev/issue/54280).
-               x.expr = e // make sure that check.overflow below has an error position
-               check.overflow(x, opPos(x.expr))
 
        case *syntax.FuncLit:
                check.funcLit(x, e)
index 188c92077690370ca4ad872ee3bc8ba5be5b723d..1b47015ae20590f73cf96c473f69ddf50ae98a87 100644 (file)
@@ -2,15 +2,80 @@
 // 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 composite literals.
+// This file implements typechecking of literals.
 
 package types2
 
 import (
        "cmd/compile/internal/syntax"
        . "internal/types/errors"
+       "strings"
 )
 
+// langCompat reports an error if the representation of a numeric
+// literal is not compatible with the current language version.
+func (check *Checker) langCompat(lit *syntax.BasicLit) {
+       s := lit.Value
+       if len(s) <= 2 || check.allowVersion(lit, go1_13) {
+               return
+       }
+       // len(s) > 2
+       if strings.Contains(s, "_") {
+               check.versionErrorf(lit, go1_13, "underscore in numeric literal")
+               return
+       }
+       if s[0] != '0' {
+               return
+       }
+       radix := s[1]
+       if radix == 'b' || radix == 'B' {
+               check.versionErrorf(lit, go1_13, "binary literal")
+               return
+       }
+       if radix == 'o' || radix == 'O' {
+               check.versionErrorf(lit, go1_13, "0o/0O-style octal literal")
+               return
+       }
+       if lit.Kind != syntax.IntLit && (radix == 'x' || radix == 'X') {
+               check.versionErrorf(lit, go1_13, "hexadecimal floating-point literal")
+       }
+}
+
+func (check *Checker) basicLit(x *operand, e *syntax.BasicLit) {
+       switch e.Kind {
+       case syntax.IntLit, syntax.FloatLit, syntax.ImagLit:
+               check.langCompat(e)
+               // 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 limit = 10000
+               if len(e.Value) > limit {
+                       check.errorf(e, InvalidConstVal, "excessively long constant: %s... (%d chars)", e.Value[:10], len(e.Value))
+                       x.mode = invalid
+                       return
+               }
+       }
+       x.setConst(e.Kind, e.Value)
+       if x.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.
+               check.errorf(e, InvalidConstVal, "malformed constant: %s", e.Value)
+               x.mode = invalid
+               return
+       }
+       // Ensure that integer values don't overflow (go.dev/issue/54280).
+       x.expr = e // make sure that check.overflow below has an error position
+       check.overflow(x, opPos(x.expr))
+}
+
 func (check *Checker) funcLit(x *operand, e *syntax.FuncLit) {
        if sig, ok := check.typ(e.Type).(*Signature); ok {
                // Set the Scope's extent to the complete "func (...) {...}"
index f74226345543e6bd8e8a97b2b8838707f0f5863b..eb97c894363dabe5dbd4bad2eb5358798660924a 100644 (file)
@@ -13,7 +13,6 @@ import (
        "go/internal/typeparams"
        "go/token"
        . "internal/types/errors"
-       "strings"
 )
 
 /*
@@ -1027,35 +1026,6 @@ func (check *Checker) nonGeneric(T *target, x *operand) {
        }
 }
 
-// langCompat reports an error if the representation of a numeric
-// literal is not compatible with the current language version.
-func (check *Checker) langCompat(lit *ast.BasicLit) {
-       s := lit.Value
-       if len(s) <= 2 || check.allowVersion(lit, go1_13) {
-               return
-       }
-       // len(s) > 2
-       if strings.Contains(s, "_") {
-               check.versionErrorf(lit, go1_13, "underscore in numeric literal")
-               return
-       }
-       if s[0] != '0' {
-               return
-       }
-       radix := s[1]
-       if radix == 'b' || radix == 'B' {
-               check.versionErrorf(lit, go1_13, "binary literal")
-               return
-       }
-       if radix == 'o' || radix == 'O' {
-               check.versionErrorf(lit, go1_13, "0o/0O-style octal literal")
-               return
-       }
-       if lit.Kind != token.INT && (radix == 'x' || radix == 'X') {
-               check.versionErrorf(lit, go1_13, "hexadecimal floating-point literal")
-       }
-}
-
 // exprInternal contains the core of type checking of expressions.
 // Must only be called by rawExpr.
 // (See rawExpr for an explanation of the parameters.)
@@ -1079,36 +1049,10 @@ func (check *Checker) exprInternal(T *target, x *operand, e ast.Expr, hint Type)
                goto Error
 
        case *ast.BasicLit:
-               switch e.Kind {
-               case token.INT, token.FLOAT, token.IMAG:
-                       check.langCompat(e)
-                       // 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 limit = 10000
-                       if len(e.Value) > limit {
-                               check.errorf(e, InvalidConstVal, "excessively long constant: %s... (%d chars)", e.Value[:10], len(e.Value))
-                               goto Error
-                       }
-               }
-               x.setConst(e.Kind, e.Value)
+               check.basicLit(x, e)
                if x.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.
-                       check.errorf(e, InvalidConstVal, "malformed constant: %s", e.Value)
                        goto Error
                }
-               // Ensure that integer values don't overflow (go.dev/issue/54280).
-               x.expr = e // make sure that check.overflow below has an error position
-               check.overflow(x, opPos(x.expr))
 
        case *ast.FuncLit:
                check.funcLit(x, e)
index 1422d1ae7c5e931529ccf1fb1955b86091e5c42a..62e17a957a5c84de0b19fb90189a5d185f973bb2 100644 (file)
@@ -137,8 +137,11 @@ var filemap = map[string]action{
        "instantiate.go":      func(f *ast.File) { fixTokenPos(f); fixCheckErrorfCall(f) },
        "instantiate_test.go": func(f *ast.File) { renameImportPath(f, `"cmd/compile/internal/types2"->"go/types"`) },
        "literals.go": func(f *ast.File) {
+               insertImportPath(f, `"go/token"`)
                renameImportPath(f, `"cmd/compile/internal/syntax"->"go/ast"`)
-               renameSelectorExprs(f, "syntax.Name->ast.Ident", "key.Value->key.Name", "atyp.Elem->atyp.Elt") // must happen before renaming identifiers
+               renameSelectorExprs(f,
+                       "syntax.IntLit->token.INT", "syntax.FloatLit->token.FLOAT", "syntax.ImagLit->token.IMAG",
+                       "syntax.Name->ast.Ident", "key.Value->key.Name", "atyp.Elem->atyp.Elt") // must happen before renaming identifiers
                renameIdents(f, "syntax->ast")
                renameSelectors(f, "ElemList->Elts")
        },
index 5efb0360adbf09ced1d892bd61d79890ff9b26d0..0945eed1538c3420a19b6167ab713a2a88d7a966 100644 (file)
@@ -5,15 +5,81 @@
 // 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 composite literals.
+// This file implements typechecking of literals.
 
 package types
 
 import (
        "go/ast"
+       "go/token"
        . "internal/types/errors"
+       "strings"
 )
 
+// langCompat reports an error if the representation of a numeric
+// literal is not compatible with the current language version.
+func (check *Checker) langCompat(lit *ast.BasicLit) {
+       s := lit.Value
+       if len(s) <= 2 || check.allowVersion(lit, go1_13) {
+               return
+       }
+       // len(s) > 2
+       if strings.Contains(s, "_") {
+               check.versionErrorf(lit, go1_13, "underscore in numeric literal")
+               return
+       }
+       if s[0] != '0' {
+               return
+       }
+       radix := s[1]
+       if radix == 'b' || radix == 'B' {
+               check.versionErrorf(lit, go1_13, "binary literal")
+               return
+       }
+       if radix == 'o' || radix == 'O' {
+               check.versionErrorf(lit, go1_13, "0o/0O-style octal literal")
+               return
+       }
+       if lit.Kind != token.INT && (radix == 'x' || radix == 'X') {
+               check.versionErrorf(lit, go1_13, "hexadecimal floating-point literal")
+       }
+}
+
+func (check *Checker) basicLit(x *operand, e *ast.BasicLit) {
+       switch e.Kind {
+       case token.INT, token.FLOAT, token.IMAG:
+               check.langCompat(e)
+               // 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 limit = 10000
+               if len(e.Value) > limit {
+                       check.errorf(e, InvalidConstVal, "excessively long constant: %s... (%d chars)", e.Value[:10], len(e.Value))
+                       x.mode = invalid
+                       return
+               }
+       }
+       x.setConst(e.Kind, e.Value)
+       if x.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.
+               check.errorf(e, InvalidConstVal, "malformed constant: %s", e.Value)
+               x.mode = invalid
+               return
+       }
+       // Ensure that integer values don't overflow (go.dev/issue/54280).
+       x.expr = e // make sure that check.overflow below has an error position
+       check.overflow(x, opPos(x.expr))
+}
+
 func (check *Checker) funcLit(x *operand, e *ast.FuncLit) {
        if sig, ok := check.typ(e.Type).(*Signature); ok {
                // Set the Scope's extent to the complete "func (...) {...}"