mirror of
https://github.com/golang/go
synced 2024-09-15 14:10:17 +00:00
cmd/compile: fix crawler for unexported fields with instantiated types
In markType() in crawler.go, mark the type of a unexported field if it is a fully-instantiated type, since we create and instantiate the methods of any fully-instantiated type that we see during import. As before, we still do not mark the type of an unexported field if that type is not generic. Fixes #48454 and most recent issue described in 48337. The included test is similar to the case in 48454. Fixes #48454 Fixes #48337 Change-Id: I77a2a62b9e2647876facfa6f004201e8f699c905 Reviewed-on: https://go-review.googlesource.com/c/go/+/351315 Trust: Dan Scales <danscales@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
812c99f86a
commit
f6b5ffb5e1
|
@ -10,10 +10,12 @@ import (
|
|||
"cmd/compile/internal/types"
|
||||
)
|
||||
|
||||
// crawlExports crawls the type/object graph rooted at the given list
|
||||
// of exported objects. Any functions that are found to be potentially
|
||||
// callable by importers are marked with ExportInline so that
|
||||
// iexport.go knows to re-export their inline body.
|
||||
// crawlExports crawls the type/object graph rooted at the given list of exported
|
||||
// objects. It descends through all parts of types and follows any methods on defined
|
||||
// types. Any functions that are found to be potentially callable by importers are
|
||||
// marked with ExportInline, so that iexport.go knows to re-export their inline body.
|
||||
// Also, any function or global referenced by a function marked by ExportInline() is
|
||||
// marked for export (whether its name is exported or not).
|
||||
func crawlExports(exports []*ir.Name) {
|
||||
p := crawler{
|
||||
marked: make(map[*types.Type]bool),
|
||||
|
@ -29,7 +31,7 @@ type crawler struct {
|
|||
embedded map[*types.Type]bool // types already seen by markEmbed
|
||||
}
|
||||
|
||||
// markObject visits a reachable object.
|
||||
// markObject visits a reachable object (function, method, global type, or global variable)
|
||||
func (p *crawler) markObject(n *ir.Name) {
|
||||
if n.Op() == ir.ONAME && n.Class == ir.PFUNC {
|
||||
p.markInlBody(n)
|
||||
|
@ -97,7 +99,12 @@ func (p *crawler) markType(t *types.Type) {
|
|||
break
|
||||
}
|
||||
for _, f := range t.FieldSlice() {
|
||||
if types.IsExported(f.Sym.Name) || f.Embedded != 0 {
|
||||
// Mark the type of a unexported field if it is a
|
||||
// fully-instantiated type, since we create and instantiate
|
||||
// the methods of any fully-instantiated type that we see
|
||||
// during import (see end of typecheck.substInstType).
|
||||
if types.IsExported(f.Sym.Name) || f.Embedded != 0 ||
|
||||
isPtrFullyInstantiated(f.Type) {
|
||||
p.markType(f.Type)
|
||||
}
|
||||
}
|
||||
|
@ -108,8 +115,6 @@ func (p *crawler) markType(t *types.Type) {
|
|||
}
|
||||
|
||||
case types.TINTER:
|
||||
// TODO(danscales) - will have to deal with the types in interface
|
||||
// elements here when implemented in types2 and represented in types1.
|
||||
for _, f := range t.AllMethods().Slice() {
|
||||
if types.IsExported(f.Sym.Name) {
|
||||
p.markType(f.Type)
|
||||
|
@ -226,3 +231,10 @@ func (p *crawler) markInlBody(n *ir.Name) {
|
|||
// because after inlining they might be callable.
|
||||
ir.VisitList(fn.Inl.Body, doFlood)
|
||||
}
|
||||
|
||||
// isPtrFullyInstantiated returns true if t is a fully-instantiated type, or it is a
|
||||
// pointer to a fully-instantiated type.
|
||||
func isPtrFullyInstantiated(t *types.Type) bool {
|
||||
return t.IsPtr() && t.Elem().IsFullyInstantiated() ||
|
||||
t.IsFullyInstantiated()
|
||||
}
|
||||
|
|
16
test/typeparam/issue48454.dir/a.go
Normal file
16
test/typeparam/issue48454.dir/a.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
// 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 "sync"
|
||||
|
||||
type Val[T any] struct {
|
||||
mu sync.RWMutex
|
||||
val T
|
||||
}
|
||||
|
||||
func (v *Val[T]) Has() {
|
||||
v.mu.RLock()
|
||||
}
|
11
test/typeparam/issue48454.dir/b.go
Normal file
11
test/typeparam/issue48454.dir/b.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
// 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 b
|
||||
|
||||
import "a"
|
||||
|
||||
type Session struct {
|
||||
privateField a.Val[string]
|
||||
}
|
11
test/typeparam/issue48454.dir/main.go
Normal file
11
test/typeparam/issue48454.dir/main.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
// 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 "b"
|
||||
|
||||
func main() {
|
||||
var _ b.Session
|
||||
}
|
7
test/typeparam/issue48454.go
Normal file
7
test/typeparam/issue48454.go
Normal file
|
@ -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
|
Loading…
Reference in a new issue