mirror of
https://github.com/golang/go
synced 2024-10-04 15:09:59 +00:00
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:
parent
d604cf7808
commit
862179b0f5
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
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;
|
||||||
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) {
|
||||||
|
|
|
@ -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)
|
||||||
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.
|
||||||
|
|
|
@ -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
19
test/alias.go
Normal 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"
|
||||||
|
}
|
Loading…
Reference in a new issue