diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go index 175216f279..922a01bfbe 100644 --- a/src/cmd/compile/internal/typecheck/stmt.go +++ b/src/cmd/compile/internal/typecheck/stmt.go @@ -204,8 +204,20 @@ assignOK: r.Use = ir.CallUseList rtyp := r.Type() + mismatched := false + failed := false for i := range lhs { - assignType(i, rtyp.Field(i).Type) + result := rtyp.Field(i).Type + assignType(i, result) + + if lhs[i].Type() == nil || result == nil { + failed = true + } else if lhs[i] != ir.BlankNode && !types.Identical(lhs[i].Type(), result) { + mismatched = true + } + } + if mismatched && !failed { + rewriteMultiValueCall(stmt, r) } return } diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index 391e18bd0a..bf52941b2c 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -989,6 +989,16 @@ func rewriteMultiValueCall(n ir.InitNode, call ir.Node) { n.Args = list case *ir.ReturnStmt: n.Results = list + case *ir.AssignListStmt: + if n.Op() != ir.OAS2FUNC { + base.Fatalf("rewriteMultiValueCall: invalid op %v", n.Op()) + } + as.SetOp(ir.OAS2FUNC) + n.SetOp(ir.OAS2) + n.Rhs = make([]ir.Node, len(list)) + for i, tmp := range list { + n.Rhs[i] = AssignConv(tmp, n.Lhs[i].Type(), "assignment") + } } } diff --git a/test/declbad.go b/test/declbad.go index 728eceb7f1..b978652a2b 100644 --- a/test/declbad.go +++ b/test/declbad.go @@ -23,13 +23,13 @@ func main() { { // change of type for f i, f, s := f3() - f, g, t := f3() // ERROR "redeclared|cannot assign|incompatible" + f, g, t := f3() // ERROR "redeclared|cannot assign|incompatible|cannot use" _, _, _, _, _ = i, f, s, g, t } { // change of type for i i, f, s := f3() - j, i, t := f3() // ERROR "redeclared|cannot assign|incompatible" + j, i, t := f3() // ERROR "redeclared|cannot assign|incompatible|cannot use" _, _, _, _, _ = i, f, s, j, t } { diff --git a/test/fixedbugs/issue46725.go b/test/fixedbugs/issue46725.go new file mode 100644 index 0000000000..29799c7d7e --- /dev/null +++ b/test/fixedbugs/issue46725.go @@ -0,0 +1,48 @@ +// run + +// Copyright 2021 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 "runtime" + +type T [4]int + +//go:noinline +func g(x []*T) ([]*T, []*T) { return x, x } + +func main() { + const Jenny = 8675309 + s := [10]*T{{Jenny}} + + done := make(chan struct{}) + runtime.SetFinalizer(s[0], func(p *T) { close(done) }) + + var h, _ interface{} = g(s[:]) + + if wait(done) { + panic("GC'd early") + } + + if h.([]*T)[0][0] != Jenny { + panic("lost Jenny's number") + } + + if !wait(done) { + panic("never GC'd") + } +} + +func wait(done <-chan struct{}) bool { + for i := 0; i < 10; i++ { + runtime.GC() + select { + case <-done: + return true + default: + } + } + return false +}