Commit 862179b0 authored by Russ Cox's avatar Russ Cox

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
parent d604cf78
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 = ...@@ -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"
......
...@@ -94,7 +94,7 @@ dumpprereq(Type *t) ...@@ -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;
......
...@@ -784,6 +784,7 @@ EXTERN Idir* idirs; ...@@ -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];
......
...@@ -19,6 +19,7 @@ int yyprev; ...@@ -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[]) ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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) {
......
...@@ -692,7 +692,7 @@ dtypesym(Type *t) ...@@ -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
......
...@@ -1280,12 +1280,18 @@ Tpretty(Fmt *fp, Type *t) ...@@ -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) ...@@ -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;
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; return 0;
}
switch(t1->etype) { switch(t1->etype) {
case TINTER: case TINTER:
...@@ -2088,24 +2105,20 @@ convertop(Type *src, Type *dst, char **why) ...@@ -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.
......
...@@ -1040,7 +1040,7 @@ reswitch: ...@@ -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: ...@@ -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;
......
// 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"
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment