1 // Copyright 2024 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 5 package aliases
6 7 import (
8 "go/ast"
9 "go/parser"
10 "go/token"
11 "go/types"
12 )
13 14 // Rhs returns the type on the right-hand side of the alias declaration.
15 func Rhs(alias *types.Alias) types.Type {
16 if alias, ok := any(alias).(interface{ Rhs() types.Type }); ok {
17 return alias.Rhs() // go1.23+
18 }
19 20 // go1.22's Alias didn't have the Rhs method,
21 // so Unalias is the best we can do.
22 return types.Unalias(alias)
23 }
24 25 // TypeParams returns the type parameter list of the alias.
26 func TypeParams(alias *types.Alias) *types.TypeParamList {
27 if alias, ok := any(alias).(interface{ TypeParams() *types.TypeParamList }); ok {
28 return alias.TypeParams() // go1.23+
29 }
30 return nil
31 }
32 33 // SetTypeParams sets the type parameters of the alias type.
34 func SetTypeParams(alias *types.Alias, tparams []*types.TypeParam) {
35 if alias, ok := any(alias).(interface {
36 SetTypeParams(tparams []*types.TypeParam)
37 }); ok {
38 alias.SetTypeParams(tparams) // go1.23+
39 } else if len(tparams) > 0 {
40 panic("cannot set type parameters of an Alias type in go1.22")
41 }
42 }
43 44 // TypeArgs returns the type arguments used to instantiate the Alias type.
45 func TypeArgs(alias *types.Alias) *types.TypeList {
46 if alias, ok := any(alias).(interface{ TypeArgs() *types.TypeList }); ok {
47 return alias.TypeArgs() // go1.23+
48 }
49 return nil // empty (go1.22)
50 }
51 52 // Origin returns the generic Alias type of which alias is an instance.
53 // If alias is not an instance of a generic alias, Origin returns alias.
54 func Origin(alias *types.Alias) *types.Alias {
55 if alias, ok := any(alias).(interface{ Origin() *types.Alias }); ok {
56 return alias.Origin() // go1.23+
57 }
58 return alias // not an instance of a generic alias (go1.22)
59 }
60 61 // Enabled reports whether [NewAlias] should create [types.Alias] types.
62 //
63 // This function is expensive! Call it sparingly.
64 func Enabled() bool {
65 // The only reliable way to compute the answer is to invoke go/types.
66 // We don't parse the GODEBUG environment variable, because
67 // (a) it's tricky to do so in a manner that is consistent
68 // with the godebug package; in particular, a simple
69 // substring check is not good enough. The value is a
70 // rightmost-wins list of options. But more importantly:
71 // (b) it is impossible to detect changes to the effective
72 // setting caused by os.Setenv("GODEBUG"), as happens in
73 // many tests. Therefore any attempt to cache the result
74 // is just incorrect.
75 fset := token.NewFileSet()
76 f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", parser.SkipObjectResolution)
77 pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil)
78 _, enabled := pkg.Scope().Lookup("A").Type().(*types.Alias)
79 return enabled
80 }
81