@@ -22,8 +22,11 @@ This document is maintained by Alan Donovan `adonovan@google.com`.
2222 1. [Struct Types](#struct-types)
2323 1. [Tuple Types](#tuple-types)
2424 1. [Function and Method Types](#function-and-method-types)
25+ 1. [Alias Types](#alias-types)
2526 1. [Named Types](#named-types)
2627 1. [Interface Types](#interface-types)
28+ 1. [TypeParam types](#typeparam-types)
29+ 1. [Union types](#union-types)
2730 1. [TypeAndValue](#typeandvalue)
28311 . [ Selections] ( #selections )
29321 . [ Ids] ( #ids )
@@ -103,9 +106,6 @@ type, or has an inappropriate type for its context; this is known as
103106_ type deduction_ .
104107Third, for every constant expression in the program, it determines the
105108value of that constant; this is known as _ constant evaluation_ .
106-
107-
108-
109109Superficially, it appears that these three processes could be done
110110sequentially, in the order above, but perhaps surprisingly, they must
111111be done together.
@@ -115,9 +115,6 @@ Conversely, the type of an expression may depend on the value of a
115115constant, since array types contain constants.
116116As a result, type deduction and constant evaluation must be done
117117together.
118-
119-
120-
121118As another example, we cannot resolve the identifier ` k ` in the composite
122119literal ` T{k: 0} ` until we know whether ` T ` is a struct type.
123120If it is, then ` k ` must be found among ` T ` 's fields.
@@ -264,7 +261,7 @@ Scope: package "cmd/hello" scope 0x820533590 {
264261
265262A package's ` Path ` , such as ` "encoding/json" ` , is the string
266263by which import declarations identify it.
267- It is unique within a ` $GOPATH ` workspace,
264+ It is unique within a workspace,
268265and for published packages it must be globally unique.
269266
270267
@@ -282,7 +279,7 @@ which provides access to all the named entities or
282279[ _ objects_ ] ( #objects ) declared at package level.
283280` Imports ` returns the set of packages directly imported by this
284281one, and may be useful for computing dependencies
285- ([ Initialization Order] ( #initialization-order ) ).
282+ (see [ Initialization Order] ( #initialization-order ) ).
286283
287284
288285
@@ -336,12 +333,8 @@ offset, though usually we just call its `String` method:
336333 fmt.Println(fset.Position(obj.Pos())) // "hello.go:10:6"
337334
338335
339- Not all objects carry position information.
340- Since the file format for compiler export data ([ Imports] ( #imports ) )
341- does not record position information, calling ` Pos ` on an object
342- imported from such a file returns zero, also known as
343- ` token.NoPos ` .
344-
336+ Objects for predeclared functions and types such as ` len ` and ` int `
337+ do not have a valid (non-zero) position: ` !obj.Pos().IsValid() ` .
345338
346339
347340There are eight kinds of objects in the Go type checker.
@@ -367,14 +360,22 @@ possible types, and we commonly use a type switch to distinguish them.
367360 | *Nil // predeclared nil
368361
369362
370- ` Object ` s are canonical.
371- That is, two ` Object ` s ` x ` and ` y ` denote the same
372- entity if and only if ` x==y ` .
363+
364+ Objects are canonical.
365+ That is, two Objects ` x ` and ` y ` denote the same entity if and only if ` x==y ` .
366+ (This is generally true but beware that parameterized types complicate matters; see
367+ https://github.com/golang/exp/tree/master/typeparams/example for details.)
368+
373369Object identity is significant, and objects are routinely compared by
374370the addresses of the underlying pointers.
375- Although a package-level object is uniquely identified by its name
376- and enclosing package, for other objects there is no simple way to
377- obtain a string that uniquely identifies it.
371+ A package-level object (func/var/const/type) can be uniquely
372+ identified by its name and enclosing package.
373+ The [ ` golang.org/x/tools/go/types/objectpath ` ] ( https://pkg.go.dev/golang.org/x/tools/go/types/objectpath )
374+ package defines a naming scheme for objects that are
375+ [ exported] ( #imports ) from their package or are unexported but form part of the
376+ type of an exported object.
377+ But for most objects, including all function-local objects,
378+ there is no simple way to obtain a string that uniquely identifies it.
378379
379380
380381
@@ -409,18 +410,20 @@ And some kinds of objects have methods in addition to those required by the
409410
410411
411412` (*Func).Scope ` returns the [ lexical block] ( #scopes )
412- containing the function's parameters, results,
413+ containing the function's type parameters, parameters, results,
413414and other local declarations.
414415` (*Var).IsField ` distinguishes struct fields from ordinary
415416variables, and ` (*Var).Anonymous ` discriminates named fields like
416417the one in ` struct{T T} ` from anonymous fields like the one in ` struct{T} ` .
417418` (*Const).Val ` returns the value of a named [ constant] ( #constants ) .
418419
419420
420- ` (*TypeName).IsAlias ` , introduced in Go 1.9, reports whether the
421- type name is simply an alias for a type (as in ` type I = int ` ),
422- as opposed to a definition of a [ ` Named ` ] ( #named-types ) type, as
423- in ` type Celsius float64 ` .
421+ ` (*TypeName).IsAlias ` reports whether the type name declares an alias
422+ for an existing type (as in ` type I = int ` ), as opposed to defining a new
423+ [ ` Named ` ] ( #named-types ) type, as in ` type Celsius float64 ` .
424+ (Most ` TypeName ` s for which ` IsAlias() ` is true have a ` Type() ` of
425+ type ` *types.Alias ` , but ` IsAlias() ` is also true for the predeclared
426+ ` byte ` and ` rune ` types, which are aliases for ` uint8 ` and ` int32 ` .)
424427
425428
426429` (*PkgName).Imported ` returns the package (for instance,
@@ -436,9 +439,9 @@ We'll look more closely at this in [Imports](#imports).
436439All relationships between the syntax trees (` ast.Node ` s) and type
437440checker data structures such as ` Object ` s and ` Type ` s are
438441stored in mappings outside the syntax tree itself.
439- Be aware that the ` go/ast ` package also defines a type called
440- ` Object ` that resembles---and predates---the type checker's
441- ` Object ` , and that ` ast.Object ` s are held directly by
442+ Be aware that the ` go/ast ` package also defines an older deprecated
443+ type called ` Object ` that resembles---and predates---the type
444+ checker's ` Object ` , and that ` ast.Object ` s are held directly by
442445identifiers in the AST.
443446They are created by the parser, which has a necessarily limited view
444447of the package, so the information they represent is at best partial and
@@ -974,7 +977,7 @@ Here is the interface:
974977 }
975978
976979
977- And here are the eleven concrete types that satisfy it:
980+ And here are the 14 concrete types that satisfy it:
978981
979982
980983 Type = *Basic
@@ -986,12 +989,17 @@ And here are the eleven concrete types that satisfy it:
986989 | *Struct
987990 | *Tuple
988991 | *Signature
992+ | *Alias
989993 | *Named
990994 | *Interface
995+ | *Union
996+ | *TypeParam
991997
992998
993999With the exception of ` Named ` types, instances of ` Type ` are
9941000not canonical.
1001+ (Even for ` Named ` types, parameterized types complicate matters; see
1002+ https://github.com/golang/exp/tree/master/typeparams/example .)
9951003That is, it is usually a mistake to compare types using ` t1==t2 `
9961004since this equivalence is not the same as the
9971005[ type identity relation] ( https://golang.org/ref/spec#Type_identity )
@@ -1052,8 +1060,8 @@ basic type this is.
10521060The kinds ` Bool ` , ` String ` , ` Int16 ` , and so on,
10531061represent the corresponding predeclared boolean, string, or numeric
10541062types.
1055- There are two synonyms : ` Byte ` is equivalent to ` Uint8 `
1056- and ` Rune ` is equivalent to ` Int32 ` .
1063+ There are two aliases : ` Byte ` is an alias for ` Uint8 `
1064+ and ` Rune ` is an alias for ` Int32 ` .
10571065The kind ` UnsafePointer ` represents ` unsafe.Pointer ` .
10581066The kinds ` UntypedBool ` , ` UntypedInt ` and so on represent
10591067the six kinds of "untyped" constant types: boolean, integer, rune,
@@ -1082,21 +1090,20 @@ modify it.
10821090
10831091
10841092A few minor subtleties:
1085- According to the Go spec, pre-declared types such as ` int ` are
1086- named types for the purposes of assignability, even though the type
1087- checker does not represent them using ` Named ` .
1088- And ` unsafe.Pointer ` is a pointer type for the purpose of
1089- determining whether the receiver type of a method is legal, even
1090- though the type checker does not represent it using ` Pointer ` .
1091-
10921093
1094+ - According to the Go spec, pre-declared types such as ` int ` are
1095+ named types for the purposes of assignability, even though the type
1096+ checker does not represent them using ` Named ` .
10931097
1094- The "untyped" types are usually only ascribed to constant expressions,
1095- but there is one exception.
1096- A comparison ` x==y ` has type "untyped bool", so the result of
1097- this expression may be assigned to a variable of type ` bool ` or
1098- any other named boolean type.
1098+ - ` unsafe.Pointer ` is a pointer type for the purpose of
1099+ determining whether the receiver type of a method is legal, even
1100+ though the type checker does not represent it using ` Pointer ` .
10991101
1102+ - The "untyped" types are usually only ascribed to constant expressions,
1103+ but there is one exception.
1104+ A comparison ` x==y ` has type "untyped bool", so the result of
1105+ this expression may be assigned to a variable of type ` bool ` or
1106+ any other named boolean type.
11001107
11011108
11021109## Simple Composite Types
@@ -1262,21 +1269,73 @@ These types are recorded during type checking for later use
12621269
12631270
12641271
1265- ## Named Types
1272+ ## Alias Types
1273+
1274+ Type declarations come in two forms, aliases and defined types.
12661275
1276+ Aliases, though introduced only in Go 1.9 and not very common, are
1277+ simplest, so we'll present them first and explain defined types in
1278+ the next section ("Named Types").
12671279
1268- Type declarations come in two forms.
1269- The simplest kind, introduced in Go 1.9,
1270- merely declares a (possibly alternative) name for an existing type.
1271- Type names used in this way are informally called _ type aliases_ .
1272- For example, this declaration lets you use the type
1273- ` Dictionary ` as an alias for ` map[string]string ` :
1280+ An alias type declaration declares an alternative name for an existing
1281+ type. For example, this declaration lets you use the type ` Dictionary `
1282+ as a synonym for ` map[string]string ` :
12741283
12751284 type Dictionary = map[string]string
12761285
1277- The declaration creates a ` TypeName ` object for ` Dictionary ` . The
1278- object's ` IsAlias ` method returns true, and its ` Type ` method returns
1279- a ` Map ` type that represents ` map[string]string ` .
1286+ The declaration creates a ` TypeName ` object for ` Dictionary ` .
1287+ The object's ` IsAlias ` method returns true,
1288+ and its ` Type ` method returns an ` Alias ` :
1289+
1290+ type Alias struct{ ... }
1291+ func (a *Alias) Obj() *TypeName
1292+ func (a *Alias) Origin() *Alias
1293+ func (a *Alias) Rhs() Type
1294+ func (a *Alias) SetTypeParams(tparams []*TypeParam)
1295+ func (a *Alias) TypeArgs() *TypeList
1296+ func (a *Alias) TypeParams() *TypeParamList
1297+
1298+ The type on the right-hand side of an alias declaration,
1299+ such as ` map[string]string ` in the example above,
1300+ can be accessed using the ` Rhs() ` method.
1301+ The ` types.Unalias(t) ` helper function recursively applies ` Rhs ` ,
1302+ removing all ` Alias ` types from the operand t and returning the
1303+ outermost non-alias type.
1304+
1305+ The ` Obj ` method returns the declaring ` TypeName ` object, such as
1306+ ` Dictionary ` ; it provides the name, position, and other properties of
1307+ the declaration. Conversely, the ` TypeName ` object's ` Type ` method
1308+ returns the ` Alias ` type.
1309+
1310+ Starting with Go 1.24, alias types may have type parameters.
1311+ For example, this declaration creates an Alias type with
1312+ a type parameter:
1313+
1314+ type Set[T comparable] = map[T]bool
1315+
1316+ Each instantiation such as ` Set[string] ` is identical to the
1317+ corresponding instantiation of the alias' right-hand side type, such
1318+ as ` map[string]bool ` .
1319+
1320+ The remaining methods--Origin, SetTypeParams, TypeArgs,
1321+ TypeParams--are all concerned with type parameters. For now, see
1322+ https://github.com/golang/exp/tree/master/typeparams/example .
1323+
1324+ Prior to Go 1.22, aliases were not materialized as ` Alias ` types:
1325+ each reference to an alias type such as ` Dictionary ` would be
1326+ immediately replaced by its right-hand side type, leaving no
1327+ indication in the output of the type checker that an alias was
1328+ present.
1329+ By materializing alias types, optionally in Go 1.22 and by default
1330+ starting in Go 1.23, we can more faithfully record the structure of
1331+ the program, which improves the quality of diagnostic messages and
1332+ enables certain analyses and code transformations. And, crucially, it
1333+ enabled the addition of parameterized aliases in Go 1.24.)
1334+
1335+
1336+
1337+ ## Named Types
1338+
12801339
12811340
12821341The second form of type declaration, and the only kind prior to Go
@@ -1292,10 +1351,11 @@ from any other type, including `float64`. The declaration binds the
12921351
12931352Since Go 1.9, the Go language specification has used the term _ defined
12941353types_ instead of named types;
1295- the essential property of a defined type is not that it has a name,
1354+ the essential property of a defined type is not that it has a name
1355+ (aliases and type parameters also have names)
12961356but that it is a distinct type with its own method set.
12971357However, the type checker API predates that
1298- change and instead calls defined types "named" types.
1358+ change and instead calls defined types ` Named ` types.
12991359
13001360 type Named struct{ ... }
13011361 func (*Named) NumMethods() int
@@ -1321,8 +1381,8 @@ methods than this list. We'll return to this in [Method Sets](#method-sets).
13211381
13221382
13231383Every ` Type ` has an ` Underlying ` method, but for all of them
1324- except ` *Named ` , it is simply the identity function.
1325- For a named type, ` Underlying ` returns its underlying type, which
1384+ except ` *Named ` and ` *Alias ` , it is simply the identity function.
1385+ For a named or alias type, ` Underlying ` returns its underlying type, which
13261386is always an unnamed type.
13271387Thus ` Underlying ` returns ` int ` for both ` T ` and
13281388` U ` below.
@@ -1335,14 +1395,13 @@ Thus `Underlying` returns `int` for both `T` and
13351395Clients of the type checker often use type assertions or type switches
13361396with a ` Type ` operand.
13371397When doing so, it is often necessary to switch on the type that
1338- _ underlies_ the type of interest, and failure to do so may be a
1339- bug.
1398+ underlies the type of interest, and failure to do so may be a bug.
13401399
13411400This is a common pattern:
13421401
13431402
13441403 // handle types of composite literal
1345- switch u := t.Underlying().(type) {
1404+ switch u := t.Underlying().(type) { // remove any *Named and *Alias types
13461405 case *Struct: // ...
13471406 case *Map: // ...
13481407 case *Array, *Slice: // ...
@@ -1423,6 +1482,36 @@ interface `v`, then the type assertion is not legal, as in this example:
14231482
14241483
14251484
1485+
1486+ ## TypeParam types
1487+
1488+
1489+ A ` TypeParam ` is the type of a type parameter.
1490+ For example, the type of the variable ` x ` in the ` identity ` function
1491+ below is a ` TypeParam ` :
1492+
1493+ func identity[T any](x T) T { return x }
1494+
1495+ As with ` Alias ` and ` Named ` types, each ` TypeParam ` has an associated
1496+ ` TypeName ` object that provides its name, position, and other
1497+ properties of the declaration.
1498+
1499+ See https://github.com/golang/exp/tree/master/typeparams/example
1500+ for a more thorough treatment of parameterized types.
1501+
1502+
1503+
1504+
1505+ ## Union types
1506+
1507+ A ` Union ` is the type of type-parameter constraint of the form `func
1508+ f[ T int | string] `.
1509+
1510+ See https://github.com/golang/exp/tree/master/typeparams/example
1511+ for a more thorough treatment of parameterized types.
1512+
1513+
1514+
14261515## TypeAndValue
14271516
14281517
@@ -2264,10 +2353,9 @@ compiler file formats, and so on.
22642353 }
22652354
22662355
2267- Most of our examples used the simplest ` Importer ` implementation,
2356+ Most of our examples used the trivial ` Importer ` implementation,
22682357` importer.Default() ` , provided by the ` go/importer ` package.
2269- This importer looks in ` $GOROOT ` and ` $GOPATH ` for ` .a `
2270- files written by the compiler (` gc ` or ` gccgo ` )
2358+ This importer looks for ` .a ` files written by the compiler
22712359that was used to build the program.
22722360In addition to object code, these files contain _ export data_ ,
22732361that is, a description of all the objects declared by the package, and
@@ -2279,13 +2367,11 @@ transitive dependency.
22792367
22802368
22812369Compiler export data is compact and efficient to locate, load, and
2282- parse, but it has several shortcomings.
2283- First, it does not contain position information for imported
2284- objects, reducing the quality of certain diagnostic messages.
2285- Second, it does not contain complete syntax trees nor semantic information
2286- about the contents of function bodies, so it is not suitable for
2287- interprocedural analyses.
2288- Third, compiler object data may be stale. Nothing detects or ensures
2370+ parse, but it has some shortcomings.
2371+ First, it does not contain complete syntax trees nor semantic
2372+ information about the bodies of all functions, so it is not
2373+ suitable for interprocedural analyses.
2374+ Second, compiler object data may be stale. Nothing detects or ensures
22892375that the object files are more recent than the source files from which
22902376they were derived.
22912377Generally, object data for standard packages is likely to be
0 commit comments