// Copyright 2024 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. //go:build go1.22 // +build go1.22 package aliases import ( "go/ast" "go/parser" "go/token" "go/types" ) // Alias is an alias of types.Alias. type Alias = types.Alias // Rhs returns the type on the right-hand side of the alias declaration. func Rhs(alias *Alias) types.Type { if alias, ok := any(alias).(interface{ Rhs() types.Type }); ok { return alias.Rhs() // go1.23+ } // go1.22's Alias didn't have the Rhs method, // so Unalias is the best we can do. return Unalias(alias) } // TypeParams returns the type parameter list of the alias. func TypeParams(alias *Alias) *types.TypeParamList { if alias, ok := any(alias).(interface{ TypeParams() *types.TypeParamList }); ok { return alias.TypeParams() // go1.23+ } return nil } // SetTypeParams sets the type parameters of the alias type. func SetTypeParams(alias *Alias, tparams []*types.TypeParam) { if alias, ok := any(alias).(interface { SetTypeParams(tparams []*types.TypeParam) }); ok { alias.SetTypeParams(tparams) // go1.23+ } else if len(tparams) > 0 { panic("cannot set type parameters of an Alias type in go1.22") } } // TypeArgs returns the type arguments used to instantiate the Alias type. func TypeArgs(alias *Alias) *types.TypeList { if alias, ok := any(alias).(interface{ TypeArgs() *types.TypeList }); ok { return alias.TypeArgs() // go1.23+ } return nil // empty (go1.22) } // Origin returns the generic Alias type of which alias is an instance. // If alias is not an instance of a generic alias, Origin returns alias. func Origin(alias *Alias) *Alias { if alias, ok := any(alias).(interface{ Origin() *types.Alias }); ok { return alias.Origin() // go1.23+ } return alias // not an instance of a generic alias (go1.22) } // Unalias is a wrapper of types.Unalias. func Unalias(t types.Type) types.Type { return types.Unalias(t) } // newAlias is an internal alias around types.NewAlias. // Direct usage is discouraged as the moment. // Try to use NewAlias instead. func newAlias(tname *types.TypeName, rhs types.Type) *Alias { a := types.NewAlias(tname, rhs) // TODO(go.dev/issue/65455): Remove kludgy workaround to set a.actual as a side-effect. Unalias(a) return a } // Enabled reports whether [NewAlias] should create [types.Alias] types. // // This function is expensive! Call it sparingly. func Enabled() bool { // The only reliable way to compute the answer is to invoke go/types. // We don't parse the GODEBUG environment variable, because // (a) it's tricky to do so in a manner that is consistent // with the godebug package; in particular, a simple // substring check is not good enough. The value is a // rightmost-wins list of options. But more importantly: // (b) it is impossible to detect changes to the effective // setting caused by os.Setenv("GODEBUG"), as happens in // many tests. Therefore any attempt to cache the result // is just incorrect. fset := token.NewFileSet() f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", 0) pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil) _, enabled := pkg.Scope().Lookup("A").Type().(*types.Alias) return enabled }