mirror of
https://github.com/golang/go
synced 2024-11-25 12:17:56 -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:
parent
0f12e51ce7
commit
0fc3b127a0
@ -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)
|
||||
|
@ -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 (...) {...}"
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
},
|
||||
|
@ -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 (...) {...}"
|
||||
|
Loading…
Reference in New Issue
Block a user