6 "github.com/hashicorp/hcl2/hcl"
7 "github.com/zclconf/go-cty/cty"
9 "github.com/hashicorp/terraform/addrs"
10 "github.com/hashicorp/terraform/lang"
11 "github.com/hashicorp/terraform/tfdiags"
14 // EvalLocal is an EvalNode implementation that evaluates the
15 // expression for a local value and writes it into a transient part of
17 type EvalLocal struct {
22 func (n *EvalLocal) Eval(ctx EvalContext) (interface{}, error) {
23 var diags tfdiags.Diagnostics
25 // We ignore diags here because any problems we might find will be found
26 // again in EvaluateExpr below.
27 refs, _ := lang.ReferencesInExpr(n.Expr)
28 for _, ref := range refs {
29 if ref.Subject == n.Addr {
30 diags = diags.Append(&hcl.Diagnostic{
31 Severity: hcl.DiagError,
32 Summary: "Self-referencing local value",
33 Detail: fmt.Sprintf("Local value %s cannot use its own result as part of its expression.", n.Addr),
34 Subject: ref.SourceRange.ToHCL().Ptr(),
35 Context: n.Expr.Range().Ptr(),
39 if diags.HasErrors() {
40 return nil, diags.Err()
43 val, moreDiags := ctx.EvaluateExpr(n.Expr, cty.DynamicPseudoType, nil)
44 diags = diags.Append(moreDiags)
45 if moreDiags.HasErrors() {
46 return nil, diags.Err()
51 return nil, fmt.Errorf("cannot write local value to nil state")
54 state.SetLocalValue(n.Addr.Absolute(ctx.Path()), val)
59 // EvalDeleteLocal is an EvalNode implementation that deletes a Local value
60 // from the state. Locals aren't persisted, but we don't need to evaluate them
62 type EvalDeleteLocal struct {
66 func (n *EvalDeleteLocal) Eval(ctx EvalContext) (interface{}, error) {
72 state.RemoveLocalValue(n.Addr.Absolute(ctx.Path()))