summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-06-25 21:02:39 -0700
committerRuss Cox <rsc@golang.org>2009-06-25 21:02:39 -0700
commit3bcbb610293bec97cd2ae3ac8f575ff756bb8271 (patch)
treea6c9d8788ff4acbaf70e011972a3e487cd42f854
parentb26cd1bfcd7107d8208595614ba45f54d5efacf6 (diff)
downloadgolang-3bcbb610293bec97cd2ae3ac8f575ff756bb8271.tar.gz
bug165
R=ken OCL=30783 CL=30783
-rw-r--r--src/cmd/gc/dcl.c11
-rw-r--r--src/cmd/gc/go.h2
-rw-r--r--src/cmd/gc/subr.c15
-rw-r--r--test/fixedbugs/bug165.go (renamed from test/bugs/bug165.go)6
-rw-r--r--test/golden.out4
5 files changed, 31 insertions, 7 deletions
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index c33ead564..38bc022d2 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 876a03a93..3b521dd2d 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 9dfb445c6..2e0c6b07d 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
index 02a6c379b..8ce67a46d 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 09ac96269..695a68cd4 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