mirror of https://github.com/golang/go.git
go/types, types2: reduce differences between go/types and types2 builtins.go
Change-Id: I2946e061c70d31df3ba2aa3582700c3785b647e0 Reviewed-on: https://go-review.googlesource.com/c/go/+/495615 Reviewed-by: Robert Findley <rfindley@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@google.com> Auto-Submit: Robert Griesemer <gri@google.com> Run-TryBot: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
8e3dfe783a
commit
44b8f3907c
|
|
@ -18,12 +18,16 @@ import (
|
|||
// but x.expr is not set. If the call is invalid, the result is
|
||||
// false, and *x is undefined.
|
||||
func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (_ bool) {
|
||||
argList := call.ArgList
|
||||
|
||||
// append is the only built-in that permits the use of ... for the last argument
|
||||
bin := predeclaredFuncs[id]
|
||||
if call.HasDots && id != _Append {
|
||||
//check.errorf(call.Ellipsis, invalidOp + "invalid use of ... with built-in %s", bin.name)
|
||||
check.errorf(call, InvalidDotDotDot, invalidOp+"invalid use of ... with built-in %s", bin.name)
|
||||
check.use(call.ArgList...)
|
||||
check.errorf(call,
|
||||
InvalidDotDotDot,
|
||||
invalidOp+"invalid use of ... with built-in %s", bin.name)
|
||||
check.use(argList...)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -47,7 +51,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
switch id {
|
||||
default:
|
||||
// check all arguments
|
||||
args = check.exprList(call.ArgList)
|
||||
args = check.exprList(argList)
|
||||
nargs = len(args)
|
||||
for _, a := range args {
|
||||
if a.mode == invalid {
|
||||
|
|
@ -60,7 +64,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
}
|
||||
case _Make, _New, _Offsetof, _Trace:
|
||||
// arguments require special handling
|
||||
nargs = len(call.ArgList)
|
||||
nargs = len(argList)
|
||||
}
|
||||
|
||||
// check argument count
|
||||
|
|
@ -486,7 +490,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
// make(T, n)
|
||||
// make(T, n, m)
|
||||
// (no argument evaluated yet)
|
||||
arg0 := call.ArgList[0]
|
||||
arg0 := argList[0]
|
||||
T := check.varType(arg0)
|
||||
if T == Typ[Invalid] {
|
||||
return
|
||||
|
|
@ -512,7 +516,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
|
||||
types := []Type{T}
|
||||
var sizes []int64 // constant integer arguments, if any
|
||||
for _, arg := range call.ArgList[1:] {
|
||||
for _, arg := range argList[1:] {
|
||||
typ, size := check.index(arg, -1) // ok to continue with typ == Typ[Invalid]
|
||||
types = append(types, typ)
|
||||
if size >= 0 {
|
||||
|
|
@ -520,7 +524,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
}
|
||||
}
|
||||
if len(sizes) == 2 && sizes[0] > sizes[1] {
|
||||
check.error(call.ArgList[1], SwappedMakeArgs, invalidArg+"length and capacity swapped")
|
||||
check.error(argList[1], SwappedMakeArgs, invalidArg+"length and capacity swapped")
|
||||
// safe to continue
|
||||
}
|
||||
x.mode = value
|
||||
|
|
@ -532,7 +536,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
case _New:
|
||||
// new(T)
|
||||
// (no argument evaluated yet)
|
||||
T := check.varType(call.ArgList[0])
|
||||
T := check.varType(argList[0])
|
||||
if T == Typ[Invalid] {
|
||||
return
|
||||
}
|
||||
|
|
@ -641,7 +645,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
case _Offsetof:
|
||||
// unsafe.Offsetof(x T) uintptr, where x must be a selector
|
||||
// (no argument evaluated yet)
|
||||
arg0 := call.ArgList[0]
|
||||
arg0 := argList[0]
|
||||
selx, _ := unparen(arg0).(*syntax.SelectorExpr)
|
||||
if selx == nil {
|
||||
check.errorf(arg0, BadOffsetofSyntax, invalidArg+"%s is not a selector expression", arg0)
|
||||
|
|
@ -842,7 +846,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
}
|
||||
var t operand
|
||||
x1 := x
|
||||
for _, arg := range call.ArgList {
|
||||
for _, arg := range argList {
|
||||
check.rawExpr(nil, x1, arg, nil, false) // permit trace for types, e.g.: new(trace(T))
|
||||
check.dump("%v: %s", atPos(x1), x1)
|
||||
x1 = &t // use incoming x only for first argument
|
||||
|
|
@ -921,8 +925,8 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x *operand, id builtinId)
|
|||
|
||||
// We can type-check this fine but we're introducing a synthetic
|
||||
// type parameter for the result. It's not clear what the API
|
||||
// implications are here. Report an error for 1.18 but continue
|
||||
// type-checking.
|
||||
// implications are here. Report an error for 1.18 (see go.dev/issue/50912),
|
||||
// but continue type-checking.
|
||||
var code Code
|
||||
switch id {
|
||||
case _Real:
|
||||
|
|
|
|||
|
|
@ -286,6 +286,10 @@ type Info struct {
|
|||
InitOrder []*Initializer
|
||||
}
|
||||
|
||||
func (info *Info) recordTypes() bool {
|
||||
return info.Types != nil
|
||||
}
|
||||
|
||||
// TypeOf returns the type of expression e, or nil if not found.
|
||||
// Precondition: the Types, Uses and Defs maps are populated.
|
||||
func (info *Info) TypeOf(e ast.Expr) Type {
|
||||
|
|
|
|||
|
|
@ -18,13 +18,15 @@ import (
|
|||
// but x.expr is not set. If the call is invalid, the result is
|
||||
// false, and *x is undefined.
|
||||
func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ bool) {
|
||||
argList := call.Args
|
||||
|
||||
// append is the only built-in that permits the use of ... for the last argument
|
||||
bin := predeclaredFuncs[id]
|
||||
if call.Ellipsis.IsValid() && id != _Append {
|
||||
check.errorf(atPos(call.Ellipsis),
|
||||
InvalidDotDotDot,
|
||||
invalidOp+"invalid use of ... with built-in %s", bin.name)
|
||||
check.use(call.Args...)
|
||||
check.use(argList...)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +50,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
switch id {
|
||||
default:
|
||||
// check all arguments
|
||||
args = check.exprList(call.Args)
|
||||
args = check.exprList(argList)
|
||||
nargs = len(args)
|
||||
for _, a := range args {
|
||||
if a.mode == invalid {
|
||||
|
|
@ -61,7 +63,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
}
|
||||
case _Make, _New, _Offsetof, _Trace:
|
||||
// arguments require special handling
|
||||
nargs = len(call.Args)
|
||||
nargs = len(argList)
|
||||
}
|
||||
|
||||
// check argument count
|
||||
|
|
@ -115,7 +117,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
if ok, _ := x.assignableTo(check, NewSlice(universeByte), nil); ok {
|
||||
y := args[1]
|
||||
if t := coreString(y.typ); t != nil && isString(t) {
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
sig := makeSig(S, S, y.typ)
|
||||
sig.variadic = true
|
||||
check.recordBuiltinType(call.Fun, sig)
|
||||
|
|
@ -135,7 +137,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
|
||||
x.mode = value
|
||||
x.typ = S
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, sig)
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +216,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
}
|
||||
|
||||
// record the signature before changing x.typ
|
||||
if check.Types != nil && mode != constant_ {
|
||||
if check.recordTypes() && mode != constant_ {
|
||||
check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ))
|
||||
}
|
||||
|
||||
|
|
@ -240,7 +242,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
}
|
||||
|
||||
x.mode = novalue
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(nil, x.typ))
|
||||
}
|
||||
|
||||
|
|
@ -261,7 +263,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
return
|
||||
}
|
||||
x.mode = novalue
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(nil, x.typ))
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +318,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
|
||||
// both argument types must be identical
|
||||
if !Identical(x.typ, y.typ) {
|
||||
check.errorf(x, InvalidComplex, invalidArg+"mismatched types %s and %s", x.typ, y.typ)
|
||||
check.errorf(x, InvalidComplex, invalidOp+"%v (mismatched types %s and %s)", call, x.typ, y.typ)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -349,7 +351,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
x.mode = value
|
||||
}
|
||||
|
||||
if check.Types != nil && x.mode != constant_ {
|
||||
if check.recordTypes() && x.mode != constant_ {
|
||||
check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ, x.typ))
|
||||
}
|
||||
|
||||
|
|
@ -372,11 +374,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
}
|
||||
|
||||
if !Identical(dst.elem, src.elem) {
|
||||
check.errorf(x, InvalidCopy, "arguments to copy %s and %s have different element types %s and %s", x, y, dst.elem, src.elem)
|
||||
check.errorf(x, InvalidCopy, invalidArg+"arguments to copy %s and %s have different element types %s and %s", x, y, dst.elem, src.elem)
|
||||
return
|
||||
}
|
||||
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(Typ[Int], x.typ, y.typ))
|
||||
}
|
||||
x.mode = value
|
||||
|
|
@ -411,7 +413,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
}
|
||||
|
||||
x.mode = novalue
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(nil, map_, key))
|
||||
}
|
||||
|
||||
|
|
@ -477,7 +479,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
x.mode = value
|
||||
}
|
||||
|
||||
if check.Types != nil && x.mode != constant_ {
|
||||
if check.recordTypes() && x.mode != constant_ {
|
||||
check.recordBuiltinType(call.Fun, makeSig(resTyp, x.typ))
|
||||
}
|
||||
|
||||
|
|
@ -487,7 +489,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
// make(T, n)
|
||||
// make(T, n, m)
|
||||
// (no argument evaluated yet)
|
||||
arg0 := call.Args[0]
|
||||
arg0 := argList[0]
|
||||
T := check.varType(arg0)
|
||||
if T == Typ[Invalid] {
|
||||
return
|
||||
|
|
@ -500,7 +502,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
case *Map, *Chan:
|
||||
min = 1
|
||||
case nil:
|
||||
check.errorf(arg0, InvalidMake, "cannot make %s: no core type", arg0)
|
||||
check.errorf(arg0, InvalidMake, invalidArg+"cannot make %s: no core type", arg0)
|
||||
return
|
||||
default:
|
||||
check.errorf(arg0, InvalidMake, invalidArg+"cannot make %s; type must be slice, map, or channel", arg0)
|
||||
|
|
@ -513,7 +515,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
|
||||
types := []Type{T}
|
||||
var sizes []int64 // constant integer arguments, if any
|
||||
for _, arg := range call.Args[1:] {
|
||||
for _, arg := range argList[1:] {
|
||||
typ, size := check.index(arg, -1) // ok to continue with typ == Typ[Invalid]
|
||||
types = append(types, typ)
|
||||
if size >= 0 {
|
||||
|
|
@ -521,26 +523,26 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
}
|
||||
}
|
||||
if len(sizes) == 2 && sizes[0] > sizes[1] {
|
||||
check.error(call.Args[1], SwappedMakeArgs, invalidArg+"length and capacity swapped")
|
||||
check.error(argList[1], SwappedMakeArgs, invalidArg+"length and capacity swapped")
|
||||
// safe to continue
|
||||
}
|
||||
x.mode = value
|
||||
x.typ = T
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(x.typ, types...))
|
||||
}
|
||||
|
||||
case _New:
|
||||
// new(T)
|
||||
// (no argument evaluated yet)
|
||||
T := check.varType(call.Args[0])
|
||||
T := check.varType(argList[0])
|
||||
if T == Typ[Invalid] {
|
||||
return
|
||||
}
|
||||
|
||||
x.mode = value
|
||||
x.typ = &Pointer{base: T}
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(x.typ, T))
|
||||
}
|
||||
|
||||
|
|
@ -565,7 +567,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
}
|
||||
|
||||
x.mode = novalue
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(nil, &emptyInterface))
|
||||
}
|
||||
|
||||
|
|
@ -586,7 +588,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
}
|
||||
|
||||
x.mode = novalue
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(nil, params...))
|
||||
}
|
||||
|
||||
|
|
@ -594,7 +596,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
// recover() interface{}
|
||||
x.mode = value
|
||||
x.typ = &emptyInterface
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(x.typ))
|
||||
}
|
||||
|
||||
|
|
@ -616,7 +618,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
|
||||
x.mode = value
|
||||
x.typ = Typ[UnsafePointer]
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(x.typ, x.typ, y.typ))
|
||||
}
|
||||
|
||||
|
|
@ -629,7 +631,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
|
||||
if hasVarSize(x.typ, nil) {
|
||||
x.mode = value
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ))
|
||||
}
|
||||
} else {
|
||||
|
|
@ -642,7 +644,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
case _Offsetof:
|
||||
// unsafe.Offsetof(x T) uintptr, where x must be a selector
|
||||
// (no argument evaluated yet)
|
||||
arg0 := call.Args[0]
|
||||
arg0 := argList[0]
|
||||
selx, _ := unparen(arg0).(*ast.SelectorExpr)
|
||||
if selx == nil {
|
||||
check.errorf(arg0, BadOffsetofSyntax, invalidArg+"%s is not a selector expression", arg0)
|
||||
|
|
@ -693,7 +695,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
// arranging struct fields if it wanted to.
|
||||
if hasVarSize(base, nil) {
|
||||
x.mode = value
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], obj.Type()))
|
||||
}
|
||||
} else {
|
||||
|
|
@ -717,7 +719,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
|
||||
if hasVarSize(x.typ, nil) {
|
||||
x.mode = value
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(Typ[Uintptr], x.typ))
|
||||
}
|
||||
} else {
|
||||
|
|
@ -751,7 +753,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
|
||||
x.mode = value
|
||||
x.typ = NewSlice(ptr.base)
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(x.typ, ptr, y.typ))
|
||||
}
|
||||
|
||||
|
|
@ -769,7 +771,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
|
||||
x.mode = value
|
||||
x.typ = NewPointer(slice.elem)
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(x.typ, slice))
|
||||
}
|
||||
|
||||
|
|
@ -791,7 +793,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
|
||||
x.mode = value
|
||||
x.typ = Typ[String]
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(x.typ, NewPointer(universeByte), y.typ))
|
||||
}
|
||||
|
||||
|
|
@ -808,7 +810,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
|
||||
x.mode = value
|
||||
x.typ = NewPointer(universeByte)
|
||||
if check.Types != nil {
|
||||
if check.recordTypes() {
|
||||
check.recordBuiltinType(call.Fun, makeSig(x.typ, Typ[String]))
|
||||
}
|
||||
|
||||
|
|
@ -843,7 +845,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
}
|
||||
var t operand
|
||||
x1 := x
|
||||
for _, arg := range call.Args {
|
||||
for _, arg := range argList {
|
||||
check.rawExpr(nil, x1, arg, nil, false) // permit trace for types, e.g.: new(trace(T))
|
||||
check.dump("%v: %s", x1.Pos(), x1)
|
||||
x1 = &t // use incoming x only for first argument
|
||||
|
|
|
|||
Loading…
Reference in New Issue