summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/gc/walk.c47
-rw-r--r--test/assign.go33
2 files changed, 79 insertions, 1 deletions
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index b1c1c2d22..8b4fc40f2 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -2047,13 +2047,58 @@ loop:
}
/*
+ * do the export rules allow writing to this type?
+ * cannot be implicitly assigning to any type with
+ * an unavailable field.
+ */
+int
+exportasok(Type *t)
+{
+ Type *f;
+ Sym *s;
+
+ if(t == T)
+ return 1;
+ switch(t->etype) {
+ default:
+ // most types can't contain others; they're all fine.
+ break;
+ case TSTRUCT:
+ for(f=t->type; f; f=f->down) {
+ if(f->etype != TFIELD)
+ fatal("structas: not field");
+ s = f->sym;
+ // s == nil doesn't happen for embedded fields (they get the type symbol).
+ // it only happens for fields in a ... struct.
+ if(s != nil && !exportname(s->name) && strcmp(package, s->package) != 0) {
+ yyerror("implicit assignment of %T field '%s'", t, s->name);
+ return 0;
+ }
+ if(!exportasok(f->type))
+ return 0;
+ }
+ break;
+
+ case TARRAY:
+ if(t->bound < 0) // slices are pointers; that's fine
+ break;
+ if(!exportasok(t->type))
+ return 0;
+ break;
+ }
+ return 1;
+}
+
+/*
* can we assign var of type src to var of type dst
*/
int
ascompat(Type *dst, Type *src)
{
- if(eqtype(dst, src))
+ if(eqtype(dst, src)) {
+ exportasok(src);
return 1;
+ }
if(dst == T || src == T)
return 0;
diff --git a/test/assign.go b/test/assign.go
new file mode 100644
index 000000000..a98b7b75a
--- /dev/null
+++ b/test/assign.go
@@ -0,0 +1,33 @@
+// errchk $G $D/$F.go
+
+// Copyright 2009 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
+
+import "sync"
+
+type T struct {
+ int;
+ sync.Mutex;
+}
+
+func main() {
+ {
+ var x, y sync.Mutex;
+ x = y; // ERROR "assignment.*Mutex"
+ }
+ {
+ var x, y T;
+ x = y; // ERROR "assignment.*Mutex"
+ }
+ {
+ var x, y [2]sync.Mutex;
+ x = y; // ERROR "assignment.*Mutex"
+ }
+ {
+ var x, y [2]T;
+ x = y; // ERROR "assignment.*Mutex"
+ }
+}