From f6b5ffb5e1d31fd24edadfe6c105886093638825 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sat, 18 Sep 2021 20:02:08 -0700 Subject: [PATCH] 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 Reviewed-by: Cuong Manh Le Reviewed-by: Keith Randall --- src/cmd/compile/internal/typecheck/crawler.go | 28 +++++++++++++------ test/typeparam/issue48454.dir/a.go | 16 +++++++++++ test/typeparam/issue48454.dir/b.go | 11 ++++++++ test/typeparam/issue48454.dir/main.go | 11 ++++++++ test/typeparam/issue48454.go | 7 +++++ 5 files changed, 65 insertions(+), 8 deletions(-) create mode 100644 test/typeparam/issue48454.dir/a.go create mode 100644 test/typeparam/issue48454.dir/b.go create mode 100644 test/typeparam/issue48454.dir/main.go create mode 100644 test/typeparam/issue48454.go diff --git a/src/cmd/compile/internal/typecheck/crawler.go b/src/cmd/compile/internal/typecheck/crawler.go index 3f212aa805..667e76e130 100644 --- a/src/cmd/compile/internal/typecheck/crawler.go +++ b/src/cmd/compile/internal/typecheck/crawler.go @@ -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() +} diff --git a/test/typeparam/issue48454.dir/a.go b/test/typeparam/issue48454.dir/a.go new file mode 100644 index 0000000000..9613916a4c --- /dev/null +++ b/test/typeparam/issue48454.dir/a.go @@ -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() +} diff --git a/test/typeparam/issue48454.dir/b.go b/test/typeparam/issue48454.dir/b.go new file mode 100644 index 0000000000..2b59b714b8 --- /dev/null +++ b/test/typeparam/issue48454.dir/b.go @@ -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] +} diff --git a/test/typeparam/issue48454.dir/main.go b/test/typeparam/issue48454.dir/main.go new file mode 100644 index 0000000000..becb5f3024 --- /dev/null +++ b/test/typeparam/issue48454.dir/main.go @@ -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 +} diff --git a/test/typeparam/issue48454.go b/test/typeparam/issue48454.go new file mode 100644 index 0000000000..76930e5e4f --- /dev/null +++ b/test/typeparam/issue48454.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 -- 2.48.1