Commit d1ee5d6e authored by Russ Cox's avatar Russ Cox

bug184 - assignment compatibility in unpacked multireturn

R=ken
OCL=32890
CL=32894
parent 5005fb46
...@@ -1309,6 +1309,8 @@ typecheckaste(int op, Type *tstruct, NodeList *nl) ...@@ -1309,6 +1309,8 @@ typecheckaste(int op, Type *tstruct, NodeList *nl)
yyerror("not enough arguments to %#O", op); yyerror("not enough arguments to %#O", op);
goto out; goto out;
} }
if(isddd(tl->type))
goto out;
if(checkconv(tn->type, tl->type, 0, &xx, &yy) < 0) if(checkconv(tn->type, tl->type, 0, &xx, &yy) < 0)
yyerror("cannot use type %T as type %T", tn->type, tl->type); yyerror("cannot use type %T as type %T", tn->type, tl->type);
tn = tn->down; tn = tn->down;
......
...@@ -1314,7 +1314,7 @@ ascompatte(int op, Type **nl, NodeList *lr, int fp, NodeList **init) ...@@ -1314,7 +1314,7 @@ ascompatte(int op, Type **nl, NodeList *lr, int fp, NodeList **init)
{ {
Type *l, *ll; Type *l, *ll;
Node *r, *a; Node *r, *a;
NodeList *nn, *lr0; NodeList *nn, *lr0, *alist;
Iter savel, peekl; Iter savel, peekl;
lr0 = lr; lr0 = lr;
...@@ -1326,19 +1326,32 @@ ascompatte(int op, Type **nl, NodeList *lr, int fp, NodeList **init) ...@@ -1326,19 +1326,32 @@ ascompatte(int op, Type **nl, NodeList *lr, int fp, NodeList **init)
// 1 to many // 1 to many
peekl = savel; peekl = savel;
if(l != T && r != N if(l != T && r != N && structnext(&peekl) != T && lr->next == nil
&& structnext(&peekl) != T && r->type->etype == TSTRUCT && r->type->funarg) {
&& lr->next == nil // optimization - can do block copy
&& eqtypenoname(r->type, *nl)) { if(eqtypenoname(r->type, *nl)) {
// clumsy check for differently aligned structs. a = nodarg(*nl, fp);
// now that output structs are aligned separately a->type = r->type;
// from the input structs, should never happen. nn = list1(convas(nod(OAS, a, r), init));
if(r->type->width != (*nl)->width) goto ret;
fatal("misaligned multiple return\n\t%T\n\t%T", r->type, *nl); }
a = nodarg(*nl, fp); // conversions involved.
a->type = r->type; // copy into temporaries.
nn = list1(convas(nod(OAS, a, r), init)); alist = nil;
goto ret; for(l=structfirst(&savel, &r->type); l; l=structnext(&savel)) {
a = nod(OXXX, N, N);
tempname(a, l->type);
alist = list(alist, a);
}
a = nod(OAS2, N, N);
a->list = alist;
a->rlist = lr;
typecheck(&a, Etop);
walkstmt(&a);
*init = list(*init, a);
lr = alist;
r = lr->n;
l = structfirst(&savel, nl);
} }
loop: loop:
...@@ -1369,9 +1382,9 @@ loop: ...@@ -1369,9 +1382,9 @@ loop:
if(l == T || r == N) { if(l == T || r == N) {
if(l != T || r != N) { if(l != T || r != N) {
if(l != T) if(l != T)
yyerror("not enough arguments to %O", op); yyerror("xxx not enough arguments to %O", op);
else else
yyerror("too many arguments to %O", op); yyerror("xxx too many arguments to %O", op);
dumptypes(nl, "expected"); dumptypes(nl, "expected");
dumpnodetypes(lr0, "given"); dumpnodetypes(lr0, "given");
} }
......
// $G $D/$F.go && $L $F.$A && ./$A.out
// 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 "fmt"
type Buffer int
func (*Buffer) Read() {
}
type Reader interface { Read() }
func f() *Buffer {
return nil
}
func g() Reader {
// implicit interface conversion in assignment during return
return f()
}
func h() (b *Buffer, ok bool) {
return
}
func i() (r Reader, ok bool) {
// implicit interface conversion in multi-assignment during return
return h();
}
func fmter() (s string, i int, t string) {
return "%#x %q", 100, "hello"
}
func main() {
b := g();
bb, ok := b.(*Buffer);
b, ok = i();
bb, ok = b.(*Buffer);
s := fmt.Sprintf(fmter());
if s != "0x64 \"hello\"" {
panicln(s);
}
}
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