// Copyright IBM Corp. 2014, 2026 // SPDX-License-Identifier: BUSL-1.1 package namedvals import ( "sync" "github.com/zclconf/go-cty/cty" "github.com/hashicorp/terraform/internal/addrs" ) // State is the main type in this package, representing the current state of // evaluation that can be mutated as Terraform Core visits different graph // nodes and then queried to find values that were already resolved earlier // in the graph walk. // // Instances of this type are concurrency-safe so callers do not need to // implement their own locking when reading and writing from named value // state. type State struct { mu sync.Mutex variables inputVariableValues locals localValues outputs outputValues } func NewState() *State { return &State{ variables: newValues[addrs.InputVariable, addrs.AbsInputVariableInstance](), locals: newValues[addrs.LocalValue, addrs.AbsLocalValue](), outputs: newValues[addrs.OutputValue, addrs.AbsOutputValue](), } } func (s *State) SetInputVariableValue(addr addrs.AbsInputVariableInstance, val cty.Value) { s.mu.Lock() s.variables.SetExactResult(addr, val) s.mu.Unlock() } func (s *State) GetInputVariableValue(addr addrs.AbsInputVariableInstance) cty.Value { s.mu.Lock() defer s.mu.Unlock() return s.variables.GetExactResult(addr) } func (s *State) HasInputVariableValue(addr addrs.AbsInputVariableInstance) bool { s.mu.Lock() defer s.mu.Unlock() return s.variables.HasExactResult(addr) } func (s *State) SetInputVariablePlaceholder(addr addrs.InPartialExpandedModule[addrs.InputVariable], val cty.Value) { s.mu.Lock() s.variables.SetPlaceholderResult(addr, val) s.mu.Unlock() } func (s *State) GetInputVariablePlaceholder(addr addrs.InPartialExpandedModule[addrs.InputVariable]) cty.Value { s.mu.Lock() defer s.mu.Unlock() return s.variables.GetPlaceholderResult(addr) } func (s *State) SetLocalValue(addr addrs.AbsLocalValue, val cty.Value) { s.mu.Lock() s.locals.SetExactResult(addr, val) s.mu.Unlock() } func (s *State) GetLocalValue(addr addrs.AbsLocalValue) cty.Value { s.mu.Lock() defer s.mu.Unlock() return s.locals.GetExactResult(addr) } func (s *State) HasLocalValue(addr addrs.AbsLocalValue) bool { s.mu.Lock() defer s.mu.Unlock() return s.locals.HasExactResult(addr) } func (s *State) SetLocalValuePlaceholder(addr addrs.InPartialExpandedModule[addrs.LocalValue], val cty.Value) { s.mu.Lock() s.locals.SetPlaceholderResult(addr, val) s.mu.Unlock() } func (s *State) GetLocalValuePlaceholder(addr addrs.InPartialExpandedModule[addrs.LocalValue]) cty.Value { s.mu.Lock() defer s.mu.Unlock() return s.locals.GetPlaceholderResult(addr) } func (s *State) SetOutputValue(addr addrs.AbsOutputValue, val cty.Value) { s.mu.Lock() s.outputs.SetExactResult(addr, val) s.mu.Unlock() } func (s *State) GetOutputValue(addr addrs.AbsOutputValue) cty.Value { s.mu.Lock() defer s.mu.Unlock() return s.outputs.GetExactResult(addr) } func (s *State) HasOutputValue(addr addrs.AbsOutputValue) bool { s.mu.Lock() defer s.mu.Unlock() return s.outputs.HasExactResult(addr) } func (s *State) SetOutputValuePlaceholder(addr addrs.InPartialExpandedModule[addrs.OutputValue], val cty.Value) { s.mu.Lock() s.outputs.SetPlaceholderResult(addr, val) s.mu.Unlock() } func (s *State) GetOutputValuePlaceholder(addr addrs.InPartialExpandedModule[addrs.OutputValue]) cty.Value { s.mu.Lock() defer s.mu.Unlock() return s.outputs.GetPlaceholderResult(addr) }