aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Scales <danscales@google.com>2021-09-13 18:50:19 -0700
committerDan Scales <danscales@google.com>2021-09-17 19:50:04 +0000
commitcea7a71d40115333d5943162e5764162b767389d (patch)
tree56060d677326dab6886fc253407af1c95c9bf02f
parent74e384f50d3071c97effa3afd43ec29111587d59 (diff)
downloadgo-cea7a71d40115333d5943162e5764162b767389d.tar.gz
go-cea7a71d40115333d5943162e5764162b767389d.zip
cmd/compile: fix generic type handling in crawler
There are a bunch of nodes beside ONAME and OTYPE, (such as OSTRUCTLIT and OCOMPLIT) which can introduce a generic type that we need to mark. So, just mark any generic type on any node in markInlBody. In this particular issue, the type is introduced by an OSTRUCTLIT node. Updates #48337 Change-Id: I271932518f0c1fb54d91a603e01a855c69df631d Reviewed-on: https://go-review.googlesource.com/c/go/+/349909 Trust: Dan Scales <danscales@google.com> Trust: Carlos Amedee <carlos@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
-rw-r--r--src/cmd/compile/internal/typecheck/crawler.go45
-rw-r--r--test/typeparam/issue48337a.dir/a.go32
-rw-r--r--test/typeparam/issue48337a.dir/main.go12
-rw-r--r--test/typeparam/issue48337a.go7
-rw-r--r--test/typeparam/issue48337a.out1
5 files changed, 73 insertions, 24 deletions
diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go
index 9e523c3d14..3f212aa805 100644
--- a/src/cmd/compile/internal/typecheck/crawler.go
+++ b/src/cmd/compile/internal/typecheck/crawler.go
@@ -44,12 +44,13 @@ func (p *crawler) markObject(n *ir.Name) {
p.markType(n.Type())
}
-// markType recursively visits types reachable from t to identify
-// functions whose inline bodies may be needed.
+// markType recursively visits types reachable from t to identify functions whose
+// inline bodies may be needed. For instantiated generic types, it visits the base
+// generic type, which has the relevant methods.
func (p *crawler) markType(t *types.Type) {
- if t.IsInstantiatedGeneric() {
- // Re-instantiated types don't add anything new, so don't follow them.
- return
+ if t.OrigSym() != nil {
+ // Convert to the base generic type.
+ t = t.OrigSym().Def.Type()
}
if p.marked[t] {
return
@@ -92,6 +93,9 @@ func (p *crawler) markType(t *types.Type) {
p.markType(t.Elem())
case types.TSTRUCT:
+ if t.IsFuncArgStruct() {
+ break
+ }
for _, f := range t.FieldSlice() {
if types.IsExported(f.Sym.Name) || f.Embedded != 0 {
p.markType(f.Type)
@@ -129,9 +133,9 @@ func (p *crawler) markEmbed(t *types.Type) {
t = t.Elem()
}
- if t.IsInstantiatedGeneric() {
- // Re-instantiated types don't add anything new, so don't follow them.
- return
+ if t.OrigSym() != nil {
+ // Convert to the base generic type.
+ t = t.OrigSym().Def.Type()
}
if p.embedded[t] {
@@ -185,6 +189,15 @@ func (p *crawler) markInlBody(n *ir.Name) {
var doFlood func(n ir.Node)
doFlood = func(n ir.Node) {
+ t := n.Type()
+ if t != nil && (t.HasTParam() || t.IsFullyInstantiated()) {
+ // Ensure that we call markType() on any base generic type
+ // that is written to the export file (even if not explicitly
+ // marked for export), so we will call markInlBody on its
+ // methods, and the methods will be available for
+ // instantiation if needed.
+ p.markType(t)
+ }
switch n.Op() {
case ir.OMETHEXPR, ir.ODOTMETH:
p.markInlBody(ir.MethodExprName(n))
@@ -198,9 +211,6 @@ func (p *crawler) markInlBody(n *ir.Name) {
case ir.PEXTERN:
Export(n)
}
- p.checkGenericType(n.Type())
- case ir.OTYPE:
- p.checkGenericType(n.Type())
case ir.OMETHVALUE:
// Okay, because we don't yet inline indirect
// calls to method values.
@@ -216,16 +226,3 @@ func (p *crawler) markInlBody(n *ir.Name) {
// because after inlining they might be callable.
ir.VisitList(fn.Inl.Body, doFlood)
}
-
-// checkGenerictype ensures that we call markType() on any base generic type that
-// is written to the export file (even if not explicitly marked
-// for export), so its methods will be available for inlining if needed.
-func (p *crawler) checkGenericType(t *types.Type) {
- if t != nil && t.HasTParam() {
- if t.OrigSym() != nil {
- // Convert to the base generic type.
- t = t.OrigSym().Def.Type()
- }
- p.markType(t)
- }
-}
diff --git a/test/typeparam/issue48337a.dir/a.go b/test/typeparam/issue48337a.dir/a.go
new file mode 100644
index 0000000000..6f1b128589
--- /dev/null
+++ b/test/typeparam/issue48337a.dir/a.go
@@ -0,0 +1,32 @@
+// 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 a
+
+import (
+ "fmt"
+ "sync"
+)
+
+type WrapperWithLock[T any] interface {
+ PrintWithLock()
+}
+
+func NewWrapperWithLock[T any](value T) WrapperWithLock[T] {
+ return &wrapperWithLock[T]{
+ Object: value,
+ }
+}
+
+type wrapperWithLock[T any] struct {
+ Lock sync.Mutex
+ Object T
+}
+
+func (w *wrapperWithLock[T]) PrintWithLock() {
+ w.Lock.Lock()
+ defer w.Lock.Unlock()
+
+ fmt.Println(w.Object)
+}
diff --git a/test/typeparam/issue48337a.dir/main.go b/test/typeparam/issue48337a.dir/main.go
new file mode 100644
index 0000000000..16f71153f3
--- /dev/null
+++ b/test/typeparam/issue48337a.dir/main.go
@@ -0,0 +1,12 @@
+// 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 "a"
+
+func main() {
+ obj := a.NewWrapperWithLock("this file does import sync")
+ obj.PrintWithLock()
+}
diff --git a/test/typeparam/issue48337a.go b/test/typeparam/issue48337a.go
new file mode 100644
index 0000000000..76930e5e4f
--- /dev/null
+++ b/test/typeparam/issue48337a.go
@@ -0,0 +1,7 @@
+// rundir -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 ignored
diff --git a/test/typeparam/issue48337a.out b/test/typeparam/issue48337a.out
new file mode 100644
index 0000000000..fa8d3eedcb
--- /dev/null
+++ b/test/typeparam/issue48337a.out
@@ -0,0 +1 @@
+this file does import sync