gc: preserve uint8 and byte distinction in errors, import data

There is no semantic change here, just better errors.
If a function says it takes a byte, and you pass it an int,
the compiler error now says that you need a byte, not
that you need a uint8.

Groundwork for rune.

R=ken2
CC=golang-dev
https://golang.org/cl/5300042
This commit is contained in:
Russ Cox 2011-10-18 14:55:50 -04:00
parent d604cf7808
commit 862179b0f5
8 changed files with 112 additions and 59 deletions

View file

@ -1,7 +1,7 @@
char *runtimeimport = char *runtimeimport =
"package runtime\n" "package runtime\n"
"import runtime \"runtime\"\n" "import runtime \"runtime\"\n"
"func @\"\".new (typ *uint8) *any\n" "func @\"\".new (typ *byte) *any\n"
"func @\"\".panicindex ()\n" "func @\"\".panicindex ()\n"
"func @\"\".panicslice ()\n" "func @\"\".panicslice ()\n"
"func @\"\".throwreturn ()\n" "func @\"\".throwreturn ()\n"
@ -24,67 +24,67 @@ char *runtimeimport =
"func @\"\".goprintf ()\n" "func @\"\".goprintf ()\n"
"func @\"\".concatstring ()\n" "func @\"\".concatstring ()\n"
"func @\"\".append ()\n" "func @\"\".append ()\n"
"func @\"\".appendslice (typ *uint8, x any, y []any) any\n" "func @\"\".appendslice (typ *byte, x any, y []any) any\n"
"func @\"\".appendstr (typ *uint8, x []uint8, y string) []uint8\n" "func @\"\".appendstr (typ *byte, x []byte, y string) []byte\n"
"func @\"\".cmpstring (? string, ? string) int\n" "func @\"\".cmpstring (? string, ? string) int\n"
"func @\"\".slicestring (? string, ? int, ? int) string\n" "func @\"\".slicestring (? string, ? int, ? int) string\n"
"func @\"\".slicestring1 (? string, ? int) string\n" "func @\"\".slicestring1 (? string, ? int) string\n"
"func @\"\".intstring (? int64) string\n" "func @\"\".intstring (? int64) string\n"
"func @\"\".slicebytetostring (? []uint8) string\n" "func @\"\".slicebytetostring (? []byte) string\n"
"func @\"\".sliceinttostring (? []int) string\n" "func @\"\".sliceinttostring (? []int) string\n"
"func @\"\".stringtoslicebyte (? string) []uint8\n" "func @\"\".stringtoslicebyte (? string) []byte\n"
"func @\"\".stringtosliceint (? string) []int\n" "func @\"\".stringtosliceint (? string) []int\n"
"func @\"\".stringiter (? string, ? int) int\n" "func @\"\".stringiter (? string, ? int) int\n"
"func @\"\".stringiter2 (? string, ? int) (retk int, retv int)\n" "func @\"\".stringiter2 (? string, ? int) (retk int, retv int)\n"
"func @\"\".slicecopy (to any, fr any, wid uint32) int\n" "func @\"\".slicecopy (to any, fr any, wid uint32) int\n"
"func @\"\".slicestringcopy (to any, fr any) int\n" "func @\"\".slicestringcopy (to any, fr any) int\n"
"func @\"\".convI2E (elem any) any\n" "func @\"\".convI2E (elem any) any\n"
"func @\"\".convI2I (typ *uint8, elem any) any\n" "func @\"\".convI2I (typ *byte, elem any) any\n"
"func @\"\".convT2E (typ *uint8, elem any) any\n" "func @\"\".convT2E (typ *byte, elem any) any\n"
"func @\"\".convT2I (typ *uint8, typ2 *uint8, elem any) any\n" "func @\"\".convT2I (typ *byte, typ2 *byte, elem any) any\n"
"func @\"\".assertE2E (typ *uint8, iface any) any\n" "func @\"\".assertE2E (typ *byte, iface any) any\n"
"func @\"\".assertE2E2 (typ *uint8, iface any) (ret any, ok bool)\n" "func @\"\".assertE2E2 (typ *byte, iface any) (ret any, ok bool)\n"
"func @\"\".assertE2I (typ *uint8, iface any) any\n" "func @\"\".assertE2I (typ *byte, iface any) any\n"
"func @\"\".assertE2I2 (typ *uint8, iface any) (ret any, ok bool)\n" "func @\"\".assertE2I2 (typ *byte, iface any) (ret any, ok bool)\n"
"func @\"\".assertE2T (typ *uint8, iface any) any\n" "func @\"\".assertE2T (typ *byte, iface any) any\n"
"func @\"\".assertE2T2 (typ *uint8, iface any) (ret any, ok bool)\n" "func @\"\".assertE2T2 (typ *byte, iface any) (ret any, ok bool)\n"
"func @\"\".assertI2E (typ *uint8, iface any) any\n" "func @\"\".assertI2E (typ *byte, iface any) any\n"
"func @\"\".assertI2E2 (typ *uint8, iface any) (ret any, ok bool)\n" "func @\"\".assertI2E2 (typ *byte, iface any) (ret any, ok bool)\n"
"func @\"\".assertI2I (typ *uint8, iface any) any\n" "func @\"\".assertI2I (typ *byte, iface any) any\n"
"func @\"\".assertI2I2 (typ *uint8, iface any) (ret any, ok bool)\n" "func @\"\".assertI2I2 (typ *byte, iface any) (ret any, ok bool)\n"
"func @\"\".assertI2T (typ *uint8, iface any) any\n" "func @\"\".assertI2T (typ *byte, iface any) any\n"
"func @\"\".assertI2T2 (typ *uint8, iface any) (ret any, ok bool)\n" "func @\"\".assertI2T2 (typ *byte, iface any) (ret any, ok bool)\n"
"func @\"\".ifaceeq (i1 any, i2 any) bool\n" "func @\"\".ifaceeq (i1 any, i2 any) bool\n"
"func @\"\".efaceeq (i1 any, i2 any) bool\n" "func @\"\".efaceeq (i1 any, i2 any) bool\n"
"func @\"\".ifacethash (i1 any) uint32\n" "func @\"\".ifacethash (i1 any) uint32\n"
"func @\"\".efacethash (i1 any) uint32\n" "func @\"\".efacethash (i1 any) uint32\n"
"func @\"\".makemap (mapType *uint8, hint int64) map[any] any\n" "func @\"\".makemap (mapType *byte, hint int64) map[any] any\n"
"func @\"\".mapaccess1 (mapType *uint8, hmap map[any] any, key any) any\n" "func @\"\".mapaccess1 (mapType *byte, hmap map[any] any, key any) any\n"
"func @\"\".mapaccess2 (mapType *uint8, hmap map[any] any, key any) (val any, pres bool)\n" "func @\"\".mapaccess2 (mapType *byte, hmap map[any] any, key any) (val any, pres bool)\n"
"func @\"\".mapassign1 (mapType *uint8, hmap map[any] any, key any, val any)\n" "func @\"\".mapassign1 (mapType *byte, hmap map[any] any, key any, val any)\n"
"func @\"\".mapassign2 (mapType *uint8, hmap map[any] any, key any, val any, pres bool)\n" "func @\"\".mapassign2 (mapType *byte, hmap map[any] any, key any, val any, pres bool)\n"
"func @\"\".mapiterinit (mapType *uint8, hmap map[any] any, hiter *any)\n" "func @\"\".mapiterinit (mapType *byte, hmap map[any] any, hiter *any)\n"
"func @\"\".mapdelete (mapType *uint8, hmap map[any] any, key any)\n" "func @\"\".mapdelete (mapType *byte, hmap map[any] any, key any)\n"
"func @\"\".mapiternext (hiter *any)\n" "func @\"\".mapiternext (hiter *any)\n"
"func @\"\".mapiter1 (hiter *any) any\n" "func @\"\".mapiter1 (hiter *any) any\n"
"func @\"\".mapiter2 (hiter *any) (key any, val any)\n" "func @\"\".mapiter2 (hiter *any) (key any, val any)\n"
"func @\"\".makechan (chanType *uint8, hint int64) chan any\n" "func @\"\".makechan (chanType *byte, hint int64) chan any\n"
"func @\"\".chanrecv1 (chanType *uint8, hchan <-chan any) any\n" "func @\"\".chanrecv1 (chanType *byte, hchan <-chan any) any\n"
"func @\"\".chanrecv2 (chanType *uint8, hchan <-chan any) (elem any, received bool)\n" "func @\"\".chanrecv2 (chanType *byte, hchan <-chan any) (elem any, received bool)\n"
"func @\"\".chansend1 (chanType *uint8, hchan chan<- any, elem any)\n" "func @\"\".chansend1 (chanType *byte, hchan chan<- any, elem any)\n"
"func @\"\".closechan (hchan any)\n" "func @\"\".closechan (hchan any)\n"
"func @\"\".selectnbsend (chanType *uint8, hchan chan<- any, elem any) bool\n" "func @\"\".selectnbsend (chanType *byte, hchan chan<- any, elem any) bool\n"
"func @\"\".selectnbrecv (chanType *uint8, elem *any, hchan <-chan any) bool\n" "func @\"\".selectnbrecv (chanType *byte, elem *any, hchan <-chan any) bool\n"
"func @\"\".selectnbrecv2 (chanType *uint8, elem *any, received *bool, hchan <-chan any) bool\n" "func @\"\".selectnbrecv2 (chanType *byte, elem *any, received *bool, hchan <-chan any) bool\n"
"func @\"\".newselect (size int) *uint8\n" "func @\"\".newselect (size int) *byte\n"
"func @\"\".selectsend (sel *uint8, hchan chan<- any, elem *any) bool\n" "func @\"\".selectsend (sel *byte, hchan chan<- any, elem *any) bool\n"
"func @\"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) bool\n" "func @\"\".selectrecv (sel *byte, hchan <-chan any, elem *any) bool\n"
"func @\"\".selectrecv2 (sel *uint8, hchan <-chan any, elem *any, received *bool) bool\n" "func @\"\".selectrecv2 (sel *byte, hchan <-chan any, elem *any, received *bool) bool\n"
"func @\"\".selectdefault (sel *uint8) bool\n" "func @\"\".selectdefault (sel *byte) bool\n"
"func @\"\".selectgo (sel *uint8)\n" "func @\"\".selectgo (sel *byte)\n"
"func @\"\".block ()\n" "func @\"\".block ()\n"
"func @\"\".makeslice (typ *uint8, nel int64, cap int64) []any\n" "func @\"\".makeslice (typ *byte, nel int64, cap int64) []any\n"
"func @\"\".growslice (typ *uint8, old []any, n int64) []any\n" "func @\"\".growslice (typ *byte, old []any, n int64) []any\n"
"func @\"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n" "func @\"\".sliceslice1 (old []any, lb uint64, width uint64) []any\n"
"func @\"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n" "func @\"\".sliceslice (old []any, lb uint64, hb uint64, width uint64) []any\n"
"func @\"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n" "func @\"\".slicearray (old *any, nel uint64, lb uint64, hb uint64, width uint64) []any\n"

View file

@ -94,7 +94,7 @@ dumpprereq(Type *t)
if(t == T) if(t == T)
return; return;
if(t->printed || t == types[t->etype]) if(t->printed || t == types[t->etype] || t == bytetype)
return; return;
t->printed = 1; t->printed = 1;

View file

@ -784,6 +784,7 @@ EXTERN Idir* idirs;
EXTERN Type* types[NTYPE]; EXTERN Type* types[NTYPE];
EXTERN Type* idealstring; EXTERN Type* idealstring;
EXTERN Type* idealbool; EXTERN Type* idealbool;
EXTERN Type* bytetype;
EXTERN uchar simtype[NTYPE]; EXTERN uchar simtype[NTYPE];
EXTERN uchar isptr[NTYPE]; EXTERN uchar isptr[NTYPE];
EXTERN uchar isforw[NTYPE]; EXTERN uchar isforw[NTYPE];

View file

@ -19,6 +19,7 @@ int yyprev;
int yylast; int yylast;
static void lexinit(void); static void lexinit(void);
static void lexinit1(void);
static void lexfini(void); static void lexfini(void);
static void yytinit(void); static void yytinit(void);
static int getc(void); static int getc(void);
@ -211,6 +212,7 @@ main(int argc, char *argv[])
lexinit(); lexinit();
typeinit(); typeinit();
lexinit1();
yytinit(); yytinit();
blockgen = 1; blockgen = 1;
@ -1588,7 +1590,6 @@ static struct
"complex128", LNAME, TCOMPLEX128, OXXX, "complex128", LNAME, TCOMPLEX128, OXXX,
"bool", LNAME, TBOOL, OXXX, "bool", LNAME, TBOOL, OXXX,
"byte", LNAME, TUINT8, OXXX,
"string", LNAME, TSTRING, OXXX, "string", LNAME, TSTRING, OXXX,
"any", LNAME, TANY, OXXX, "any", LNAME, TANY, OXXX,
@ -1706,6 +1707,21 @@ lexinit(void)
nblank = s->def; nblank = s->def;
} }
static void
lexinit1(void)
{
Sym *s, *s1;
// byte alias
s = lookup("byte");
s->lexical = LNAME;
bytetype = typ(TUINT8);
bytetype->sym = s;
s1 = pkglookup("byte", builtinpkg);
s1->lexical = LNAME;
s1->def = typenod(bytetype);
}
static void static void
lexfini(void) lexfini(void)
{ {
@ -1741,6 +1757,10 @@ lexfini(void)
// there's only so much table-driven we can handle. // there's only so much table-driven we can handle.
// these are special cases. // these are special cases.
s = lookup("byte");
if(s->def == N)
s->def = typenod(bytetype);
types[TNIL] = typ(TNIL); types[TNIL] = typ(TNIL);
s = lookup("nil"); s = lookup("nil");
if(s->def == N) { if(s->def == N) {

View file

@ -692,7 +692,7 @@ dtypesym(Type *t)
tbase = t->type; tbase = t->type;
dupok = tbase->sym == S; dupok = tbase->sym == S;
if(compiling_runtime && tbase == types[tbase->etype]) // int, float, etc if(compiling_runtime && (tbase == types[tbase->etype] || tbase == bytetype)) // int, float, etc
goto ok; goto ok;
// named types from other files are defined only by those files // named types from other files are defined only by those files

View file

@ -1280,12 +1280,18 @@ Tpretty(Fmt *fp, Type *t)
debug['r'] = 1; debug['r'] = 1;
return 0; return 0;
} }
if(noargnames) {
// called from typesym
if(t == bytetype)
t = types[bytetype->etype];
}
if(t->etype != TFIELD if(t->etype != TFIELD
&& t->sym != S && t->sym != S
&& !(fp->flags&FmtLong)) { && !(fp->flags&FmtLong)) {
s = t->sym; s = t->sym;
if(t == types[t->etype] && t->etype != TUNSAFEPTR) if((t == types[t->etype] && t->etype != TUNSAFEPTR) || t == bytetype)
return fmtprint(fp, "%s", s->name); return fmtprint(fp, "%s", s->name);
if(exporting) { if(exporting) {
if(fp->flags & FmtShort) if(fp->flags & FmtShort)
@ -1859,8 +1865,19 @@ eqtype(Type *t1, Type *t2)
{ {
if(t1 == t2) if(t1 == t2)
return 1; return 1;
if(t1 == T || t2 == T || t1->etype != t2->etype || t1->sym || t2->sym) if(t1 == T || t2 == T || t1->etype != t2->etype)
return 0; return 0;
if(t1->sym || t2->sym) {
// Special case: we keep byte and uint8 separate
// for error messages. Treat them as equal.
switch(t1->etype) {
case TUINT8:
if((t1 == types[TUINT8] || t1 == bytetype) && (t2 == types[TUINT8] || t2 == bytetype))
return 1;
break;
}
return 0;
}
switch(t1->etype) { switch(t1->etype) {
case TINTER: case TINTER:
@ -2088,24 +2105,20 @@ convertop(Type *src, Type *dst, char **why)
if(isint[src->etype] && dst->etype == TSTRING) if(isint[src->etype] && dst->etype == TSTRING)
return ORUNESTR; return ORUNESTR;
if(isslice(src) && src->sym == nil && src->type == types[src->type->etype] && dst->etype == TSTRING) { if(isslice(src) && src->sym == nil && dst->etype == TSTRING) {
switch(src->type->etype) { if(eqtype(src->type, bytetype))
case TUINT8:
return OARRAYBYTESTR; return OARRAYBYTESTR;
case TINT: if(eqtype(src->type, types[TINT]))
return OARRAYRUNESTR; return OARRAYRUNESTR;
}
} }
// 7. src is a string and dst is []byte or []int. // 7. src is a string and dst is []byte or []int.
// String to slice. // String to slice.
if(src->etype == TSTRING && isslice(dst) && dst->sym == nil && dst->type == types[dst->type->etype]) { if(src->etype == TSTRING && isslice(dst) && dst->sym == nil) {
switch(dst->type->etype) { if(eqtype(dst->type, bytetype))
case TUINT8:
return OSTRARRAYBYTE; return OSTRARRAYBYTE;
case TINT: if(eqtype(dst->type, types[TINT]))
return OSTRARRAYRUNE; return OSTRARRAYRUNE;
}
} }
// 8. src is a pointer or uintptr and dst is unsafe.Pointer. // 8. src is a pointer or uintptr and dst is unsafe.Pointer.

View file

@ -1040,7 +1040,7 @@ reswitch:
yyerror("too many arguments to append"); yyerror("too many arguments to append");
goto error; goto error;
} }
if(istype(t->type, TUINT8) && istype(args->next->n->type, TSTRING)) { if(istype(t->type, TUINT8) && istype(args->next->n->type, TSTRING)) {
defaultlit(&args->next->n, types[TSTRING]); defaultlit(&args->next->n, types[TSTRING]);
goto ret; goto ret;
} }
@ -1078,7 +1078,7 @@ reswitch:
// copy([]byte, string) // copy([]byte, string)
if(isslice(n->left->type) && n->right->type->etype == TSTRING) { if(isslice(n->left->type) && n->right->type->etype == TSTRING) {
if(n->left->type->type == types[TUINT8]) if(eqtype(n->left->type->type, bytetype))
goto ret; goto ret;
yyerror("arguments to copy have different element types: %lT and string", n->left->type); yyerror("arguments to copy have different element types: %lT and string", n->left->type);
goto error; goto error;

19
test/alias.go Normal file
View file

@ -0,0 +1,19 @@
// errchk $G -e $D/$F.go
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
// Test that error messages say what the source file says
// (uint8 vs byte).
func f(byte) {}
func g(uint8) {}
func main() {
var x int
f(x) // ERROR "byte"
g(x) // ERROR "uint8"
}