]> Cypherpunks repositories - gostls13.git/commit
go/types, types2: ensure that named types never expand infinitely
authorRobert Findley <rfindley@google.com>
Sun, 8 May 2022 01:22:17 +0000 (21:22 -0400)
committerRobert Findley <rfindley@google.com>
Mon, 6 Jun 2022 15:42:19 +0000 (15:42 +0000)
commit47e34ca533b118bd47061b15fc7918563f4837a7
tree0f0d527a7f0ef12377a5dc11d8549fd2a9268da3
parent02e69cfa9695f17902ff1806205c26a0d02a684f
go/types, types2: ensure that named types never expand infinitely

During type-checking, newly created instances share a type checking
Context which de-duplicates identical instances. However, when
unexpanded types escape the type-checking pass or are created via calls
to Instantiate, they lack this shared context. As reported in #52728,
this may lead to infinitely many identical but distinct types that are
reachable via the API.

This CL introduces a new invariant that ensures we don't create such
infinitely expanding chains: instances created during expansion share a
context with the type that led to their creation. During expansion, the
expanding type passes its Context to any newly created instances.

This ensures that cycles will eventually terminate with a previously
seen instance. For example, if we have an instantiation chain
T1[P]->T2[P]->T3[P]->T1[P], by virtue of this Context passing the
expansion of T3[P] will find the instantiation T1[P].

In general, storing a Context in a Named type could lead to pinning
types in memory unnecessarily, but in this case the Context pins only
those types that are reachable from the original instance. This seems
like a reasonable compromise between lazy and eager expansion.

Our treatment of Context was a little haphazard: Checker.bestContext
made it easy to get a context at any point, but made it harder to reason
about which context is being used. To fix this, replace bestContext with
Checker.context, which returns the type-checking context and panics on a
nil receiver. Update all call-sites to verify that the Checker is
non-nil when context is called.

Also make it a panic to call subst with a nil context. Instead, update
subst to explicitly accept a local (=instance) context along with a
global context, and require that one of them is non-nil. Thread this
through to the call to Checker.instance, and handle context updating
there.

Fixes #52728

Change-Id: Ib7f26eb8c406290325bc3212fda25421a37a1e8e
Reviewed-on: https://go-review.googlesource.com/c/go/+/404885
Reviewed-by: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
18 files changed:
src/cmd/compile/internal/types2/call.go
src/cmd/compile/internal/types2/infer.go
src/cmd/compile/internal/types2/instantiate.go
src/cmd/compile/internal/types2/named.go
src/cmd/compile/internal/types2/named_test.go
src/cmd/compile/internal/types2/predicates.go
src/cmd/compile/internal/types2/signature.go
src/cmd/compile/internal/types2/subst.go
src/cmd/compile/internal/types2/typexpr.go
src/go/types/call.go
src/go/types/infer.go
src/go/types/instantiate.go
src/go/types/named.go
src/go/types/named_test.go
src/go/types/predicates.go
src/go/types/signature.go
src/go/types/subst.go
src/go/types/typexpr.go