Skip to content

Commit

Permalink
cmd/compile: fix transform.AssignOp to deal with tricky case
Browse files Browse the repository at this point in the history
When going to dictionary formats derived from the function
instantiations, I had broken out noder.Assignop() to deal specially with
shape types, but didn't quite get the tricky case right. We still need
to allow conversion between shape types, but if the destination is an
interface, we need to use CONVIFACE rather than CONVNOP.

Fixes #48453.

Change-Id: I8c4b39c2e628172ac34f493f1dd682cbac1e55ae
Reviewed-on: https://go-review.googlesource.com/c/go/+/350949
Trust: Dan Scales <[email protected]>
Run-TryBot: Dan Scales <[email protected]>
Reviewed-by: Keith Randall <[email protected]>
  • Loading branch information
danscales committed Sep 20, 2021
1 parent 9e60c37 commit b6dddac
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 3 deletions.
15 changes: 12 additions & 3 deletions src/cmd/compile/internal/noder/transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,18 @@ func Assignop(src, dst *types.Type) (ir.Op, string) {
return ir.OXXX, ""
}

// 1. src type is identical to dst.
if types.IdenticalStrict(src, dst) {
return ir.OCONVNOP, ""
// 1. src type is identical to dst (taking shapes into account)
if types.Identical(src, dst) {
// We already know from assignconvfn above that IdenticalStrict(src,
// dst) is false, so the types are not exactly the same and one of
// src or dst is a shape. If dst is an interface (which means src is
// an interface too), we need a real OCONVIFACE op; otherwise we need a
// OCONVNOP. See issue #48453.
if dst.IsInterface() {
return ir.OCONVIFACE, ""
} else {
return ir.OCONVNOP, ""
}
}
return typecheck.Assignop1(src, dst)
}
Expand Down
21 changes: 21 additions & 0 deletions test/typeparam/issue48453.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// run -gcflags=-G=3

// 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

//go:noinline
func CopyMap[M interface{ ~map[K]V }, K comparable, V any](m M) M {
out := make(M, len(m))
for k, v := range m {
out[k] = v
}
return out
}

func main() {
var m map[*string]int
CopyMap(m)
}

0 comments on commit b6dddac

Please sign in to comment.