aboutsummaryrefslogtreecommitdiff
path: root/src/encoding
diff options
context:
space:
mode:
authorMark Freeman <mark@golang.org>2025-08-20 17:30:26 -0400
committerGopher Robot <gobot@golang.org>2025-10-16 11:21:47 -0700
commit1099436f1b63560a0587dd4c5814edd13f80e577 (patch)
tree26704e7d8cfdb5f2d39ef4d127a29c94e97bc564 /src/encoding
parent41f5659347f9498ce81911032bb46537d923bdd7 (diff)
downloadgo-1099436f1b63560a0587dd4c5814edd13f80e577.tar.xz
go/types, types2: change and enforce lifecycle of Named.fromRHS and Named.underlying fields
A type definition or alias declaration consists of a type name (LHS) which is bound to a type expression (RHS) by the declaration. This CL consistently uses the fromRHS fields of Named and Alias types to represent that RHS type expression, and sets Named.underlying and Alias.actual only once those types have been computed. Currently, Named types use Named.underlying for some of this functionality, which makes the code difficult to understand. Operations which used Named.underlying now use Named.fromRHS. For example, in: type A = B type B = int A.fromRHS is B (Alias) and B.fromRHS is int (Basic). Meanwhile, in: type A B type B int A.underlying is B (Named) and B.underlying is int (Basic) initially. Note that despite A.underlying pointing to B, B is not the underlying type of A (it is int). At some point during type checking, A walks through the chain A.underlying -> B.underlying -> int and sets A.underlying to int. While this approach works, it introduces some problems: 1. Whether A.underlying refers to the underlying type (int) or not (B) depends on when the field is accessed. 2. There is no convenient mechanism to check if the underlying type of B has been deduced. One can check if B.underlying is a named type, but since B.underlying is already B's underlying type (int), it's still ambiguous. Operations derived from Named.underlying share similar problems. For example, Named.expandUnderlying() (which substitutes type arguments) returns an instantiated named type whose Named.underlying also may or may not refer to its underlying type. With this change, Named.underlying is nil as long as it is unknown, and non-nil and not a named type once it is known. Additional assertions are added to enforce that: 1. Named.underlying is not set until Named has been resolved. 2. Named is not resolved until Named.fromRHS is populated, unless it is given explicit permission. This permission is briefly given while type-checking declarations of named types to account for cycles of alias types represented as TypeNames. It is also given to named types created through NewNamed for backward compatibility. This permission is revoked when SetUnderlying is called. Accessors of Named.underlying are responsible for first resolving the named type, unless they are in a context where they know the type to already be resolved. This change also exposed a bug in validType wherein the underlying type for struct types containing invalid types did not have their underlying type set to invalid (see #75194). This bug was exploited by a test in x/tools, which has been disabled for Go 1.26 (via CL 700395). Other minor adjustments are made for instantiated and loaded types. Instantiated types have no RHS as they are not declared, and loaded types set their RHS to the underlying from export data directly. Minor simplifications are also made throughout. Fixes #75194 Change-Id: I72644d7329c996eb1e67514063fe51c3ae06c38d Reviewed-on: https://go-review.googlesource.com/c/go/+/695977 Auto-Submit: Mark Freeman <markfreeman@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Robert Griesemer <gri@google.com>
Diffstat (limited to 'src/encoding')
0 files changed, 0 insertions, 0 deletions