aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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