mirror of
https://github.com/golang/go
synced 2024-11-25 12:57:58 -07:00
bug184 - assignment compatibility in unpacked multireturn
R=ken OCL=32890 CL=32894
This commit is contained in:
parent
5005fb46a2
commit
d1ee5d6e8f
@ -1309,6 +1309,8 @@ typecheckaste(int op, Type *tstruct, NodeList *nl)
|
||||
yyerror("not enough arguments to %#O", op);
|
||||
goto out;
|
||||
}
|
||||
if(isddd(tl->type))
|
||||
goto out;
|
||||
if(checkconv(tn->type, tl->type, 0, &xx, &yy) < 0)
|
||||
yyerror("cannot use type %T as type %T", tn->type, tl->type);
|
||||
tn = tn->down;
|
||||
|
@ -1314,7 +1314,7 @@ ascompatte(int op, Type **nl, NodeList *lr, int fp, NodeList **init)
|
||||
{
|
||||
Type *l, *ll;
|
||||
Node *r, *a;
|
||||
NodeList *nn, *lr0;
|
||||
NodeList *nn, *lr0, *alist;
|
||||
Iter savel, peekl;
|
||||
|
||||
lr0 = lr;
|
||||
@ -1326,20 +1326,33 @@ ascompatte(int op, Type **nl, NodeList *lr, int fp, NodeList **init)
|
||||
|
||||
// 1 to many
|
||||
peekl = savel;
|
||||
if(l != T && r != N
|
||||
&& structnext(&peekl) != T
|
||||
&& lr->next == nil
|
||||
&& eqtypenoname(r->type, *nl)) {
|
||||
// clumsy check for differently aligned structs.
|
||||
// now that output structs are aligned separately
|
||||
// from the input structs, should never happen.
|
||||
if(r->type->width != (*nl)->width)
|
||||
fatal("misaligned multiple return\n\t%T\n\t%T", r->type, *nl);
|
||||
if(l != T && r != N && structnext(&peekl) != T && lr->next == nil
|
||||
&& r->type->etype == TSTRUCT && r->type->funarg) {
|
||||
// optimization - can do block copy
|
||||
if(eqtypenoname(r->type, *nl)) {
|
||||
a = nodarg(*nl, fp);
|
||||
a->type = r->type;
|
||||
nn = list1(convas(nod(OAS, a, r), init));
|
||||
goto ret;
|
||||
}
|
||||
// conversions involved.
|
||||
// copy into temporaries.
|
||||
alist = nil;
|
||||
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:
|
||||
if(l != T && isddd(l->type)) {
|
||||
@ -1369,9 +1382,9 @@ loop:
|
||||
if(l == T || r == N) {
|
||||
if(l != T || r != N) {
|
||||
if(l != T)
|
||||
yyerror("not enough arguments to %O", op);
|
||||
yyerror("xxx not enough arguments to %O", op);
|
||||
else
|
||||
yyerror("too many arguments to %O", op);
|
||||
yyerror("xxx too many arguments to %O", op);
|
||||
dumptypes(nl, "expected");
|
||||
dumpnodetypes(lr0, "given");
|
||||
}
|
||||
|
51
test/fixedbugs/bug184.go
Normal file
51
test/fixedbugs/bug184.go
Normal file
@ -0,0 +1,51 @@
|
||||
// $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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user