aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go')
-rw-r--r--vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go456
1 files changed, 311 insertions, 145 deletions
diff --git a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go
index cfc7cd9..26819a2 100644
--- a/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go
+++ b/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go
@@ -2,6 +2,7 @@ package hclsyntax
2 2
3import ( 3import (
4 "fmt" 4 "fmt"
5 "sync"
5 6
6 "github.com/hashicorp/hcl2/hcl" 7 "github.com/hashicorp/hcl2/hcl"
7 "github.com/zclconf/go-cty/cty" 8 "github.com/zclconf/go-cty/cty"
@@ -104,7 +105,9 @@ func (e *ScopeTraversalExpr) walkChildNodes(w internalWalkFunc) {
104} 105}
105 106
106func (e *ScopeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 107func (e *ScopeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
107 return e.Traversal.TraverseAbs(ctx) 108 val, diags := e.Traversal.TraverseAbs(ctx)
109 setDiagEvalContext(diags, e, ctx)
110 return val, diags
108} 111}
109 112
110func (e *ScopeTraversalExpr) Range() hcl.Range { 113func (e *ScopeTraversalExpr) Range() hcl.Range {
@@ -129,12 +132,13 @@ type RelativeTraversalExpr struct {
129} 132}
130 133
131func (e *RelativeTraversalExpr) walkChildNodes(w internalWalkFunc) { 134func (e *RelativeTraversalExpr) walkChildNodes(w internalWalkFunc) {
132 // Scope traversals have no child nodes 135 w(e.Source)
133} 136}
134 137
135func (e *RelativeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 138func (e *RelativeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
136 src, diags := e.Source.Value(ctx) 139 src, diags := e.Source.Value(ctx)
137 ret, travDiags := e.Traversal.TraverseRel(src) 140 ret, travDiags := e.Traversal.TraverseRel(src)
141 setDiagEvalContext(travDiags, e, ctx)
138 diags = append(diags, travDiags...) 142 diags = append(diags, travDiags...)
139 return ret, diags 143 return ret, diags
140} 144}
@@ -177,8 +181,8 @@ type FunctionCallExpr struct {
177} 181}
178 182
179func (e *FunctionCallExpr) walkChildNodes(w internalWalkFunc) { 183func (e *FunctionCallExpr) walkChildNodes(w internalWalkFunc) {
180 for i, arg := range e.Args { 184 for _, arg := range e.Args {
181 e.Args[i] = w(arg).(Expression) 185 w(arg)
182 } 186 }
183} 187}
184 188
@@ -206,10 +210,12 @@ func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnosti
206 if !hasNonNilMap { 210 if !hasNonNilMap {
207 return cty.DynamicVal, hcl.Diagnostics{ 211 return cty.DynamicVal, hcl.Diagnostics{
208 { 212 {
209 Severity: hcl.DiagError, 213 Severity: hcl.DiagError,
210 Summary: "Function calls not allowed", 214 Summary: "Function calls not allowed",
211 Detail: "Functions may not be called here.", 215 Detail: "Functions may not be called here.",
212 Subject: e.Range().Ptr(), 216 Subject: e.Range().Ptr(),
217 Expression: e,
218 EvalContext: ctx,
213 }, 219 },
214 } 220 }
215 } 221 }
@@ -225,11 +231,13 @@ func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnosti
225 231
226 return cty.DynamicVal, hcl.Diagnostics{ 232 return cty.DynamicVal, hcl.Diagnostics{
227 { 233 {
228 Severity: hcl.DiagError, 234 Severity: hcl.DiagError,
229 Summary: "Call to unknown function", 235 Summary: "Call to unknown function",
230 Detail: fmt.Sprintf("There is no function named %q.%s", e.Name, suggestion), 236 Detail: fmt.Sprintf("There is no function named %q.%s", e.Name, suggestion),
231 Subject: &e.NameRange, 237 Subject: &e.NameRange,
232 Context: e.Range().Ptr(), 238 Context: e.Range().Ptr(),
239 Expression: e,
240 EvalContext: ctx,
233 }, 241 },
234 } 242 }
235 } 243 }
@@ -254,11 +262,13 @@ func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnosti
254 case expandVal.Type().IsTupleType() || expandVal.Type().IsListType() || expandVal.Type().IsSetType(): 262 case expandVal.Type().IsTupleType() || expandVal.Type().IsListType() || expandVal.Type().IsSetType():
255 if expandVal.IsNull() { 263 if expandVal.IsNull() {
256 diags = append(diags, &hcl.Diagnostic{ 264 diags = append(diags, &hcl.Diagnostic{
257 Severity: hcl.DiagError, 265 Severity: hcl.DiagError,
258 Summary: "Invalid expanding argument value", 266 Summary: "Invalid expanding argument value",
259 Detail: "The expanding argument (indicated by ...) must not be null.", 267 Detail: "The expanding argument (indicated by ...) must not be null.",
260 Context: expandExpr.Range().Ptr(), 268 Subject: expandExpr.Range().Ptr(),
261 Subject: e.Range().Ptr(), 269 Context: e.Range().Ptr(),
270 Expression: expandExpr,
271 EvalContext: ctx,
262 }) 272 })
263 return cty.DynamicVal, diags 273 return cty.DynamicVal, diags
264 } 274 }
@@ -279,11 +289,13 @@ func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnosti
279 args = newArgs 289 args = newArgs
280 default: 290 default:
281 diags = append(diags, &hcl.Diagnostic{ 291 diags = append(diags, &hcl.Diagnostic{
282 Severity: hcl.DiagError, 292 Severity: hcl.DiagError,
283 Summary: "Invalid expanding argument value", 293 Summary: "Invalid expanding argument value",
284 Detail: "The expanding argument (indicated by ...) must be of a tuple, list, or set type.", 294 Detail: "The expanding argument (indicated by ...) must be of a tuple, list, or set type.",
285 Context: expandExpr.Range().Ptr(), 295 Subject: expandExpr.Range().Ptr(),
286 Subject: e.Range().Ptr(), 296 Context: e.Range().Ptr(),
297 Expression: expandExpr,
298 EvalContext: ctx,
287 }) 299 })
288 return cty.DynamicVal, diags 300 return cty.DynamicVal, diags
289 } 301 }
@@ -303,8 +315,10 @@ func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnosti
303 "Function %q expects%s %d argument(s). Missing value for %q.", 315 "Function %q expects%s %d argument(s). Missing value for %q.",
304 e.Name, qual, len(params), missing.Name, 316 e.Name, qual, len(params), missing.Name,
305 ), 317 ),
306 Subject: &e.CloseParenRange, 318 Subject: &e.CloseParenRange,
307 Context: e.Range().Ptr(), 319 Context: e.Range().Ptr(),
320 Expression: e,
321 EvalContext: ctx,
308 }, 322 },
309 } 323 }
310 } 324 }
@@ -318,8 +332,10 @@ func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnosti
318 "Function %q expects only %d argument(s).", 332 "Function %q expects only %d argument(s).",
319 e.Name, len(params), 333 e.Name, len(params),
320 ), 334 ),
321 Subject: args[len(params)].StartRange().Ptr(), 335 Subject: args[len(params)].StartRange().Ptr(),
322 Context: e.Range().Ptr(), 336 Context: e.Range().Ptr(),
337 Expression: e,
338 EvalContext: ctx,
323 }, 339 },
324 } 340 }
325 } 341 }
@@ -349,8 +365,10 @@ func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnosti
349 "Invalid value for %q parameter: %s.", 365 "Invalid value for %q parameter: %s.",
350 param.Name, err, 366 param.Name, err,
351 ), 367 ),
352 Subject: argExpr.StartRange().Ptr(), 368 Subject: argExpr.StartRange().Ptr(),
353 Context: e.Range().Ptr(), 369 Context: e.Range().Ptr(),
370 Expression: argExpr,
371 EvalContext: ctx,
354 }) 372 })
355 } 373 }
356 374
@@ -386,8 +404,10 @@ func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnosti
386 "Invalid value for %q parameter: %s.", 404 "Invalid value for %q parameter: %s.",
387 param.Name, err, 405 param.Name, err,
388 ), 406 ),
389 Subject: argExpr.StartRange().Ptr(), 407 Subject: argExpr.StartRange().Ptr(),
390 Context: e.Range().Ptr(), 408 Context: e.Range().Ptr(),
409 Expression: argExpr,
410 EvalContext: ctx,
391 }) 411 })
392 412
393 default: 413 default:
@@ -398,8 +418,10 @@ func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnosti
398 "Call to function %q failed: %s.", 418 "Call to function %q failed: %s.",
399 e.Name, err, 419 e.Name, err,
400 ), 420 ),
401 Subject: e.StartRange().Ptr(), 421 Subject: e.StartRange().Ptr(),
402 Context: e.Range().Ptr(), 422 Context: e.Range().Ptr(),
423 Expression: e,
424 EvalContext: ctx,
403 }) 425 })
404 } 426 }
405 427
@@ -441,9 +463,9 @@ type ConditionalExpr struct {
441} 463}
442 464
443func (e *ConditionalExpr) walkChildNodes(w internalWalkFunc) { 465func (e *ConditionalExpr) walkChildNodes(w internalWalkFunc) {
444 e.Condition = w(e.Condition).(Expression) 466 w(e.Condition)
445 e.TrueResult = w(e.TrueResult).(Expression) 467 w(e.TrueResult)
446 e.FalseResult = w(e.FalseResult).(Expression) 468 w(e.FalseResult)
447} 469}
448 470
449func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 471func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
@@ -464,10 +486,12 @@ func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostic
464 // "These expressions are object and object respectively" if the 486 // "These expressions are object and object respectively" if the
465 // object types don't exactly match. 487 // object types don't exactly match.
466 "The true and false result expressions must have consistent types. The given expressions are %s and %s, respectively.", 488 "The true and false result expressions must have consistent types. The given expressions are %s and %s, respectively.",
467 trueResult.Type(), falseResult.Type(), 489 trueResult.Type().FriendlyName(), falseResult.Type().FriendlyName(),
468 ), 490 ),
469 Subject: hcl.RangeBetween(e.TrueResult.Range(), e.FalseResult.Range()).Ptr(), 491 Subject: hcl.RangeBetween(e.TrueResult.Range(), e.FalseResult.Range()).Ptr(),
470 Context: &e.SrcRange, 492 Context: &e.SrcRange,
493 Expression: e,
494 EvalContext: ctx,
471 }, 495 },
472 } 496 }
473 } 497 }
@@ -476,11 +500,13 @@ func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostic
476 diags = append(diags, condDiags...) 500 diags = append(diags, condDiags...)
477 if condResult.IsNull() { 501 if condResult.IsNull() {
478 diags = append(diags, &hcl.Diagnostic{ 502 diags = append(diags, &hcl.Diagnostic{
479 Severity: hcl.DiagError, 503 Severity: hcl.DiagError,
480 Summary: "Null condition", 504 Summary: "Null condition",
481 Detail: "The condition value is null. Conditions must either be true or false.", 505 Detail: "The condition value is null. Conditions must either be true or false.",
482 Subject: e.Condition.Range().Ptr(), 506 Subject: e.Condition.Range().Ptr(),
483 Context: &e.SrcRange, 507 Context: &e.SrcRange,
508 Expression: e.Condition,
509 EvalContext: ctx,
484 }) 510 })
485 return cty.UnknownVal(resultType), diags 511 return cty.UnknownVal(resultType), diags
486 } 512 }
@@ -490,11 +516,13 @@ func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostic
490 condResult, err := convert.Convert(condResult, cty.Bool) 516 condResult, err := convert.Convert(condResult, cty.Bool)
491 if err != nil { 517 if err != nil {
492 diags = append(diags, &hcl.Diagnostic{ 518 diags = append(diags, &hcl.Diagnostic{
493 Severity: hcl.DiagError, 519 Severity: hcl.DiagError,
494 Summary: "Incorrect condition type", 520 Summary: "Incorrect condition type",
495 Detail: fmt.Sprintf("The condition expression must be of type bool."), 521 Detail: fmt.Sprintf("The condition expression must be of type bool."),
496 Subject: e.Condition.Range().Ptr(), 522 Subject: e.Condition.Range().Ptr(),
497 Context: &e.SrcRange, 523 Context: &e.SrcRange,
524 Expression: e.Condition,
525 EvalContext: ctx,
498 }) 526 })
499 return cty.UnknownVal(resultType), diags 527 return cty.UnknownVal(resultType), diags
500 } 528 }
@@ -513,8 +541,10 @@ func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostic
513 "The true result value has the wrong type: %s.", 541 "The true result value has the wrong type: %s.",
514 err.Error(), 542 err.Error(),
515 ), 543 ),
516 Subject: e.TrueResult.Range().Ptr(), 544 Subject: e.TrueResult.Range().Ptr(),
517 Context: &e.SrcRange, 545 Context: &e.SrcRange,
546 Expression: e.TrueResult,
547 EvalContext: ctx,
518 }) 548 })
519 trueResult = cty.UnknownVal(resultType) 549 trueResult = cty.UnknownVal(resultType)
520 } 550 }
@@ -534,8 +564,10 @@ func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostic
534 "The false result value has the wrong type: %s.", 564 "The false result value has the wrong type: %s.",
535 err.Error(), 565 err.Error(),
536 ), 566 ),
537 Subject: e.TrueResult.Range().Ptr(), 567 Subject: e.FalseResult.Range().Ptr(),
538 Context: &e.SrcRange, 568 Context: &e.SrcRange,
569 Expression: e.FalseResult,
570 EvalContext: ctx,
539 }) 571 })
540 falseResult = cty.UnknownVal(resultType) 572 falseResult = cty.UnknownVal(resultType)
541 } 573 }
@@ -561,8 +593,8 @@ type IndexExpr struct {
561} 593}
562 594
563func (e *IndexExpr) walkChildNodes(w internalWalkFunc) { 595func (e *IndexExpr) walkChildNodes(w internalWalkFunc) {
564 e.Collection = w(e.Collection).(Expression) 596 w(e.Collection)
565 e.Key = w(e.Key).(Expression) 597 w(e.Key)
566} 598}
567 599
568func (e *IndexExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 600func (e *IndexExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
@@ -572,7 +604,10 @@ func (e *IndexExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
572 diags = append(diags, collDiags...) 604 diags = append(diags, collDiags...)
573 diags = append(diags, keyDiags...) 605 diags = append(diags, keyDiags...)
574 606
575 return hcl.Index(coll, key, &e.SrcRange) 607 val, indexDiags := hcl.Index(coll, key, &e.SrcRange)
608 setDiagEvalContext(indexDiags, e, ctx)
609 diags = append(diags, indexDiags...)
610 return val, diags
576} 611}
577 612
578func (e *IndexExpr) Range() hcl.Range { 613func (e *IndexExpr) Range() hcl.Range {
@@ -591,8 +626,8 @@ type TupleConsExpr struct {
591} 626}
592 627
593func (e *TupleConsExpr) walkChildNodes(w internalWalkFunc) { 628func (e *TupleConsExpr) walkChildNodes(w internalWalkFunc) {
594 for i, expr := range e.Exprs { 629 for _, expr := range e.Exprs {
595 e.Exprs[i] = w(expr).(Expression) 630 w(expr)
596 } 631 }
597} 632}
598 633
@@ -640,9 +675,9 @@ type ObjectConsItem struct {
640} 675}
641 676
642func (e *ObjectConsExpr) walkChildNodes(w internalWalkFunc) { 677func (e *ObjectConsExpr) walkChildNodes(w internalWalkFunc) {
643 for i, item := range e.Items { 678 for _, item := range e.Items {
644 e.Items[i].KeyExpr = w(item.KeyExpr).(Expression) 679 w(item.KeyExpr)
645 e.Items[i].ValueExpr = w(item.ValueExpr).(Expression) 680 w(item.ValueExpr)
646 } 681 }
647} 682}
648 683
@@ -675,10 +710,12 @@ func (e *ObjectConsExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics
675 710
676 if key.IsNull() { 711 if key.IsNull() {
677 diags = append(diags, &hcl.Diagnostic{ 712 diags = append(diags, &hcl.Diagnostic{
678 Severity: hcl.DiagError, 713 Severity: hcl.DiagError,
679 Summary: "Null value as key", 714 Summary: "Null value as key",
680 Detail: "Can't use a null value as a key.", 715 Detail: "Can't use a null value as a key.",
681 Subject: item.ValueExpr.Range().Ptr(), 716 Subject: item.ValueExpr.Range().Ptr(),
717 Expression: item.KeyExpr,
718 EvalContext: ctx,
682 }) 719 })
683 known = false 720 known = false
684 continue 721 continue
@@ -688,10 +725,12 @@ func (e *ObjectConsExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics
688 key, err = convert.Convert(key, cty.String) 725 key, err = convert.Convert(key, cty.String)
689 if err != nil { 726 if err != nil {
690 diags = append(diags, &hcl.Diagnostic{ 727 diags = append(diags, &hcl.Diagnostic{
691 Severity: hcl.DiagError, 728 Severity: hcl.DiagError,
692 Summary: "Incorrect key type", 729 Summary: "Incorrect key type",
693 Detail: fmt.Sprintf("Can't use this value as a key: %s.", err.Error()), 730 Detail: fmt.Sprintf("Can't use this value as a key: %s.", err.Error()),
694 Subject: item.ValueExpr.Range().Ptr(), 731 Subject: item.KeyExpr.Range().Ptr(),
732 Expression: item.KeyExpr,
733 EvalContext: ctx,
695 }) 734 })
696 known = false 735 known = false
697 continue 736 continue
@@ -754,11 +793,31 @@ func (e *ObjectConsKeyExpr) walkChildNodes(w internalWalkFunc) {
754 // We only treat our wrapped expression as a real expression if we're 793 // We only treat our wrapped expression as a real expression if we're
755 // not going to interpret it as a literal. 794 // not going to interpret it as a literal.
756 if e.literalName() == "" { 795 if e.literalName() == "" {
757 e.Wrapped = w(e.Wrapped).(Expression) 796 w(e.Wrapped)
758 } 797 }
759} 798}
760 799
761func (e *ObjectConsKeyExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 800func (e *ObjectConsKeyExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
801 // Because we accept a naked identifier as a literal key rather than a
802 // reference, it's confusing to accept a traversal containing periods
803 // here since we can't tell if the user intends to create a key with
804 // periods or actually reference something. To avoid confusing downstream
805 // errors we'll just prohibit a naked multi-step traversal here and
806 // require the user to state their intent more clearly.
807 // (This is handled at evaluation time rather than parse time because
808 // an application using static analysis _can_ accept a naked multi-step
809 // traversal here, if desired.)
810 if travExpr, isTraversal := e.Wrapped.(*ScopeTraversalExpr); isTraversal && len(travExpr.Traversal) > 1 {
811 var diags hcl.Diagnostics
812 diags = append(diags, &hcl.Diagnostic{
813 Severity: hcl.DiagError,
814 Summary: "Ambiguous attribute key",
815 Detail: "If this expression is intended to be a reference, wrap it in parentheses. If it's instead intended as a literal name containing periods, wrap it in quotes to create a string literal.",
816 Subject: e.Range().Ptr(),
817 })
818 return cty.DynamicVal, diags
819 }
820
762 if ln := e.literalName(); ln != "" { 821 if ln := e.literalName(); ln != "" {
763 return cty.StringVal(ln), nil 822 return cty.StringVal(ln), nil
764 } 823 }
@@ -818,11 +877,13 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
818 877
819 if collVal.IsNull() { 878 if collVal.IsNull() {
820 diags = append(diags, &hcl.Diagnostic{ 879 diags = append(diags, &hcl.Diagnostic{
821 Severity: hcl.DiagError, 880 Severity: hcl.DiagError,
822 Summary: "Iteration over null value", 881 Summary: "Iteration over null value",
823 Detail: "A null value cannot be used as the collection in a 'for' expression.", 882 Detail: "A null value cannot be used as the collection in a 'for' expression.",
824 Subject: e.CollExpr.Range().Ptr(), 883 Subject: e.CollExpr.Range().Ptr(),
825 Context: &e.SrcRange, 884 Context: &e.SrcRange,
885 Expression: e.CollExpr,
886 EvalContext: ctx,
826 }) 887 })
827 return cty.DynamicVal, diags 888 return cty.DynamicVal, diags
828 } 889 }
@@ -837,8 +898,10 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
837 "A value of type %s cannot be used as the collection in a 'for' expression.", 898 "A value of type %s cannot be used as the collection in a 'for' expression.",
838 collVal.Type().FriendlyName(), 899 collVal.Type().FriendlyName(),
839 ), 900 ),
840 Subject: e.CollExpr.Range().Ptr(), 901 Subject: e.CollExpr.Range().Ptr(),
841 Context: &e.SrcRange, 902 Context: &e.SrcRange,
903 Expression: e.CollExpr,
904 EvalContext: ctx,
842 }) 905 })
843 return cty.DynamicVal, diags 906 return cty.DynamicVal, diags
844 } 907 }
@@ -846,14 +909,13 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
846 return cty.DynamicVal, diags 909 return cty.DynamicVal, diags
847 } 910 }
848 911
849 childCtx := ctx.NewChild()
850 childCtx.Variables = map[string]cty.Value{}
851
852 // Before we start we'll do an early check to see if any CondExpr we've 912 // Before we start we'll do an early check to see if any CondExpr we've
853 // been given is of the wrong type. This isn't 100% reliable (it may 913 // been given is of the wrong type. This isn't 100% reliable (it may
854 // be DynamicVal until real values are given) but it should catch some 914 // be DynamicVal until real values are given) but it should catch some
855 // straightforward cases and prevent a barrage of repeated errors. 915 // straightforward cases and prevent a barrage of repeated errors.
856 if e.CondExpr != nil { 916 if e.CondExpr != nil {
917 childCtx := ctx.NewChild()
918 childCtx.Variables = map[string]cty.Value{}
857 if e.KeyVar != "" { 919 if e.KeyVar != "" {
858 childCtx.Variables[e.KeyVar] = cty.DynamicVal 920 childCtx.Variables[e.KeyVar] = cty.DynamicVal
859 } 921 }
@@ -863,22 +925,26 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
863 diags = append(diags, condDiags...) 925 diags = append(diags, condDiags...)
864 if result.IsNull() { 926 if result.IsNull() {
865 diags = append(diags, &hcl.Diagnostic{ 927 diags = append(diags, &hcl.Diagnostic{
866 Severity: hcl.DiagError, 928 Severity: hcl.DiagError,
867 Summary: "Condition is null", 929 Summary: "Condition is null",
868 Detail: "The value of the 'if' clause must not be null.", 930 Detail: "The value of the 'if' clause must not be null.",
869 Subject: e.CondExpr.Range().Ptr(), 931 Subject: e.CondExpr.Range().Ptr(),
870 Context: &e.SrcRange, 932 Context: &e.SrcRange,
933 Expression: e.CondExpr,
934 EvalContext: ctx,
871 }) 935 })
872 return cty.DynamicVal, diags 936 return cty.DynamicVal, diags
873 } 937 }
874 _, err := convert.Convert(result, cty.Bool) 938 _, err := convert.Convert(result, cty.Bool)
875 if err != nil { 939 if err != nil {
876 diags = append(diags, &hcl.Diagnostic{ 940 diags = append(diags, &hcl.Diagnostic{
877 Severity: hcl.DiagError, 941 Severity: hcl.DiagError,
878 Summary: "Invalid 'for' condition", 942 Summary: "Invalid 'for' condition",
879 Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()), 943 Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()),
880 Subject: e.CondExpr.Range().Ptr(), 944 Subject: e.CondExpr.Range().Ptr(),
881 Context: &e.SrcRange, 945 Context: &e.SrcRange,
946 Expression: e.CondExpr,
947 EvalContext: ctx,
882 }) 948 })
883 return cty.DynamicVal, diags 949 return cty.DynamicVal, diags
884 } 950 }
@@ -902,6 +968,8 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
902 known := true 968 known := true
903 for it.Next() { 969 for it.Next() {
904 k, v := it.Element() 970 k, v := it.Element()
971 childCtx := ctx.NewChild()
972 childCtx.Variables = map[string]cty.Value{}
905 if e.KeyVar != "" { 973 if e.KeyVar != "" {
906 childCtx.Variables[e.KeyVar] = k 974 childCtx.Variables[e.KeyVar] = k
907 } 975 }
@@ -913,11 +981,13 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
913 if includeRaw.IsNull() { 981 if includeRaw.IsNull() {
914 if known { 982 if known {
915 diags = append(diags, &hcl.Diagnostic{ 983 diags = append(diags, &hcl.Diagnostic{
916 Severity: hcl.DiagError, 984 Severity: hcl.DiagError,
917 Summary: "Condition is null", 985 Summary: "Invalid 'for' condition",
918 Detail: "The value of the 'if' clause must not be null.", 986 Detail: "The value of the 'if' clause must not be null.",
919 Subject: e.CondExpr.Range().Ptr(), 987 Subject: e.CondExpr.Range().Ptr(),
920 Context: &e.SrcRange, 988 Context: &e.SrcRange,
989 Expression: e.CondExpr,
990 EvalContext: childCtx,
921 }) 991 })
922 } 992 }
923 known = false 993 known = false
@@ -927,11 +997,13 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
927 if err != nil { 997 if err != nil {
928 if known { 998 if known {
929 diags = append(diags, &hcl.Diagnostic{ 999 diags = append(diags, &hcl.Diagnostic{
930 Severity: hcl.DiagError, 1000 Severity: hcl.DiagError,
931 Summary: "Invalid 'for' condition", 1001 Summary: "Invalid 'for' condition",
932 Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()), 1002 Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()),
933 Subject: e.CondExpr.Range().Ptr(), 1003 Subject: e.CondExpr.Range().Ptr(),
934 Context: &e.SrcRange, 1004 Context: &e.SrcRange,
1005 Expression: e.CondExpr,
1006 EvalContext: childCtx,
935 }) 1007 })
936 } 1008 }
937 known = false 1009 known = false
@@ -953,11 +1025,13 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
953 if keyRaw.IsNull() { 1025 if keyRaw.IsNull() {
954 if known { 1026 if known {
955 diags = append(diags, &hcl.Diagnostic{ 1027 diags = append(diags, &hcl.Diagnostic{
956 Severity: hcl.DiagError, 1028 Severity: hcl.DiagError,
957 Summary: "Invalid object key", 1029 Summary: "Invalid object key",
958 Detail: "Key expression in 'for' expression must not produce a null value.", 1030 Detail: "Key expression in 'for' expression must not produce a null value.",
959 Subject: e.KeyExpr.Range().Ptr(), 1031 Subject: e.KeyExpr.Range().Ptr(),
960 Context: &e.SrcRange, 1032 Context: &e.SrcRange,
1033 Expression: e.KeyExpr,
1034 EvalContext: childCtx,
961 }) 1035 })
962 } 1036 }
963 known = false 1037 known = false
@@ -972,11 +1046,13 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
972 if err != nil { 1046 if err != nil {
973 if known { 1047 if known {
974 diags = append(diags, &hcl.Diagnostic{ 1048 diags = append(diags, &hcl.Diagnostic{
975 Severity: hcl.DiagError, 1049 Severity: hcl.DiagError,
976 Summary: "Invalid object key", 1050 Summary: "Invalid object key",
977 Detail: fmt.Sprintf("The key expression produced an invalid result: %s.", err.Error()), 1051 Detail: fmt.Sprintf("The key expression produced an invalid result: %s.", err.Error()),
978 Subject: e.KeyExpr.Range().Ptr(), 1052 Subject: e.KeyExpr.Range().Ptr(),
979 Context: &e.SrcRange, 1053 Context: &e.SrcRange,
1054 Expression: e.KeyExpr,
1055 EvalContext: childCtx,
980 }) 1056 })
981 } 1057 }
982 known = false 1058 known = false
@@ -996,11 +1072,13 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
996 Severity: hcl.DiagError, 1072 Severity: hcl.DiagError,
997 Summary: "Duplicate object key", 1073 Summary: "Duplicate object key",
998 Detail: fmt.Sprintf( 1074 Detail: fmt.Sprintf(
999 "Two different items produced the key %q in this for expression. If duplicates are expected, use the ellipsis (...) after the value expression to enable grouping by key.", 1075 "Two different items produced the key %q in this 'for' expression. If duplicates are expected, use the ellipsis (...) after the value expression to enable grouping by key.",
1000 k, 1076 k,
1001 ), 1077 ),
1002 Subject: e.KeyExpr.Range().Ptr(), 1078 Subject: e.KeyExpr.Range().Ptr(),
1003 Context: &e.SrcRange, 1079 Context: &e.SrcRange,
1080 Expression: e.KeyExpr,
1081 EvalContext: childCtx,
1004 }) 1082 })
1005 } else { 1083 } else {
1006 vals[key.AsString()] = val 1084 vals[key.AsString()] = val
@@ -1030,6 +1108,8 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
1030 known := true 1108 known := true
1031 for it.Next() { 1109 for it.Next() {
1032 k, v := it.Element() 1110 k, v := it.Element()
1111 childCtx := ctx.NewChild()
1112 childCtx.Variables = map[string]cty.Value{}
1033 if e.KeyVar != "" { 1113 if e.KeyVar != "" {
1034 childCtx.Variables[e.KeyVar] = k 1114 childCtx.Variables[e.KeyVar] = k
1035 } 1115 }
@@ -1041,11 +1121,13 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
1041 if includeRaw.IsNull() { 1121 if includeRaw.IsNull() {
1042 if known { 1122 if known {
1043 diags = append(diags, &hcl.Diagnostic{ 1123 diags = append(diags, &hcl.Diagnostic{
1044 Severity: hcl.DiagError, 1124 Severity: hcl.DiagError,
1045 Summary: "Condition is null", 1125 Summary: "Invalid 'for' condition",
1046 Detail: "The value of the 'if' clause must not be null.", 1126 Detail: "The value of the 'if' clause must not be null.",
1047 Subject: e.CondExpr.Range().Ptr(), 1127 Subject: e.CondExpr.Range().Ptr(),
1048 Context: &e.SrcRange, 1128 Context: &e.SrcRange,
1129 Expression: e.CondExpr,
1130 EvalContext: childCtx,
1049 }) 1131 })
1050 } 1132 }
1051 known = false 1133 known = false
@@ -1063,11 +1145,13 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
1063 if err != nil { 1145 if err != nil {
1064 if known { 1146 if known {
1065 diags = append(diags, &hcl.Diagnostic{ 1147 diags = append(diags, &hcl.Diagnostic{
1066 Severity: hcl.DiagError, 1148 Severity: hcl.DiagError,
1067 Summary: "Invalid 'for' condition", 1149 Summary: "Invalid 'for' condition",
1068 Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()), 1150 Detail: fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()),
1069 Subject: e.CondExpr.Range().Ptr(), 1151 Subject: e.CondExpr.Range().Ptr(),
1070 Context: &e.SrcRange, 1152 Context: &e.SrcRange,
1153 Expression: e.CondExpr,
1154 EvalContext: childCtx,
1071 }) 1155 })
1072 } 1156 }
1073 known = false 1157 known = false
@@ -1094,7 +1178,7 @@ func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
1094} 1178}
1095 1179
1096func (e *ForExpr) walkChildNodes(w internalWalkFunc) { 1180func (e *ForExpr) walkChildNodes(w internalWalkFunc) {
1097 e.CollExpr = w(e.CollExpr).(Expression) 1181 w(e.CollExpr)
1098 1182
1099 scopeNames := map[string]struct{}{} 1183 scopeNames := map[string]struct{}{}
1100 if e.KeyVar != "" { 1184 if e.KeyVar != "" {
@@ -1107,17 +1191,17 @@ func (e *ForExpr) walkChildNodes(w internalWalkFunc) {
1107 if e.KeyExpr != nil { 1191 if e.KeyExpr != nil {
1108 w(ChildScope{ 1192 w(ChildScope{
1109 LocalNames: scopeNames, 1193 LocalNames: scopeNames,
1110 Expr: &e.KeyExpr, 1194 Expr: e.KeyExpr,
1111 }) 1195 })
1112 } 1196 }
1113 w(ChildScope{ 1197 w(ChildScope{
1114 LocalNames: scopeNames, 1198 LocalNames: scopeNames,
1115 Expr: &e.ValExpr, 1199 Expr: e.ValExpr,
1116 }) 1200 })
1117 if e.CondExpr != nil { 1201 if e.CondExpr != nil {
1118 w(ChildScope{ 1202 w(ChildScope{
1119 LocalNames: scopeNames, 1203 LocalNames: scopeNames,
1120 Expr: &e.CondExpr, 1204 Expr: e.CondExpr,
1121 }) 1205 })
1122 } 1206 }
1123} 1207}
@@ -1151,26 +1235,78 @@ func (e *SplatExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
1151 return cty.DynamicVal, diags 1235 return cty.DynamicVal, diags
1152 } 1236 }
1153 1237
1238 sourceTy := sourceVal.Type()
1239 if sourceTy == cty.DynamicPseudoType {
1240 // If we don't even know the _type_ of our source value yet then
1241 // we'll need to defer all processing, since we can't decide our
1242 // result type either.
1243 return cty.DynamicVal, diags
1244 }
1245
1246 // A "special power" of splat expressions is that they can be applied
1247 // both to tuples/lists and to other values, and in the latter case
1248 // the value will be treated as an implicit single-item tuple, or as
1249 // an empty tuple if the value is null.
1250 autoUpgrade := !(sourceTy.IsTupleType() || sourceTy.IsListType() || sourceTy.IsSetType())
1251
1154 if sourceVal.IsNull() { 1252 if sourceVal.IsNull() {
1253 if autoUpgrade {
1254 return cty.EmptyTupleVal, diags
1255 }
1155 diags = append(diags, &hcl.Diagnostic{ 1256 diags = append(diags, &hcl.Diagnostic{
1156 Severity: hcl.DiagError, 1257 Severity: hcl.DiagError,
1157 Summary: "Splat of null value", 1258 Summary: "Splat of null value",
1158 Detail: "Splat expressions (with the * symbol) cannot be applied to null values.", 1259 Detail: "Splat expressions (with the * symbol) cannot be applied to null sequences.",
1159 Subject: e.Source.Range().Ptr(), 1260 Subject: e.Source.Range().Ptr(),
1160 Context: hcl.RangeBetween(e.Source.Range(), e.MarkerRange).Ptr(), 1261 Context: hcl.RangeBetween(e.Source.Range(), e.MarkerRange).Ptr(),
1262 Expression: e.Source,
1263 EvalContext: ctx,
1161 }) 1264 })
1162 return cty.DynamicVal, diags 1265 return cty.DynamicVal, diags
1163 } 1266 }
1164 if !sourceVal.IsKnown() { 1267
1165 return cty.DynamicVal, diags 1268 if autoUpgrade {
1269 sourceVal = cty.TupleVal([]cty.Value{sourceVal})
1270 sourceTy = sourceVal.Type()
1166 } 1271 }
1167 1272
1168 // A "special power" of splat expressions is that they can be applied 1273 // We'll compute our result type lazily if we need it. In the normal case
1169 // both to tuples/lists and to other values, and in the latter case 1274 // it's inferred automatically from the value we construct.
1170 // the value will be treated as an implicit single-value list. We'll 1275 resultTy := func() (cty.Type, hcl.Diagnostics) {
1171 // deal with that here first. 1276 chiCtx := ctx.NewChild()
1172 if !(sourceVal.Type().IsTupleType() || sourceVal.Type().IsListType()) { 1277 var diags hcl.Diagnostics
1173 sourceVal = cty.ListVal([]cty.Value{sourceVal}) 1278 switch {
1279 case sourceTy.IsListType() || sourceTy.IsSetType():
1280 ety := sourceTy.ElementType()
1281 e.Item.setValue(chiCtx, cty.UnknownVal(ety))
1282 val, itemDiags := e.Each.Value(chiCtx)
1283 diags = append(diags, itemDiags...)
1284 e.Item.clearValue(chiCtx) // clean up our temporary value
1285 return cty.List(val.Type()), diags
1286 case sourceTy.IsTupleType():
1287 etys := sourceTy.TupleElementTypes()
1288 resultTys := make([]cty.Type, 0, len(etys))
1289 for _, ety := range etys {
1290 e.Item.setValue(chiCtx, cty.UnknownVal(ety))
1291 val, itemDiags := e.Each.Value(chiCtx)
1292 diags = append(diags, itemDiags...)
1293 e.Item.clearValue(chiCtx) // clean up our temporary value
1294 resultTys = append(resultTys, val.Type())
1295 }
1296 return cty.Tuple(resultTys), diags
1297 default:
1298 // Should never happen because of our promotion to list above.
1299 return cty.DynamicPseudoType, diags
1300 }
1301 }
1302
1303 if !sourceVal.IsKnown() {
1304 // We can't produce a known result in this case, but we'll still
1305 // indicate what the result type would be, allowing any downstream type
1306 // checking to proceed.
1307 ty, tyDiags := resultTy()
1308 diags = append(diags, tyDiags...)
1309 return cty.UnknownVal(ty), diags
1174 } 1310 }
1175 1311
1176 vals := make([]cty.Value, 0, sourceVal.LengthInt()) 1312 vals := make([]cty.Value, 0, sourceVal.LengthInt())
@@ -1194,15 +1330,28 @@ func (e *SplatExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
1194 e.Item.clearValue(ctx) // clean up our temporary value 1330 e.Item.clearValue(ctx) // clean up our temporary value
1195 1331
1196 if !isKnown { 1332 if !isKnown {
1197 return cty.DynamicVal, diags 1333 // We'll ingore the resultTy diagnostics in this case since they
1334 // will just be the same errors we saw while iterating above.
1335 ty, _ := resultTy()
1336 return cty.UnknownVal(ty), diags
1198 } 1337 }
1199 1338
1200 return cty.TupleVal(vals), diags 1339 switch {
1340 case sourceTy.IsListType() || sourceTy.IsSetType():
1341 if len(vals) == 0 {
1342 ty, tyDiags := resultTy()
1343 diags = append(diags, tyDiags...)
1344 return cty.ListValEmpty(ty.ElementType()), diags
1345 }
1346 return cty.ListVal(vals), diags
1347 default:
1348 return cty.TupleVal(vals), diags
1349 }
1201} 1350}
1202 1351
1203func (e *SplatExpr) walkChildNodes(w internalWalkFunc) { 1352func (e *SplatExpr) walkChildNodes(w internalWalkFunc) {
1204 e.Source = w(e.Source).(Expression) 1353 w(e.Source)
1205 e.Each = w(e.Each).(Expression) 1354 w(e.Each)
1206} 1355}
1207 1356
1208func (e *SplatExpr) Range() hcl.Range { 1357func (e *SplatExpr) Range() hcl.Range {
@@ -1226,13 +1375,24 @@ func (e *SplatExpr) StartRange() hcl.Range {
1226// assigns it a value. 1375// assigns it a value.
1227type AnonSymbolExpr struct { 1376type AnonSymbolExpr struct {
1228 SrcRange hcl.Range 1377 SrcRange hcl.Range
1229 values map[*hcl.EvalContext]cty.Value 1378
1379 // values and its associated lock are used to isolate concurrent
1380 // evaluations of a symbol from one another. It is the calling application's
1381 // responsibility to ensure that the same splat expression is not evalauted
1382 // concurrently within the _same_ EvalContext, but it is fine and safe to
1383 // do cuncurrent evaluations with distinct EvalContexts.
1384 values map[*hcl.EvalContext]cty.Value
1385 valuesLock sync.RWMutex
1230} 1386}
1231 1387
1232func (e *AnonSymbolExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { 1388func (e *AnonSymbolExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
1233 if ctx == nil { 1389 if ctx == nil {
1234 return cty.DynamicVal, nil 1390 return cty.DynamicVal, nil
1235 } 1391 }
1392
1393 e.valuesLock.RLock()
1394 defer e.valuesLock.RUnlock()
1395
1236 val, exists := e.values[ctx] 1396 val, exists := e.values[ctx]
1237 if !exists { 1397 if !exists {
1238 return cty.DynamicVal, nil 1398 return cty.DynamicVal, nil
@@ -1243,6 +1403,9 @@ func (e *AnonSymbolExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics
1243// setValue sets a temporary local value for the expression when evaluated 1403// setValue sets a temporary local value for the expression when evaluated
1244// in the given context, which must be non-nil. 1404// in the given context, which must be non-nil.
1245func (e *AnonSymbolExpr) setValue(ctx *hcl.EvalContext, val cty.Value) { 1405func (e *AnonSymbolExpr) setValue(ctx *hcl.EvalContext, val cty.Value) {
1406 e.valuesLock.Lock()
1407 defer e.valuesLock.Unlock()
1408
1246 if e.values == nil { 1409 if e.values == nil {
1247 e.values = make(map[*hcl.EvalContext]cty.Value) 1410 e.values = make(map[*hcl.EvalContext]cty.Value)
1248 } 1411 }
@@ -1253,6 +1416,9 @@ func (e *AnonSymbolExpr) setValue(ctx *hcl.EvalContext, val cty.Value) {
1253} 1416}
1254 1417
1255func (e *AnonSymbolExpr) clearValue(ctx *hcl.EvalContext) { 1418func (e *AnonSymbolExpr) clearValue(ctx *hcl.EvalContext) {
1419 e.valuesLock.Lock()
1420 defer e.valuesLock.Unlock()
1421
1256 if e.values == nil { 1422 if e.values == nil {
1257 return 1423 return
1258 } 1424 }