// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
// Source: ../../cmd/compile/internal/types2/alias.go

// Copyright 2023 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.

package types

import "fmt"

// An Alias represents an alias type.
// Whether or not Alias types are created is controlled by the
// gotypesalias setting with the GODEBUG environment variable.
// For gotypesalias=1, alias declarations produce an Alias type.
// Otherwise, the alias information is only in the type name,
// which points directly to the actual (aliased) type.
type Alias struct {
	obj     *TypeName      // corresponding declared alias object
	tparams *TypeParamList // type parameters, or nil
	fromRHS Type           // RHS of type alias declaration; may be an alias
	actual  Type           // actual (aliased) type; never an alias
}

// NewAlias creates a new Alias type with the given type name and rhs.
// rhs must not be nil.
func NewAlias(obj *TypeName, rhs Type) *Alias {
	alias := (*Checker)(nil).newAlias(obj, rhs)
	// Ensure that alias.actual is set (#65455).
	alias.cleanup()
	return alias
}

func (a *Alias) Obj() *TypeName   { return a.obj }
func (a *Alias) Underlying() Type { return unalias(a).Underlying() }
func (a *Alias) String() string   { return TypeString(a, nil) }

// Rhs returns the type R on the right-hand side of an alias
// declaration "type A = R", which may be another alias.
func (a *Alias) Rhs() Type { return a.fromRHS }

// Unalias returns t if it is not an alias type;
// otherwise it follows t's alias chain until it
// reaches a non-alias type which is then returned.
// Consequently, the result is never an alias type.
func Unalias(t Type) Type {
	if a0, _ := t.(*Alias); a0 != nil {
		return unalias(a0)
	}
	return t
}

func unalias(a0 *Alias) Type {
	if a0.actual != nil {
		return a0.actual
	}
	var t Type
	for a := a0; a != nil; a, _ = t.(*Alias) {
		t = a.fromRHS
	}
	if t == nil {
		panic(fmt.Sprintf("non-terminated alias %s", a0.obj.name))
	}

	// Memoize the type only if valid.
	// In the presence of unfinished cyclic declarations, Unalias
	// would otherwise latch the invalid value (#66704).
	// TODO(adonovan): rethink, along with checker.typeDecl's use
	// of Invalid to mark unfinished aliases.
	if t != Typ[Invalid] {
		a0.actual = t
	}

	return t
}

// asNamed returns t as *Named if that is t's
// actual type. It returns nil otherwise.
func asNamed(t Type) *Named {
	n, _ := Unalias(t).(*Named)
	return n
}

// newAlias creates a new Alias type with the given type name and rhs.
// rhs must not be nil.
func (check *Checker) newAlias(obj *TypeName, rhs Type) *Alias {
	assert(rhs != nil)
	a := &Alias{obj, nil, rhs, nil}
	if obj.typ == nil {
		obj.typ = a
	}

	// Ensure that a.actual is set at the end of type checking.
	if check != nil {
		check.needsCleanup(a)
	}

	return a
}

func (a *Alias) cleanup() {
	// Ensure a.actual is set before types are published,
	// so Unalias is a pure "getter", not a "setter".
	actual := Unalias(a)

	if actual == Typ[Invalid] {
		// We don't set a.actual to Typ[Invalid] during type checking,
		// as it may indicate that the RHS is not fully set up.
		a.actual = actual
	}
}
