1
0
mirror of https://github.com/golang/go synced 2024-11-25 09:57:57 -07:00

go/types, types2: factor type checking of basic literals and generate go/types code

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>
This commit is contained in:
Robert Griesemer 2024-09-04 18:06:50 -07:00 committed by Gopher Robot
parent 0f12e51ce7
commit 0fc3b127a0
5 changed files with 139 additions and 117 deletions

View 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)

View 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 (...) {...}"

View 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)

View 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")
},

View 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 (...) {...}"