aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/reflectdata/reflect.go
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-06-14 19:21:14 -0700
committerMatthew Dempsky <mdempsky@google.com>2021-06-16 17:32:49 +0000
commit132ea56d292eac0226eef4bc32d784b0300c3bce (patch)
treeb3158a88a1ccfe5e1bed716e952e318b81294e9c /src/cmd/compile/internal/reflectdata/reflect.go
parent8f95eaddd334e61b1832628741b97462ddc84975 (diff)
downloadgo-132ea56d292eac0226eef4bc32d784b0300c3bce.tar.gz
go-132ea56d292eac0226eef4bc32d784b0300c3bce.zip
[dev.typeparams] cmd/compile: fix crawling of embeddable types
In reflectdata, we have a hack to only apply inlining for (*T).M wrappers generated around T.M. This was a hack because I didn't understand at the time why other cases were failing. But I understand now: during export, we generally skip exporting the inline bodies for unexported methods (unless they're reachable through some other exported method). But it doesn't take into account that embedding a type requires generating wrappers for promoted methods, including imported, unexported methods. For example: package a type T struct{} func (T) m() {} // previously omitted by exported package b import "./a" type U struct { a.T } // needs U.m -> T.m wrapper This CL adds extra logic to the crawler to recognize that T is an exported type directly reachable by the user, so *all* of its methods need to be re-exported. This finally allows simplifying reflectdata.methodWrapper to always call inline.InlineCalls. Change-Id: I25031d41fd6b6cd69d31c6a864b5329cdb5780e2 Reviewed-on: https://go-review.googlesource.com/c/go/+/327872 Trust: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Diffstat (limited to 'src/cmd/compile/internal/reflectdata/reflect.go')
-rw-r--r--src/cmd/compile/internal/reflectdata/reflect.go41
1 files changed, 26 insertions, 15 deletions
diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go
index 5516f707fa..f4a0619935 100644
--- a/src/cmd/compile/internal/reflectdata/reflect.go
+++ b/src/cmd/compile/internal/reflectdata/reflect.go
@@ -1795,20 +1795,24 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy
return lsym
}
- // Only generate (*T).M wrappers for T.M in T's own package, except for
- // instantiated methods.
- if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type &&
- rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != types.LocalPkg &&
- !rcvr.Elem().IsFullyInstantiated() {
- return lsym
+ // imported reports whether typ is a defined type that was declared
+ // in an imported package, and therefore must have been compiled in
+ // that package.
+ importedType := func(typ *types.Type) bool {
+ return typ.Sym() != nil && typ.Sym().Pkg != types.LocalPkg &&
+
+ // Exception: need wrapper for error.Error (#29304).
+ // TODO(mdempsky): Put this in package runtime, like we do for
+ // the type descriptors for predeclared types.
+ typ != types.ErrorType &&
+
+ // Exception: parameterized types may have been instantiated
+ // with new type arguments, so we don't assume they've been
+ // compiled before.
+ !typ.IsFullyInstantiated()
}
- // Only generate I.M wrappers for I in I's own package
- // but keep doing it for error.Error (was issue #29304)
- // and methods of instantiated interfaces.
- if rcvr.IsInterface() && rcvr != types.ErrorType &&
- rcvr.Sym() != nil && rcvr.Sym().Pkg != types.LocalPkg &&
- !rcvr.IsFullyInstantiated() {
+ if importedType(rcvr) || rcvr.IsPtr() && importedType(rcvr.Elem()) {
return lsym
}
@@ -1922,9 +1926,16 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy
ir.CurFunc = fn
typecheck.Stmts(fn.Body)
- // Inline calls within (*T).M wrappers. This is safe because we only
- // generate those wrappers within the same compilation unit as (T).M.
- // TODO(mdempsky): Investigate why we can't enable this more generally.
+ // TODO(mdempsky): Make this unconditional. The exporter now
+ // includes all of the inline bodies we need, and the "importedType"
+ // logic above now correctly suppresses compiling out-of-package
+ // types that we might not have inline bodies for. The only problem
+ // now is that the extra inlining can now introduce further new
+ // itabs, and gc.dumpdata's ad hoc compile loop doesn't handle this.
+ //
+ // CL 327871 will address this by writing itabs and generating
+ // wrappers as part of the loop, so we won't have to worry about
+ // "itabs changed after compile functions loop" errors anymore.
if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym() != nil {
inline.InlineCalls(fn)
}