Repository: opentofu/opentofu
File: internal/tofu/evaluate.go (Go)

Code before:
			stateMap[callInstance.Key] = instance
		}

		instance[output.Addr.OutputValue.Name] = val
	}

	// Get all changes that reside for this module call within our path.
	// The change contains the full addr, so we can key these with strings.
	changesMap := map[addrs.InstanceKey]map[string]*plans.OutputChangeSrc{}
	for _, change := range d.Evaluator.Changes.GetOutputChanges(d.ModulePath, addr) {
		_, callInstance := change.Addr.Module.CallInstance()
		instance, ok := changesMap[callInstance.Key]
		if !ok {
			instance = map[string]*plans.OutputChangeSrc{}
			changesMap[callInstance.Key] = instance
		}

		instance[change.Addr.OutputValue.Name] = change
	}

	// Build up all the module objects, creating a map of values for each
	// module instance.
	moduleInstances := map[addrs.InstanceKey]map[string]cty.Value{}

	// First, we need to determine which module instances actually exist.
	if d.Evaluator.InstanceExpander != nil {
		childModuleAddr := d.ModulePath.Module().Child(addr.Name)
		moduleInstanceAddrs := d.Evaluator.InstanceExpander.ExpandModule(childModuleAddr)

		for _, moduleInstanceAddr := range moduleInstanceAddrs {
			if len(moduleInstanceAddr) > 0 {
				lastStep := moduleInstanceAddr[len(moduleInstanceAddr)-1]
				key := lastStep.InstanceKey

				if _, exists := moduleInstances[key]; !exists {
					moduleInstances[key] = map[string]cty.Value{}
				}
			}
		}
	}

	// create a dummy object type for validation below
	unknownMap := map[string]cty.Type{}

	// the structure is based on the configuration, so iterate through all the
	// defined outputs, and add any instance state or changes we find.
	for _, cfg := range outputConfigs {
		// record the output names for validation
		unknownMap[cfg.Name] = cty.DynamicPseudoType

		// get all instance output for this path from the state

Review comment (suggestion):
Please check this [down below](https://github.com/KrishnaSindhur/opentofu/blob/d57435fd2b8e73808631c301daf164f891670bc0/internal/tofu/evaluate.go#L611).
This should be done only on non-validation phases, but the way it is done right now, it's done all the time.

Code after:
			stateMap[callInstance.Key] = instance
		}

		instance[output.Addr.OutputValue.Name] = val
	}

	// Get all changes that reside for this module call within our path.
	// The change contains the full addr, so we can key these with strings.
	changesMap := map[addrs.InstanceKey]map[string]*plans.OutputChangeSrc{}
	for _, change := range d.Evaluator.Changes.GetOutputChanges(d.ModulePath, addr) {
		_, callInstance := change.Addr.Module.CallInstance()
		instance, ok := changesMap[callInstance.Key]
		if !ok {
			instance = map[string]*plans.OutputChangeSrc{}
			changesMap[callInstance.Key] = instance
		}

		instance[change.Addr.OutputValue.Name] = change
	}

	// Build up all the module objects, creating a map of values for each
	// module instance.
	moduleInstances := map[addrs.InstanceKey]map[string]cty.Value{}

	// Pre-populate moduleInstances using InstanceExpander to handle modules with no outputs.
	// This ensures that expressions like length(module.foo) work correctly even when a module
	// has no output values defined, by consulting the expansion state to determine which
	// module instances exist based on count/for_each.
	// We only do this during non-validation operations (plan, apply, etc.) because during
	// validation, the InstanceExpander may not be fully populated yet.
	if d.Evaluator.InstanceExpander != nil && d.Evaluator.Operation != walkValidate {
		childModuleAddr := d.ModulePath.Module().Child(addr.Name)
		moduleInstanceAddrs := d.Evaluator.InstanceExpander.ExpandModule(childModuleAddr)

		for _, moduleInstanceAddr := range moduleInstanceAddrs {
			_, callInstance := moduleInstanceAddr.CallInstance()
			key := callInstance.Key
			if _, exists := moduleInstances[key]; !exists {
				moduleInstances[key] = map[string]cty.Value{}
			}
		}
	}

	// create a dummy object type for validation below
	unknownMap := map[string]cty.Type{}

	// the structure is based on the configuration, so iterate through all the
	// defined outputs, and add any instance state or changes we find.
	for _, cfg := range outputConfigs {
		// record the output names for validation
		unknownMap[cfg.Name] = cty.DynamicPseudoType