mirror of
https://github.com/golang/go
synced 2024-11-19 00:44:40 -07:00
go.tools/go/types: only report constants with constant types
The issue is addressed with the change in conversions.go. Also: - added corresponding API test - made names for untyped ints, bools consistent with others - use *Basic with names byte/rune instead of uint8/int32 for better output - minor cleanups Fixes golang/go#6949. R=adonovan CC=golang-codereviews https://golang.org/cl/50520043
This commit is contained in:
parent
d2fe54b33c
commit
179e0b3699
@ -13,6 +13,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.google.com/p/go.tools/go/exact"
|
||||||
_ "code.google.com/p/go.tools/go/gcimporter"
|
_ "code.google.com/p/go.tools/go/gcimporter"
|
||||||
. "code.google.com/p/go.tools/go/types"
|
. "code.google.com/p/go.tools/go/types"
|
||||||
)
|
)
|
||||||
@ -40,11 +41,95 @@ func mustTypecheck(t *testing.T, path, source string, info *Info) string {
|
|||||||
return pkg.Name()
|
return pkg.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValues(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
src string
|
||||||
|
expr string // constant expression
|
||||||
|
typ string // constant type
|
||||||
|
val string // constant value
|
||||||
|
}{
|
||||||
|
{`package a0; const _ = false`, `false`, `untyped bool`, `false`},
|
||||||
|
{`package a1; const _ = 0`, `0`, `untyped int`, `0`},
|
||||||
|
{`package a2; const _ = 'A'`, `'A'`, `untyped rune`, `65`},
|
||||||
|
{`package a3; const _ = 0.`, `0.`, `untyped float`, `0`},
|
||||||
|
{`package a4; const _ = 0i`, `0i`, `untyped complex`, `0`},
|
||||||
|
{`package a5; const _ = "foo"`, `"foo"`, `untyped string`, `"foo"`},
|
||||||
|
|
||||||
|
{`package b0; var _ = false`, `false`, `bool`, `false`},
|
||||||
|
{`package b1; var _ = 0`, `0`, `int`, `0`},
|
||||||
|
{`package b2; var _ = 'A'`, `'A'`, `rune`, `65`},
|
||||||
|
{`package b3; var _ = 0.`, `0.`, `float64`, `0`},
|
||||||
|
{`package b4; var _ = 0i`, `0i`, `complex128`, `0`},
|
||||||
|
{`package b5; var _ = "foo"`, `"foo"`, `string`, `"foo"`},
|
||||||
|
|
||||||
|
{`package c0a; var _ = bool(false)`, `false`, `bool`, `false`},
|
||||||
|
{`package c0b; var _ = bool(false)`, `bool(false)`, `bool`, `false`},
|
||||||
|
{`package c0c; type T bool; var _ = T(false)`, `T(false)`, `c0c.T`, `false`},
|
||||||
|
|
||||||
|
{`package c1a; var _ = int(0)`, `0`, `int`, `0`},
|
||||||
|
{`package c1b; var _ = int(0)`, `int(0)`, `int`, `0`},
|
||||||
|
{`package c1c; type T int; var _ = T(0)`, `T(0)`, `c1c.T`, `0`},
|
||||||
|
|
||||||
|
{`package c2a; var _ = rune('A')`, `'A'`, `rune`, `65`},
|
||||||
|
{`package c2b; var _ = rune('A')`, `rune('A')`, `rune`, `65`},
|
||||||
|
{`package c2c; type T rune; var _ = T('A')`, `T('A')`, `c2c.T`, `65`},
|
||||||
|
|
||||||
|
{`package c3a; var _ = float32(0.)`, `0.`, `float32`, `0`},
|
||||||
|
{`package c3b; var _ = float32(0.)`, `float32(0.)`, `float32`, `0`},
|
||||||
|
{`package c3c; type T float32; var _ = T(0.)`, `T(0.)`, `c3c.T`, `0`},
|
||||||
|
|
||||||
|
{`package c4a; var _ = complex64(0i)`, `0i`, `complex64`, `0`},
|
||||||
|
{`package c4b; var _ = complex64(0i)`, `complex64(0i)`, `complex64`, `0`},
|
||||||
|
{`package c4c; type T complex64; var _ = T(0i)`, `T(0i)`, `c4c.T`, `0`},
|
||||||
|
|
||||||
|
{`package c5a; var _ = string("foo")`, `"foo"`, `string`, `"foo"`},
|
||||||
|
{`package c5b; var _ = string("foo")`, `string("foo")`, `string`, `"foo"`},
|
||||||
|
{`package c5c; type T string; var _ = T("foo")`, `T("foo")`, `c5c.T`, `"foo"`},
|
||||||
|
|
||||||
|
{`package d0; var _ = []byte("foo")`, `"foo"`, `string`, `"foo"`},
|
||||||
|
{`package d1; var _ = []byte(string("foo"))`, `"foo"`, `string`, `"foo"`},
|
||||||
|
{`package d2; var _ = []byte(string("foo"))`, `string("foo")`, `string`, `"foo"`},
|
||||||
|
{`package d3; type T []byte; var _ = T("foo")`, `"foo"`, `string`, `"foo"`},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
info := Info{
|
||||||
|
Types: make(map[ast.Expr]Type),
|
||||||
|
Values: make(map[ast.Expr]exact.Value),
|
||||||
|
}
|
||||||
|
name := mustTypecheck(t, "Values", test.src, &info)
|
||||||
|
|
||||||
|
// look for constant expression
|
||||||
|
var expr ast.Expr
|
||||||
|
for e := range info.Values {
|
||||||
|
if ExprString(e) == test.expr {
|
||||||
|
expr = e
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if expr == nil {
|
||||||
|
t.Errorf("package %s: no expression found for %s", name, test.expr)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that type is correct
|
||||||
|
if got := info.Types[expr].String(); got != test.typ {
|
||||||
|
t.Errorf("package %s: got type %s; want %s", name, got, test.typ)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// check that value is correct
|
||||||
|
if got := info.Values[expr].String(); got != test.val {
|
||||||
|
t.Errorf("package %s: got value %s; want %s", name, got, test.val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCommaOkTypes(t *testing.T) {
|
func TestCommaOkTypes(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
src string
|
src string
|
||||||
expr string // comma-ok expression string
|
expr string // comma-ok expression
|
||||||
typ string // typestring of comma-ok value
|
typ string // comma-ok value type
|
||||||
}{
|
}{
|
||||||
{`package p0; var x interface{}; var _, _ = x.(int)`,
|
{`package p0; var x interface{}; var _, _ = x.(int)`,
|
||||||
`x.(int)`,
|
`x.(int)`,
|
||||||
|
@ -81,14 +81,14 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||||||
// spec: "As a special case, append also accepts a first argument assignable
|
// spec: "As a special case, append also accepts a first argument assignable
|
||||||
// to type []byte with a second argument of string type followed by ... .
|
// to type []byte with a second argument of string type followed by ... .
|
||||||
// This form appends the bytes of the string.
|
// This form appends the bytes of the string.
|
||||||
if nargs == 2 && call.Ellipsis.IsValid() && x.isAssignableTo(check.conf, NewSlice(Typ[Byte])) {
|
if nargs == 2 && call.Ellipsis.IsValid() && x.isAssignableTo(check.conf, NewSlice(universeByte)) {
|
||||||
arg(x, 1)
|
arg(x, 1)
|
||||||
if x.mode == invalid {
|
if x.mode == invalid {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if isString(x.typ) {
|
if isString(x.typ) {
|
||||||
if check.Types != nil {
|
if check.Types != nil {
|
||||||
sig := makeSig(S, S, NewSlice(Typ[Byte]))
|
sig := makeSig(S, S, NewSlice(universeByte))
|
||||||
sig.isVariadic = true
|
sig.isVariadic = true
|
||||||
check.recordBuiltinType(call.Fun, sig)
|
check.recordBuiltinType(call.Fun, sig)
|
||||||
}
|
}
|
||||||
@ -274,7 +274,7 @@ func (check *checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||||||
switch t := y.typ.Underlying().(type) {
|
switch t := y.typ.Underlying().(type) {
|
||||||
case *Basic:
|
case *Basic:
|
||||||
if isString(y.typ) {
|
if isString(y.typ) {
|
||||||
src = Typ[Byte]
|
src = universeByte
|
||||||
}
|
}
|
||||||
case *Slice:
|
case *Slice:
|
||||||
src = t.elem
|
src = t.elem
|
||||||
|
@ -24,8 +24,8 @@ var builtinCalls = []struct {
|
|||||||
// Note that ...uint8 (instead of ..byte) appears below because that is the type
|
// Note that ...uint8 (instead of ..byte) appears below because that is the type
|
||||||
// that corresponds to Typ[byte] (an alias) - in the other cases, the type name
|
// that corresponds to Typ[byte] (an alias) - in the other cases, the type name
|
||||||
// is chosen by the source. Either way, byte and uint8 denote identical types.
|
// is chosen by the source. Either way, byte and uint8 denote identical types.
|
||||||
{"append", `var s []byte; _ = append(s, "foo"...)`, `func([]byte, ...uint8) []byte`},
|
{"append", `var s []byte; _ = append(s, "foo"...)`, `func([]byte, ...byte) []byte`},
|
||||||
{"append", `type T []byte; var s T; _ = append(s, "foo"...)`, `func(p.T, ...uint8) p.T`},
|
{"append", `type T []byte; var s T; _ = append(s, "foo"...)`, `func(p.T, ...byte) p.T`},
|
||||||
|
|
||||||
{"cap", `var s [10]int; _ = cap(s)`, `invalid type`}, // constant
|
{"cap", `var s [10]int; _ = cap(s)`, `invalid type`}, // constant
|
||||||
{"cap", `var s [10]int; _ = cap(&s)`, `invalid type`}, // constant
|
{"cap", `var s [10]int; _ = cap(&s)`, `invalid type`}, // constant
|
||||||
|
@ -96,6 +96,7 @@ func (check *checker) recordTypeAndValue(x ast.Expr, typ Type, val exact.Value)
|
|||||||
m[x] = typ
|
m[x] = typ
|
||||||
}
|
}
|
||||||
if val != nil {
|
if val != nil {
|
||||||
|
assert(isConstType(typ))
|
||||||
if m := check.Values; m != nil {
|
if m := check.Values; m != nil {
|
||||||
m[x] = val
|
m[x] = val
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,11 @@ import "code.google.com/p/go.tools/go/exact"
|
|||||||
// Conversion type-checks the conversion T(x).
|
// Conversion type-checks the conversion T(x).
|
||||||
// The result is in x.
|
// The result is in x.
|
||||||
func (check *checker) conversion(x *operand, T Type) {
|
func (check *checker) conversion(x *operand, T Type) {
|
||||||
|
constArg := x.mode == constant
|
||||||
|
|
||||||
var ok bool
|
var ok bool
|
||||||
switch {
|
switch {
|
||||||
case x.mode == constant && isConstType(T):
|
case constArg && isConstType(T):
|
||||||
// constant conversion
|
// constant conversion
|
||||||
switch t := T.Underlying().(*Basic); {
|
switch t := T.Underlying().(*Basic); {
|
||||||
case isRepresentableConst(x.val, check.conf, t.kind, &x.val):
|
case isRepresentableConst(x.val, check.conf, t.kind, &x.val):
|
||||||
@ -45,12 +47,14 @@ func (check *checker) conversion(x *operand, T Type) {
|
|||||||
// conversion provides the type, per the spec: "A constant may be
|
// conversion provides the type, per the spec: "A constant may be
|
||||||
// given a type explicitly by a constant declaration or conversion,...".
|
// given a type explicitly by a constant declaration or conversion,...".
|
||||||
final := x.typ
|
final := x.typ
|
||||||
if isUntyped(final) {
|
if isUntyped(x.typ) {
|
||||||
final = T
|
final = T
|
||||||
// For conversions to interfaces, use the argument type's
|
// - For conversions to interfaces, use the argument's default type.
|
||||||
// default type instead. Keep untyped nil for untyped nil
|
// - For conversions of untyped constants to non-constant types, also
|
||||||
// arguments.
|
// use the default type (e.g., []byte("foo") should report string
|
||||||
if isInterface(T) {
|
// not []byte as type for the constant "foo").
|
||||||
|
// - Keep untyped nil for untyped nil arguments.
|
||||||
|
if isInterface(T) || constArg && !isConstType(T) {
|
||||||
final = defaultType(x.typ)
|
final = defaultType(x.typ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ func f(a int, s string) float64 {
|
|||||||
funcScope := fileScope.Child(0)
|
funcScope := fileScope.Child(0)
|
||||||
|
|
||||||
var tests = []string{
|
var tests = []string{
|
||||||
`true => true, untyped boolean`,
|
`true => true, untyped bool`,
|
||||||
`fmt.Println => , func(a ...interface{}) (n int, err error)`,
|
`fmt.Println => , func(a ...interface{}) (n int, err error)`,
|
||||||
`c => 3, untyped float`,
|
`c => 3, untyped float`,
|
||||||
`T => , p.T`,
|
`T => , p.T`,
|
||||||
@ -132,7 +132,7 @@ func f(a int, s string) float64 {
|
|||||||
`x => , int`,
|
`x => , int`,
|
||||||
`d/c => 1, int`,
|
`d/c => 1, int`,
|
||||||
`c/2 => 3/2, untyped float`,
|
`c/2 => 3/2, untyped float`,
|
||||||
`m.Pi < m.E => false, untyped boolean`,
|
`m.Pi < m.E => false, untyped bool`,
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
str, typ := split(test, ", ")
|
str, typ := split(test, ", ")
|
||||||
|
@ -447,7 +447,7 @@ func (check *checker) updateExprType(x ast.Expr, typ Type, final bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we have the final (typed or untyped type).
|
// Otherwise we have the final (typed or untyped type).
|
||||||
// Remove it from the map.
|
// Remove it from the map of yet untyped expressions.
|
||||||
delete(check.untyped, x)
|
delete(check.untyped, x)
|
||||||
|
|
||||||
// If x is the lhs of a shift, its final type must be integer.
|
// If x is the lhs of a shift, its final type must be integer.
|
||||||
@ -895,18 +895,20 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type) exprKind {
|
|||||||
if trace {
|
if trace {
|
||||||
check.trace(e.Pos(), "%s", e)
|
check.trace(e.Pos(), "%s", e)
|
||||||
check.indent++
|
check.indent++
|
||||||
|
defer func() {
|
||||||
|
check.indent--
|
||||||
|
check.trace(e.Pos(), "=> %s", x)
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
kind := check.exprInternal(x, e, hint)
|
kind := check.exprInternal(x, e, hint)
|
||||||
|
|
||||||
// convert x into a user-friendly set of values
|
// convert x into a user-friendly set of values
|
||||||
record := true
|
|
||||||
var typ Type
|
var typ Type
|
||||||
var val exact.Value
|
var val exact.Value
|
||||||
switch x.mode {
|
switch x.mode {
|
||||||
case invalid:
|
case invalid:
|
||||||
typ = Typ[Invalid]
|
typ = Typ[Invalid]
|
||||||
record = false // nothing to do
|
|
||||||
case novalue:
|
case novalue:
|
||||||
typ = (*Tuple)(nil)
|
typ = (*Tuple)(nil)
|
||||||
case constant:
|
case constant:
|
||||||
@ -921,18 +923,10 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type) exprKind {
|
|||||||
// delay notification until it becomes typed
|
// delay notification until it becomes typed
|
||||||
// or until the end of type checking
|
// or until the end of type checking
|
||||||
check.untyped[x.expr] = exprInfo{false, typ.(*Basic), val}
|
check.untyped[x.expr] = exprInfo{false, typ.(*Basic), val}
|
||||||
} else if record {
|
} else {
|
||||||
// TODO(gri) ensure that literals always report
|
|
||||||
// their dynamic (never interface) type.
|
|
||||||
// This is not the case yet.
|
|
||||||
check.recordTypeAndValue(e, typ, val)
|
check.recordTypeAndValue(e, typ, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
if trace {
|
|
||||||
check.indent--
|
|
||||||
check.trace(e.Pos(), "=> %s", x)
|
|
||||||
}
|
|
||||||
|
|
||||||
return kind
|
return kind
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1148,7 +1142,7 @@ func (check *checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
|||||||
// (not a constant) even if the string and the
|
// (not a constant) even if the string and the
|
||||||
// index are constant
|
// index are constant
|
||||||
x.mode = value
|
x.mode = value
|
||||||
x.typ = Typ[Byte]
|
x.typ = universeByte // use 'byte' name
|
||||||
}
|
}
|
||||||
|
|
||||||
case *Array:
|
case *Array:
|
||||||
|
@ -288,22 +288,20 @@ func isIdenticalInternal(x, y Type, p *ifacePair) bool {
|
|||||||
//
|
//
|
||||||
func defaultType(typ Type) Type {
|
func defaultType(typ Type) Type {
|
||||||
if t, ok := typ.(*Basic); ok {
|
if t, ok := typ.(*Basic); ok {
|
||||||
k := t.kind
|
switch t.kind {
|
||||||
switch k {
|
|
||||||
case UntypedBool:
|
case UntypedBool:
|
||||||
k = Bool
|
return Typ[Bool]
|
||||||
case UntypedInt:
|
case UntypedInt:
|
||||||
k = Int
|
return Typ[Int]
|
||||||
case UntypedRune:
|
case UntypedRune:
|
||||||
k = Rune
|
return universeRune // use 'rune' name
|
||||||
case UntypedFloat:
|
case UntypedFloat:
|
||||||
k = Float64
|
return Typ[Float64]
|
||||||
case UntypedComplex:
|
case UntypedComplex:
|
||||||
k = Complex128
|
return Typ[Complex128]
|
||||||
case UntypedString:
|
case UntypedString:
|
||||||
k = String
|
return Typ[String]
|
||||||
}
|
}
|
||||||
typ = Typ[k]
|
|
||||||
}
|
}
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
@ -609,7 +609,7 @@ func (check *checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
|||||||
case *Basic:
|
case *Basic:
|
||||||
if isString(typ) {
|
if isString(typ) {
|
||||||
key = Typ[Int]
|
key = Typ[Int]
|
||||||
val = Typ[Rune]
|
val = universeRune // use 'rune' name
|
||||||
}
|
}
|
||||||
case *Array:
|
case *Array:
|
||||||
key = Typ[Int]
|
key = Typ[Int]
|
||||||
|
6
go/types/testdata/errors.src
vendored
6
go/types/testdata/errors.src
vendored
@ -19,8 +19,8 @@ func f(x int, m map[string]int) {
|
|||||||
// constants
|
// constants
|
||||||
const c1 = 991
|
const c1 = 991
|
||||||
const c2 float32 = 0.5
|
const c2 float32 = 0.5
|
||||||
0 /* ERROR "0 \(untyped integer constant\) is not used" */
|
0 /* ERROR "0 \(untyped int constant\) is not used" */
|
||||||
c1 /* ERROR "c1 \(untyped integer constant 991\) is not used" */
|
c1 /* ERROR "c1 \(untyped int constant 991\) is not used" */
|
||||||
c2 /* ERROR "c2 \(constant 1/2 of type float32\) is not used" */
|
c2 /* ERROR "c2 \(constant 1/2 of type float32\) is not used" */
|
||||||
c1 /* ERROR "c1 \+ c2 \(constant 1983/2 of type float32\) is not used" */ + c2
|
c1 /* ERROR "c1 \+ c2 \(constant 1983/2 of type float32\) is not used" */ + c2
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ func f(x int, m map[string]int) {
|
|||||||
x /* ERROR "x \(variable of type int\) is not used" */
|
x /* ERROR "x \(variable of type int\) is not used" */
|
||||||
|
|
||||||
// values
|
// values
|
||||||
x /* ERROR "x != x \(untyped boolean value\) is not used" */ != x
|
x /* ERROR "x != x \(untyped bool value\) is not used" */ != x
|
||||||
x /* ERROR "x \+ x \(value of type int\) is not used" */ + x
|
x /* ERROR "x \+ x \(value of type int\) is not used" */ + x
|
||||||
|
|
||||||
// value, ok's
|
// value, ok's
|
||||||
|
@ -123,23 +123,21 @@ func (check *checker) ident(x *operand, e *ast.Ident, def *Named, cycleOk bool)
|
|||||||
// If cycleOk is set, e (or elements of e) may refer to a named type that is not
|
// If cycleOk is set, e (or elements of e) may refer to a named type that is not
|
||||||
// yet completely set up.
|
// yet completely set up.
|
||||||
//
|
//
|
||||||
func (check *checker) typ(e ast.Expr, def *Named, cycleOk bool) Type {
|
func (check *checker) typ(e ast.Expr, def *Named, cycleOk bool) (T Type) {
|
||||||
if trace {
|
if trace {
|
||||||
check.trace(e.Pos(), "%s", e)
|
check.trace(e.Pos(), "%s", e)
|
||||||
check.indent++
|
check.indent++
|
||||||
|
defer func() {
|
||||||
|
check.indent--
|
||||||
|
check.trace(e.Pos(), "=> %s", T)
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
t := check.typInternal(e, def, cycleOk)
|
T = check.typInternal(e, def, cycleOk)
|
||||||
assert(e != nil && t != nil && isTyped(t))
|
assert(isTyped(T))
|
||||||
|
check.recordTypeAndValue(e, T, nil)
|
||||||
|
|
||||||
check.recordTypeAndValue(e, t, nil)
|
return
|
||||||
|
|
||||||
if trace {
|
|
||||||
check.indent--
|
|
||||||
check.trace(e.Pos(), "=> %s", t)
|
|
||||||
}
|
|
||||||
|
|
||||||
return t
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// funcType type-checks a function or method type and returns its signature.
|
// funcType type-checks a function or method type and returns its signature.
|
||||||
|
@ -17,6 +17,8 @@ var (
|
|||||||
Universe *Scope
|
Universe *Scope
|
||||||
Unsafe *Package
|
Unsafe *Package
|
||||||
universeIota *Const
|
universeIota *Const
|
||||||
|
universeByte *Basic
|
||||||
|
universeRune *Basic
|
||||||
)
|
)
|
||||||
|
|
||||||
var Typ = [...]*Basic{
|
var Typ = [...]*Basic{
|
||||||
@ -41,8 +43,8 @@ var Typ = [...]*Basic{
|
|||||||
String: {String, IsString, 0, "string"},
|
String: {String, IsString, 0, "string"},
|
||||||
UnsafePointer: {UnsafePointer, 0, 0, "Pointer"},
|
UnsafePointer: {UnsafePointer, 0, 0, "Pointer"},
|
||||||
|
|
||||||
UntypedBool: {UntypedBool, IsBoolean | IsUntyped, 0, "untyped boolean"},
|
UntypedBool: {UntypedBool, IsBoolean | IsUntyped, 0, "untyped bool"},
|
||||||
UntypedInt: {UntypedInt, IsInteger | IsUntyped, 0, "untyped integer"},
|
UntypedInt: {UntypedInt, IsInteger | IsUntyped, 0, "untyped int"},
|
||||||
UntypedRune: {UntypedRune, IsInteger | IsUntyped, 0, "untyped rune"},
|
UntypedRune: {UntypedRune, IsInteger | IsUntyped, 0, "untyped rune"},
|
||||||
UntypedFloat: {UntypedFloat, IsFloat | IsUntyped, 0, "untyped float"},
|
UntypedFloat: {UntypedFloat, IsFloat | IsUntyped, 0, "untyped float"},
|
||||||
UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, 0, "untyped complex"},
|
UntypedComplex: {UntypedComplex, IsComplex | IsUntyped, 0, "untyped complex"},
|
||||||
@ -185,6 +187,8 @@ func init() {
|
|||||||
defPredeclaredFuncs()
|
defPredeclaredFuncs()
|
||||||
|
|
||||||
universeIota = Universe.Lookup("iota").(*Const)
|
universeIota = Universe.Lookup("iota").(*Const)
|
||||||
|
universeByte = Universe.Lookup("byte").(*TypeName).typ.(*Basic)
|
||||||
|
universeRune = Universe.Lookup("rune").(*TypeName).typ.(*Basic)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Objects with names containing blanks are internal and not entered into
|
// Objects with names containing blanks are internal and not entered into
|
||||||
|
Loading…
Reference in New Issue
Block a user