// Copyright IBM Corp. 2014, 2026 // SPDX-License-Identifier: BUSL-1.1 package stackaddrs import ( "reflect" "github.com/hashicorp/terraform/internal/collections" ) // Referenceable is a type set containing all address types that can be // the target of an expression-based reference within a particular stack. type Referenceable interface { referenceableSigil() String() string } var _ Referenceable = Component{} var _ Referenceable = StackCall{} var _ Referenceable = InputVariable{} var _ Referenceable = LocalValue{} var _ Referenceable = ProviderConfigRef{} var _ Referenceable = TestOnlyGlobal{} var _ Referenceable = ContextualRef(0) // ReferenceableUniqueKey returns a unique key for a dynamically-typed // referenceable address. // // Since the type of the target isn't statically known, the resulting unique // key is not comparable with unique keys of the specific static types // that implement [Referenceable]. func ReferenceableUniqueKey(addr Referenceable) collections.UniqueKey[Referenceable] { // NOTE: This assumes that all distinct referenceable addresses have // distinct and unique string representations. return referenceableUniqueKey{ ty: reflect.TypeOf(addr), str: addr.String(), } } type referenceableUniqueKey struct { ty reflect.Type str string } // IsUniqueKey implements collections.UniqueKey. func (referenceableUniqueKey) IsUniqueKey(Referenceable) {} type ContextualRef rune const EachValue = ContextualRef('v') const EachKey = ContextualRef('k') const CountIndex = ContextualRef('i') const Self = ContextualRef('s') const TerraformApplying = ContextualRef('a') // String implements Referenceable. func (e ContextualRef) String() string { switch e { case EachKey: return "each.key" case EachValue: return "each.value" case CountIndex: return "count.index" case Self: return "self" case TerraformApplying: return "terraform.applying" default: // The four constants in this package are the only valid values of this type panic("invalid ContextualRef instance") } } // referenceableSigil implements Referenceable. func (e ContextualRef) referenceableSigil() {} // AbsReferenceable is a [Referenceable] combined with the stack it would // be resolved in. // // This type can be used only for [Referenceable] types that have stack-wide // scope. It's not appropriate for referenceable objects with more specific // scope, such as [ContextualRef], since describing those would require // information about which specific block they are to be resolved within. type AbsReferenceable struct { Stack StackInstance Item Referenceable } func (r AbsReferenceable) UniqueKey() collections.UniqueKey[AbsReferenceable] { return absReferenceableKey{ stackKey: r.Stack.UniqueKey(), itemKey: ReferenceableUniqueKey(r.Item), } } type absReferenceableKey struct { stackKey collections.UniqueKey[StackInstance] itemKey collections.UniqueKey[Referenceable] } // IsUniqueKey implements collections.UniqueKey. func (absReferenceableKey) IsUniqueKey(AbsReferenceable) { panic("unimplemented") }