From 480f51243c0b21f4631efe15a5b61c50eea4e7ed Mon Sep 17 00:00:00 2001 From: Russ Cox <rsc@golang.org> Date: Thu, 25 Jun 2009 21:02:39 -0700 Subject: [PATCH] bug165 R=ken OCL=30783 CL=30783 --- src/cmd/gc/dcl.c | 11 +++++++++++ src/cmd/gc/go.h | 2 ++ src/cmd/gc/subr.c | 15 +++++++++++++-- test/{bugs => fixedbugs}/bug165.go | 6 +++++- test/golden.out | 4 ---- 5 files changed, 31 insertions(+), 7 deletions(-) rename test/{bugs => fixedbugs}/bug165.go (72%) diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index c33ead564d..38bc022d28 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -93,6 +93,7 @@ updatetype(Type *n, Type *t) { Sym *s; int local; + int maplineno, lno; s = n->sym; if(s == S || s->def == N || s->def->op != OTYPE || s->def->type != n) @@ -124,6 +125,7 @@ updatetype(Type *n, Type *t) // type n t; // copy t, but then zero out state associated with t // that is no longer associated with n. + maplineno = n->maplineno; local = n->local; *n = *t; n->sym = s; @@ -133,6 +135,7 @@ updatetype(Type *n, Type *t) n->method = nil; n->vargen = 0; n->nod = N; + // catch declaration of incomplete type switch(n->etype) { case TFORWSTRUCT: @@ -141,6 +144,14 @@ updatetype(Type *n, Type *t) default: checkwidth(n); } + + // double-check use of type as map key + if(maplineno) { + lno = lineno; + lineno = maplineno; + maptype(n, types[TBOOL]); + lineno = lno; + } } diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 876a03a93a..3b521dd2dd 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -171,6 +171,8 @@ struct Type // TARRAY int32 bound; // negative is dynamic array + + int32 maplineno; // first use of TFORW as map key }; #define T ((Type*)0) diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 9dfb445c63..2e0c6b07da 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -345,8 +345,19 @@ maptype(Type *key, Type *val) { Type *t; - if(key != nil && key->etype != TANY && algtype(key) == ANOEQ) - yyerror("invalid map key type %T", key); + if(key != nil && key->etype != TANY && algtype(key) == ANOEQ) { + if(key->etype == TFORW) { + // map[key] used during definition of key. + // postpone check until key is fully defined. + // if there are multiple uses of map[key] + // before key is fully defined, the error + // will only be printed for the first one. + // good enough. + if(key->maplineno == 0) + key->maplineno = lineno; + } else + yyerror("invalid map key type %T", key); + } t = typ(TMAP); t->down = key; t->type = val; diff --git a/test/bugs/bug165.go b/test/fixedbugs/bug165.go similarity index 72% rename from test/bugs/bug165.go rename to test/fixedbugs/bug165.go index 02a6c379b4..8ce67a46db 100644 --- a/test/bugs/bug165.go +++ b/test/fixedbugs/bug165.go @@ -7,5 +7,9 @@ package main type I interface { - m(map[I] bool) + m(map[I] bool); // ok +} + +type S struct { + m map[S] bool; // ERROR "map key type" } diff --git a/test/golden.out b/test/golden.out index 09ac96269a..695a68cd41 100644 --- a/test/golden.out +++ b/test/golden.out @@ -111,10 +111,6 @@ BUG: should not compile =========== bugs/bug164.go BUG: should not compile -=========== bugs/bug165.go -bugs/bug165.go:6: invalid map key type I -BUG: should compile - =========== fixedbugs/bug016.go fixedbugs/bug016.go:7: constant -3 overflows uint -- 2.30.9