Skip to content

Commit 24a7ce5

Browse files
committed
Merge pull request #445 from brett19/master
perform implicit casting for tuple returns if needed (fixes #444)
2 parents 5fbc215 + 1cf4729 commit 24a7ce5

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

compiler/statements.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,26 @@ func (c *funcContext) translateResults(results []ast.Expr) string {
748748
return " " + v.String()
749749
default:
750750
if len(results) == 1 {
751-
return " " + c.translateExpr(results[0]).String()
751+
resultTuple := c.p.TypeOf(results[0]).(*types.Tuple)
752+
753+
if resultTuple.Len() != tuple.Len() {
754+
panic("invalid tuple return assignment")
755+
}
756+
757+
resultExpr := c.translateExpr(results[0]).String()
758+
759+
if types.Identical(resultTuple, tuple) {
760+
return " " + resultExpr
761+
}
762+
763+
tmpVar := c.newVariable("_returncast")
764+
c.Printf("%s = %s;", tmpVar, resultExpr)
765+
766+
// Not all the return types matched, map everything out for implicit casting
767+
results = make([]ast.Expr, resultTuple.Len())
768+
for i := range results {
769+
results[i] = c.newIdent(fmt.Sprintf("%s[%d]", tmpVar, i), resultTuple.At(i).Type())
770+
}
752771
}
753772
values := make([]string, tuple.Len())
754773
for i := range values {

tests/misc_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,3 +535,53 @@ func TestTrivialSwitch(t *testing.T) {
535535
}
536536
t.Fail()
537537
}
538+
539+
func TestTupleFnReturnImplicitCast(t *testing.T) {
540+
var ycalled int = 0
541+
x := func(fn func() (int, error)) (interface{}, error) {
542+
return fn()
543+
}
544+
y, _ := x(func() (int, error) {
545+
ycalled++
546+
return 14, nil
547+
})
548+
if y != 14 || ycalled != 1 {
549+
t.Fail()
550+
}
551+
}
552+
553+
var tuple2called = 0
554+
555+
func tuple1() (interface{}, error) {
556+
return tuple2()
557+
}
558+
func tuple2() (int, error) {
559+
tuple2called++
560+
return 14, nil
561+
}
562+
func TestTupleReturnImplicitCast(t *testing.T) {
563+
x, _ := tuple1()
564+
if x != 14 || tuple2called != 1 {
565+
t.Fail()
566+
}
567+
}
568+
569+
func TestDeferNamedTupleReturnImplicitCast(t *testing.T) {
570+
var ycalled int = 0
571+
var zcalled int = 0
572+
z := func() {
573+
zcalled++
574+
}
575+
x := func(fn func() (int, error)) (i interface{}, e error) {
576+
defer z()
577+
i, e = fn()
578+
return
579+
}
580+
y, _ := x(func() (int, error) {
581+
ycalled++
582+
return 14, nil
583+
})
584+
if y != 14 || ycalled != 1 || zcalled != 1 {
585+
t.Fail()
586+
}
587+
}

0 commit comments

Comments
 (0)