diff options
Diffstat (limited to 'vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go')
-rw-r--r-- | vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go | 456 |
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 | ||
3 | import ( | 3 | import ( |
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 | ||
106 | func (e *ScopeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { | 107 | func (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 | ||
110 | func (e *ScopeTraversalExpr) Range() hcl.Range { | 113 | func (e *ScopeTraversalExpr) Range() hcl.Range { |
@@ -129,12 +132,13 @@ type RelativeTraversalExpr struct { | |||
129 | } | 132 | } |
130 | 133 | ||
131 | func (e *RelativeTraversalExpr) walkChildNodes(w internalWalkFunc) { | 134 | func (e *RelativeTraversalExpr) walkChildNodes(w internalWalkFunc) { |
132 | // Scope traversals have no child nodes | 135 | w(e.Source) |
133 | } | 136 | } |
134 | 137 | ||
135 | func (e *RelativeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { | 138 | func (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 | ||
179 | func (e *FunctionCallExpr) walkChildNodes(w internalWalkFunc) { | 183 | func (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 | ||
443 | func (e *ConditionalExpr) walkChildNodes(w internalWalkFunc) { | 465 | func (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 | ||
449 | func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { | 471 | func (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 | ||
563 | func (e *IndexExpr) walkChildNodes(w internalWalkFunc) { | 595 | func (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 | ||
568 | func (e *IndexExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { | 600 | func (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 | ||
578 | func (e *IndexExpr) Range() hcl.Range { | 613 | func (e *IndexExpr) Range() hcl.Range { |
@@ -591,8 +626,8 @@ type TupleConsExpr struct { | |||
591 | } | 626 | } |
592 | 627 | ||
593 | func (e *TupleConsExpr) walkChildNodes(w internalWalkFunc) { | 628 | func (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 | ||
642 | func (e *ObjectConsExpr) walkChildNodes(w internalWalkFunc) { | 677 | func (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 | ||
761 | func (e *ObjectConsKeyExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { | 800 | func (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 | ||
1096 | func (e *ForExpr) walkChildNodes(w internalWalkFunc) { | 1180 | func (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 | ||
1203 | func (e *SplatExpr) walkChildNodes(w internalWalkFunc) { | 1352 | func (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 | ||
1208 | func (e *SplatExpr) Range() hcl.Range { | 1357 | func (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. |
1227 | type AnonSymbolExpr struct { | 1376 | type 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 | ||
1232 | func (e *AnonSymbolExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) { | 1388 | func (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. |
1245 | func (e *AnonSymbolExpr) setValue(ctx *hcl.EvalContext, val cty.Value) { | 1405 | func (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 | ||
1255 | func (e *AnonSymbolExpr) clearValue(ctx *hcl.EvalContext) { | 1418 | func (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 | } |