github.com/hashicorp/hcl/v2@v2.20.0/hclsyntax/expression.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package hclsyntax
     5  
     6  import (
     7  	"fmt"
     8  	"sort"
     9  	"strings"
    10  	"sync"
    11  
    12  	"github.com/hashicorp/hcl/v2"
    13  	"github.com/hashicorp/hcl/v2/ext/customdecode"
    14  	"github.com/zclconf/go-cty/cty"
    15  	"github.com/zclconf/go-cty/cty/convert"
    16  	"github.com/zclconf/go-cty/cty/function"
    17  )
    18  
    19  // Expression is the abstract type for nodes that behave as HCL expressions.
    20  type Expression interface {
    21  	Node
    22  
    23  	// The hcl.Expression methods are duplicated here, rather than simply
    24  	// embedded, because both Node and hcl.Expression have a Range method
    25  	// and so they conflict.
    26  
    27  	Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)
    28  	Variables() []hcl.Traversal
    29  	StartRange() hcl.Range
    30  }
    31  
    32  // Assert that Expression implements hcl.Expression
    33  var _ hcl.Expression = Expression(nil)
    34  
    35  // ParenthesesExpr represents an expression written in grouping
    36  // parentheses.
    37  //
    38  // The parser takes care of the precedence effect of the parentheses, so the
    39  // only purpose of this separate expression node is to capture the source range
    40  // of the parentheses themselves, rather than the source range of the
    41  // expression within. All of the other expression operations just pass through
    42  // to the underlying expression.
    43  type ParenthesesExpr struct {
    44  	Expression
    45  	SrcRange hcl.Range
    46  }
    47  
    48  var _ hcl.Expression = (*ParenthesesExpr)(nil)
    49  
    50  func (e *ParenthesesExpr) Range() hcl.Range {
    51  	return e.SrcRange
    52  }
    53  
    54  func (e *ParenthesesExpr) walkChildNodes(w internalWalkFunc) {
    55  	// We override the walkChildNodes from the embedded Expression to
    56  	// ensure that both the parentheses _and_ the content are visible
    57  	// in a walk.
    58  	w(e.Expression)
    59  }
    60  
    61  // LiteralValueExpr is an expression that just always returns a given value.
    62  type LiteralValueExpr struct {
    63  	Val      cty.Value
    64  	SrcRange hcl.Range
    65  }
    66  
    67  func (e *LiteralValueExpr) walkChildNodes(w internalWalkFunc) {
    68  	// Literal values have no child nodes
    69  }
    70  
    71  func (e *LiteralValueExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
    72  	return e.Val, nil
    73  }
    74  
    75  func (e *LiteralValueExpr) Range() hcl.Range {
    76  	return e.SrcRange
    77  }
    78  
    79  func (e *LiteralValueExpr) StartRange() hcl.Range {
    80  	return e.SrcRange
    81  }
    82  
    83  // Implementation for hcl.AbsTraversalForExpr.
    84  func (e *LiteralValueExpr) AsTraversal() hcl.Traversal {
    85  	// This one's a little weird: the contract for AsTraversal is to interpret
    86  	// an expression as if it were traversal syntax, and traversal syntax
    87  	// doesn't have the special keywords "null", "true", and "false" so these
    88  	// are expected to be treated like variables in that case.
    89  	// Since our parser already turned them into LiteralValueExpr by the time
    90  	// we get here, we need to undo this and infer the name that would've
    91  	// originally led to our value.
    92  	// We don't do anything for any other values, since they don't overlap
    93  	// with traversal roots.
    94  
    95  	if e.Val.IsNull() {
    96  		// In practice the parser only generates null values of the dynamic
    97  		// pseudo-type for literals, so we can safely assume that any null
    98  		// was orignally the keyword "null".
    99  		return hcl.Traversal{
   100  			hcl.TraverseRoot{
   101  				Name:     "null",
   102  				SrcRange: e.SrcRange,
   103  			},
   104  		}
   105  	}
   106  
   107  	switch e.Val {
   108  	case cty.True:
   109  		return hcl.Traversal{
   110  			hcl.TraverseRoot{
   111  				Name:     "true",
   112  				SrcRange: e.SrcRange,
   113  			},
   114  		}
   115  	case cty.False:
   116  		return hcl.Traversal{
   117  			hcl.TraverseRoot{
   118  				Name:     "false",
   119  				SrcRange: e.SrcRange,
   120  			},
   121  		}
   122  	default:
   123  		// No traversal is possible for any other value.
   124  		return nil
   125  	}
   126  }
   127  
   128  // ScopeTraversalExpr is an Expression that retrieves a value from the scope
   129  // using a traversal.
   130  type ScopeTraversalExpr struct {
   131  	Traversal hcl.Traversal
   132  	SrcRange  hcl.Range
   133  }
   134  
   135  func (e *ScopeTraversalExpr) walkChildNodes(w internalWalkFunc) {
   136  	// Scope traversals have no child nodes
   137  }
   138  
   139  func (e *ScopeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
   140  	val, diags := e.Traversal.TraverseAbs(ctx)
   141  	setDiagEvalContext(diags, e, ctx)
   142  	return val, diags
   143  }
   144  
   145  func (e *ScopeTraversalExpr) Range() hcl.Range {
   146  	return e.SrcRange
   147  }
   148  
   149  func (e *ScopeTraversalExpr) StartRange() hcl.Range {
   150  	return e.SrcRange
   151  }
   152  
   153  // Implementation for hcl.AbsTraversalForExpr.
   154  func (e *ScopeTraversalExpr) AsTraversal() hcl.Traversal {
   155  	return e.Traversal
   156  }
   157  
   158  // RelativeTraversalExpr is an Expression that retrieves a value from another
   159  // value using a _relative_ traversal.
   160  type RelativeTraversalExpr struct {
   161  	Source    Expression
   162  	Traversal hcl.Traversal
   163  	SrcRange  hcl.Range
   164  }
   165  
   166  func (e *RelativeTraversalExpr) walkChildNodes(w internalWalkFunc) {
   167  	w(e.Source)
   168  }
   169  
   170  func (e *RelativeTraversalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
   171  	src, diags := e.Source.Value(ctx)
   172  	ret, travDiags := e.Traversal.TraverseRel(src)
   173  	setDiagEvalContext(travDiags, e, ctx)
   174  	diags = append(diags, travDiags...)
   175  	return ret, diags
   176  }
   177  
   178  func (e *RelativeTraversalExpr) Range() hcl.Range {
   179  	return e.SrcRange
   180  }
   181  
   182  func (e *RelativeTraversalExpr) StartRange() hcl.Range {
   183  	return e.SrcRange
   184  }
   185  
   186  // Implementation for hcl.AbsTraversalForExpr.
   187  func (e *RelativeTraversalExpr) AsTraversal() hcl.Traversal {
   188  	// We can produce a traversal only if our source can.
   189  	st, diags := hcl.AbsTraversalForExpr(e.Source)
   190  	if diags.HasErrors() {
   191  		return nil
   192  	}
   193  
   194  	ret := make(hcl.Traversal, len(st)+len(e.Traversal))
   195  	copy(ret, st)
   196  	copy(ret[len(st):], e.Traversal)
   197  	return ret
   198  }
   199  
   200  // FunctionCallExpr is an Expression that calls a function from the EvalContext
   201  // and returns its result.
   202  type FunctionCallExpr struct {
   203  	Name string
   204  	Args []Expression
   205  
   206  	// If true, the final argument should be a tuple, list or set which will
   207  	// expand to be one argument per element.
   208  	ExpandFinal bool
   209  
   210  	NameRange       hcl.Range
   211  	OpenParenRange  hcl.Range
   212  	CloseParenRange hcl.Range
   213  }
   214  
   215  func (e *FunctionCallExpr) walkChildNodes(w internalWalkFunc) {
   216  	for _, arg := range e.Args {
   217  		w(arg)
   218  	}
   219  }
   220  
   221  func (e *FunctionCallExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
   222  	var diags hcl.Diagnostics
   223  
   224  	var f function.Function
   225  	exists := false
   226  	hasNonNilMap := false
   227  	thisCtx := ctx
   228  	for thisCtx != nil {
   229  		if thisCtx.Functions == nil {
   230  			thisCtx = thisCtx.Parent()
   231  			continue
   232  		}
   233  		hasNonNilMap = true
   234  		f, exists = thisCtx.Functions[e.Name]
   235  		if exists {
   236  			break
   237  		}
   238  		thisCtx = thisCtx.Parent()
   239  	}
   240  
   241  	if !exists {
   242  		if !hasNonNilMap {
   243  			return cty.DynamicVal, hcl.Diagnostics{
   244  				{
   245  					Severity:    hcl.DiagError,
   246  					Summary:     "Function calls not allowed",
   247  					Detail:      "Functions may not be called here.",
   248  					Subject:     e.Range().Ptr(),
   249  					Expression:  e,
   250  					EvalContext: ctx,
   251  				},
   252  			}
   253  		}
   254  
   255  		extraUnknown := &functionCallUnknown{
   256  			name: e.Name,
   257  		}
   258  
   259  		// For historical reasons, we represent namespaced function names
   260  		// as strings with :: separating the names. If this was an attempt
   261  		// to call a namespaced function then we'll try to distinguish
   262  		// between an invalid namespace or an invalid name within a valid
   263  		// namespace in order to give the user better feedback about what
   264  		// is wrong.
   265  		//
   266  		// The parser guarantees that a function name will always
   267  		// be a series of valid identifiers separated by "::" with no
   268  		// other content, so we can be relatively unforgiving in our processing
   269  		// here.
   270  		if sepIdx := strings.LastIndex(e.Name, "::"); sepIdx != -1 {
   271  			namespace := e.Name[:sepIdx+2]
   272  			name := e.Name[sepIdx+2:]
   273  
   274  			avail := make([]string, 0, len(ctx.Functions))
   275  			for availName := range ctx.Functions {
   276  				if strings.HasPrefix(availName, namespace) {
   277  					avail = append(avail, availName)
   278  				}
   279  			}
   280  
   281  			extraUnknown.name = name
   282  			extraUnknown.namespace = namespace
   283  
   284  			if len(avail) == 0 {
   285  				// TODO: Maybe use nameSuggestion for the other available
   286  				// namespaces? But that'd require us to go scan the function
   287  				// table again, so we'll wait to see if it's really warranted.
   288  				// For now, we're assuming people are more likely to misremember
   289  				// the function names than the namespaces, because in many
   290  				// applications there will be relatively few namespaces compared
   291  				// to the number of distinct functions.
   292  				return cty.DynamicVal, hcl.Diagnostics{
   293  					{
   294  						Severity:    hcl.DiagError,
   295  						Summary:     "Call to unknown function",
   296  						Detail:      fmt.Sprintf("There are no functions in namespace %q.", namespace),
   297  						Subject:     &e.NameRange,
   298  						Context:     e.Range().Ptr(),
   299  						Expression:  e,
   300  						EvalContext: ctx,
   301  						Extra:       extraUnknown,
   302  					},
   303  				}
   304  			} else {
   305  				suggestion := nameSuggestion(name, avail)
   306  				if suggestion != "" {
   307  					suggestion = fmt.Sprintf(" Did you mean %s%s?", namespace, suggestion)
   308  				}
   309  
   310  				return cty.DynamicVal, hcl.Diagnostics{
   311  					{
   312  						Severity:    hcl.DiagError,
   313  						Summary:     "Call to unknown function",
   314  						Detail:      fmt.Sprintf("There is no function named %q in namespace %s.%s", name, namespace, suggestion),
   315  						Subject:     &e.NameRange,
   316  						Context:     e.Range().Ptr(),
   317  						Expression:  e,
   318  						EvalContext: ctx,
   319  						Extra:       extraUnknown,
   320  					},
   321  				}
   322  			}
   323  		}
   324  
   325  		avail := make([]string, 0, len(ctx.Functions))
   326  		for name := range ctx.Functions {
   327  			avail = append(avail, name)
   328  		}
   329  		suggestion := nameSuggestion(e.Name, avail)
   330  		if suggestion != "" {
   331  			suggestion = fmt.Sprintf(" Did you mean %q?", suggestion)
   332  		}
   333  
   334  		return cty.DynamicVal, hcl.Diagnostics{
   335  			{
   336  				Severity:    hcl.DiagError,
   337  				Summary:     "Call to unknown function",
   338  				Detail:      fmt.Sprintf("There is no function named %q.%s", e.Name, suggestion),
   339  				Subject:     &e.NameRange,
   340  				Context:     e.Range().Ptr(),
   341  				Expression:  e,
   342  				EvalContext: ctx,
   343  				Extra:       extraUnknown,
   344  			},
   345  		}
   346  	}
   347  
   348  	diagExtra := functionCallDiagExtra{
   349  		calledFunctionName: e.Name,
   350  	}
   351  
   352  	params := f.Params()
   353  	varParam := f.VarParam()
   354  
   355  	args := e.Args
   356  	if e.ExpandFinal {
   357  		if len(args) < 1 {
   358  			// should never happen if the parser is behaving
   359  			panic("ExpandFinal set on function call with no arguments")
   360  		}
   361  		expandExpr := args[len(args)-1]
   362  		expandVal, expandDiags := expandExpr.Value(ctx)
   363  		diags = append(diags, expandDiags...)
   364  		if expandDiags.HasErrors() {
   365  			return cty.DynamicVal, diags
   366  		}
   367  
   368  		switch {
   369  		case expandVal.Type().Equals(cty.DynamicPseudoType):
   370  			if expandVal.IsNull() {
   371  				diags = append(diags, &hcl.Diagnostic{
   372  					Severity:    hcl.DiagError,
   373  					Summary:     "Invalid expanding argument value",
   374  					Detail:      "The expanding argument (indicated by ...) must not be null.",
   375  					Subject:     expandExpr.Range().Ptr(),
   376  					Context:     e.Range().Ptr(),
   377  					Expression:  expandExpr,
   378  					EvalContext: ctx,
   379  					Extra:       &diagExtra,
   380  				})
   381  				return cty.DynamicVal, diags
   382  			}
   383  			return cty.DynamicVal, diags
   384  		case expandVal.Type().IsTupleType() || expandVal.Type().IsListType() || expandVal.Type().IsSetType():
   385  			if expandVal.IsNull() {
   386  				diags = append(diags, &hcl.Diagnostic{
   387  					Severity:    hcl.DiagError,
   388  					Summary:     "Invalid expanding argument value",
   389  					Detail:      "The expanding argument (indicated by ...) must not be null.",
   390  					Subject:     expandExpr.Range().Ptr(),
   391  					Context:     e.Range().Ptr(),
   392  					Expression:  expandExpr,
   393  					EvalContext: ctx,
   394  					Extra:       &diagExtra,
   395  				})
   396  				return cty.DynamicVal, diags
   397  			}
   398  			if !expandVal.IsKnown() {
   399  				return cty.DynamicVal, diags
   400  			}
   401  
   402  			// When expanding arguments from a collection, we must first unmark
   403  			// the collection itself, and apply any marks directly to the
   404  			// elements. This ensures that marks propagate correctly.
   405  			expandVal, marks := expandVal.Unmark()
   406  			newArgs := make([]Expression, 0, (len(args)-1)+expandVal.LengthInt())
   407  			newArgs = append(newArgs, args[:len(args)-1]...)
   408  			it := expandVal.ElementIterator()
   409  			for it.Next() {
   410  				_, val := it.Element()
   411  				newArgs = append(newArgs, &LiteralValueExpr{
   412  					Val:      val.WithMarks(marks),
   413  					SrcRange: expandExpr.Range(),
   414  				})
   415  			}
   416  			args = newArgs
   417  		default:
   418  			diags = append(diags, &hcl.Diagnostic{
   419  				Severity:    hcl.DiagError,
   420  				Summary:     "Invalid expanding argument value",
   421  				Detail:      "The expanding argument (indicated by ...) must be of a tuple, list, or set type.",
   422  				Subject:     expandExpr.Range().Ptr(),
   423  				Context:     e.Range().Ptr(),
   424  				Expression:  expandExpr,
   425  				EvalContext: ctx,
   426  				Extra:       &diagExtra,
   427  			})
   428  			return cty.DynamicVal, diags
   429  		}
   430  	}
   431  
   432  	if len(args) < len(params) {
   433  		missing := params[len(args)]
   434  		qual := ""
   435  		if varParam != nil {
   436  			qual = " at least"
   437  		}
   438  		return cty.DynamicVal, hcl.Diagnostics{
   439  			{
   440  				Severity: hcl.DiagError,
   441  				Summary:  "Not enough function arguments",
   442  				Detail: fmt.Sprintf(
   443  					"Function %q expects%s %d argument(s). Missing value for %q.",
   444  					e.Name, qual, len(params), missing.Name,
   445  				),
   446  				Subject:     &e.CloseParenRange,
   447  				Context:     e.Range().Ptr(),
   448  				Expression:  e,
   449  				EvalContext: ctx,
   450  				Extra:       &diagExtra,
   451  			},
   452  		}
   453  	}
   454  
   455  	if varParam == nil && len(args) > len(params) {
   456  		return cty.DynamicVal, hcl.Diagnostics{
   457  			{
   458  				Severity: hcl.DiagError,
   459  				Summary:  "Too many function arguments",
   460  				Detail: fmt.Sprintf(
   461  					"Function %q expects only %d argument(s).",
   462  					e.Name, len(params),
   463  				),
   464  				Subject:     args[len(params)].StartRange().Ptr(),
   465  				Context:     e.Range().Ptr(),
   466  				Expression:  e,
   467  				EvalContext: ctx,
   468  				Extra:       &diagExtra,
   469  			},
   470  		}
   471  	}
   472  
   473  	argVals := make([]cty.Value, len(args))
   474  
   475  	for i, argExpr := range args {
   476  		var param *function.Parameter
   477  		if i < len(params) {
   478  			param = &params[i]
   479  		} else {
   480  			param = varParam
   481  		}
   482  
   483  		var val cty.Value
   484  		if decodeFn := customdecode.CustomExpressionDecoderForType(param.Type); decodeFn != nil {
   485  			var argDiags hcl.Diagnostics
   486  			val, argDiags = decodeFn(argExpr, ctx)
   487  			diags = append(diags, argDiags...)
   488  			if val == cty.NilVal {
   489  				val = cty.UnknownVal(param.Type)
   490  			}
   491  		} else {
   492  			var argDiags hcl.Diagnostics
   493  			val, argDiags = argExpr.Value(ctx)
   494  			if len(argDiags) > 0 {
   495  				diags = append(diags, argDiags...)
   496  			}
   497  
   498  			// Try to convert our value to the parameter type
   499  			var err error
   500  			val, err = convert.Convert(val, param.Type)
   501  			if err != nil {
   502  				diags = append(diags, &hcl.Diagnostic{
   503  					Severity: hcl.DiagError,
   504  					Summary:  "Invalid function argument",
   505  					Detail: fmt.Sprintf(
   506  						"Invalid value for %q parameter: %s.",
   507  						param.Name, err,
   508  					),
   509  					Subject:     argExpr.StartRange().Ptr(),
   510  					Context:     e.Range().Ptr(),
   511  					Expression:  argExpr,
   512  					EvalContext: ctx,
   513  					Extra:       &diagExtra,
   514  				})
   515  			}
   516  		}
   517  
   518  		argVals[i] = val
   519  	}
   520  
   521  	if diags.HasErrors() {
   522  		// Don't try to execute the function if we already have errors with
   523  		// the arguments, because the result will probably be a confusing
   524  		// error message.
   525  		return cty.DynamicVal, diags
   526  	}
   527  
   528  	resultVal, err := f.Call(argVals)
   529  	if err != nil {
   530  		// For errors in the underlying call itself we also return the raw
   531  		// call error via an extra method on our "diagnostic extra" value.
   532  		diagExtra.functionCallError = err
   533  
   534  		switch terr := err.(type) {
   535  		case function.ArgError:
   536  			i := terr.Index
   537  			var param *function.Parameter
   538  			if i < len(params) {
   539  				param = &params[i]
   540  			} else {
   541  				param = varParam
   542  			}
   543  
   544  			if param == nil || i > len(args)-1 {
   545  				// Getting here means that the function we called has a bug:
   546  				// it returned an arg error that refers to an argument index
   547  				// that wasn't present in the call. For that situation
   548  				// we'll degrade to a less specific error just to give
   549  				// some sort of answer, but best to still fix the buggy
   550  				// function so that it only returns argument indices that
   551  				// are in range.
   552  				switch {
   553  				case param != nil:
   554  					// In this case we'll assume that the function was trying
   555  					// to talk about a final variadic parameter but the caller
   556  					// didn't actually provide any arguments for it. That means
   557  					// we can at least still name the parameter in the
   558  					// error message, but our source range will be the call
   559  					// as a whole because we don't have an argument expression
   560  					// to highlight specifically.
   561  					diags = append(diags, &hcl.Diagnostic{
   562  						Severity: hcl.DiagError,
   563  						Summary:  "Invalid function argument",
   564  						Detail: fmt.Sprintf(
   565  							"Invalid value for %q parameter: %s.",
   566  							param.Name, err,
   567  						),
   568  						Subject:     e.Range().Ptr(),
   569  						Expression:  e,
   570  						EvalContext: ctx,
   571  						Extra:       &diagExtra,
   572  					})
   573  				default:
   574  					// This is the most degenerate case of all, where the
   575  					// index is out of range even for the declared parameters,
   576  					// and so we can't tell which parameter the function is
   577  					// trying to report an error for. Just a generic error
   578  					// report in that case.
   579  					diags = append(diags, &hcl.Diagnostic{
   580  						Severity: hcl.DiagError,
   581  						Summary:  "Error in function call",
   582  						Detail: fmt.Sprintf(
   583  							"Call to function %q failed: %s.",
   584  							e.Name, err,
   585  						),
   586  						Subject:     e.StartRange().Ptr(),
   587  						Context:     e.Range().Ptr(),
   588  						Expression:  e,
   589  						EvalContext: ctx,
   590  						Extra:       &diagExtra,
   591  					})
   592  				}
   593  			} else {
   594  				argExpr := args[i]
   595  
   596  				// TODO: we should also unpick a PathError here and show the
   597  				// path to the deep value where the error was detected.
   598  				diags = append(diags, &hcl.Diagnostic{
   599  					Severity: hcl.DiagError,
   600  					Summary:  "Invalid function argument",
   601  					Detail: fmt.Sprintf(
   602  						"Invalid value for %q parameter: %s.",
   603  						param.Name, err,
   604  					),
   605  					Subject:     argExpr.StartRange().Ptr(),
   606  					Context:     e.Range().Ptr(),
   607  					Expression:  argExpr,
   608  					EvalContext: ctx,
   609  					Extra:       &diagExtra,
   610  				})
   611  			}
   612  
   613  		default:
   614  			diags = append(diags, &hcl.Diagnostic{
   615  				Severity: hcl.DiagError,
   616  				Summary:  "Error in function call",
   617  				Detail: fmt.Sprintf(
   618  					"Call to function %q failed: %s.",
   619  					e.Name, err,
   620  				),
   621  				Subject:     e.StartRange().Ptr(),
   622  				Context:     e.Range().Ptr(),
   623  				Expression:  e,
   624  				EvalContext: ctx,
   625  				Extra:       &diagExtra,
   626  			})
   627  		}
   628  
   629  		return cty.DynamicVal, diags
   630  	}
   631  
   632  	return resultVal, diags
   633  }
   634  
   635  func (e *FunctionCallExpr) Range() hcl.Range {
   636  	return hcl.RangeBetween(e.NameRange, e.CloseParenRange)
   637  }
   638  
   639  func (e *FunctionCallExpr) StartRange() hcl.Range {
   640  	return hcl.RangeBetween(e.NameRange, e.OpenParenRange)
   641  }
   642  
   643  // Implementation for hcl.ExprCall.
   644  func (e *FunctionCallExpr) ExprCall() *hcl.StaticCall {
   645  	ret := &hcl.StaticCall{
   646  		Name:      e.Name,
   647  		NameRange: e.NameRange,
   648  		Arguments: make([]hcl.Expression, len(e.Args)),
   649  		ArgsRange: hcl.RangeBetween(e.OpenParenRange, e.CloseParenRange),
   650  	}
   651  	// Need to convert our own Expression objects into hcl.Expression.
   652  	for i, arg := range e.Args {
   653  		ret.Arguments[i] = arg
   654  	}
   655  	return ret
   656  }
   657  
   658  // FunctionCallDiagExtra is an interface implemented by the value in the "Extra"
   659  // field of some diagnostics returned by FunctionCallExpr.Value, giving
   660  // cooperating callers access to some machine-readable information about the
   661  // call that a diagnostic relates to.
   662  type FunctionCallDiagExtra interface {
   663  	// CalledFunctionName returns the name of the function being called at
   664  	// the time the diagnostic was generated, if any. Returns an empty string
   665  	// if there is no known called function.
   666  	CalledFunctionName() string
   667  
   668  	// FunctionCallError returns the error value returned by the implementation
   669  	// of the function being called, if any. Returns nil if the diagnostic was
   670  	// not returned in response to a call error.
   671  	//
   672  	// Some errors related to calling functions are generated by HCL itself
   673  	// rather than by the underlying function, in which case this method
   674  	// will return nil.
   675  	FunctionCallError() error
   676  }
   677  
   678  type functionCallDiagExtra struct {
   679  	calledFunctionName string
   680  	functionCallError  error
   681  }
   682  
   683  func (e *functionCallDiagExtra) CalledFunctionName() string {
   684  	return e.calledFunctionName
   685  }
   686  
   687  func (e *functionCallDiagExtra) FunctionCallError() error {
   688  	return e.functionCallError
   689  }
   690  
   691  // FunctionCallUnknownDiagExtra is an interface implemented by a value in the Extra
   692  // field of some diagnostics to indicate when the error was caused by a call to
   693  // an unknown function.
   694  type FunctionCallUnknownDiagExtra interface {
   695  	CalledFunctionName() string
   696  	CalledFunctionNamespace() string
   697  }
   698  
   699  type functionCallUnknown struct {
   700  	name      string
   701  	namespace string
   702  }
   703  
   704  func (e *functionCallUnknown) CalledFunctionName() string {
   705  	return e.name
   706  }
   707  
   708  func (e *functionCallUnknown) CalledFunctionNamespace() string {
   709  	return e.namespace
   710  }
   711  
   712  type ConditionalExpr struct {
   713  	Condition   Expression
   714  	TrueResult  Expression
   715  	FalseResult Expression
   716  
   717  	SrcRange hcl.Range
   718  }
   719  
   720  func (e *ConditionalExpr) walkChildNodes(w internalWalkFunc) {
   721  	w(e.Condition)
   722  	w(e.TrueResult)
   723  	w(e.FalseResult)
   724  }
   725  
   726  func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
   727  	trueResult, trueDiags := e.TrueResult.Value(ctx)
   728  	falseResult, falseDiags := e.FalseResult.Value(ctx)
   729  	var diags hcl.Diagnostics
   730  
   731  	resultType := cty.DynamicPseudoType
   732  	convs := make([]convert.Conversion, 2)
   733  
   734  	switch {
   735  	// If either case is a dynamic null value (which would result from a
   736  	// literal null in the config), we know that it can convert to the expected
   737  	// type of the opposite case, and we don't need to speculatively reduce the
   738  	// final result type to DynamicPseudoType.
   739  
   740  	// If we know that either Type is a DynamicPseudoType, we can be certain
   741  	// that the other value can convert since it's a pass-through, and we don't
   742  	// need to unify the types. If the final evaluation results in the dynamic
   743  	// value being returned, there's no conversion we can do, so we return the
   744  	// value directly.
   745  	case trueResult.RawEquals(cty.NullVal(cty.DynamicPseudoType)):
   746  		resultType = falseResult.Type()
   747  		convs[0] = convert.GetConversionUnsafe(cty.DynamicPseudoType, resultType)
   748  	case falseResult.RawEquals(cty.NullVal(cty.DynamicPseudoType)):
   749  		resultType = trueResult.Type()
   750  		convs[1] = convert.GetConversionUnsafe(cty.DynamicPseudoType, resultType)
   751  	case trueResult.Type() == cty.DynamicPseudoType, falseResult.Type() == cty.DynamicPseudoType:
   752  		// the final resultType type is still unknown
   753  		// we don't need to get the conversion, because both are a noop.
   754  
   755  	default:
   756  		// Try to find a type that both results can be converted to.
   757  		resultType, convs = convert.UnifyUnsafe([]cty.Type{trueResult.Type(), falseResult.Type()})
   758  	}
   759  
   760  	if resultType == cty.NilType {
   761  		return cty.DynamicVal, hcl.Diagnostics{
   762  			{
   763  				Severity: hcl.DiagError,
   764  				Summary:  "Inconsistent conditional result types",
   765  				Detail: fmt.Sprintf(
   766  					"The true and false result expressions must have consistent types. %s.",
   767  					describeConditionalTypeMismatch(trueResult.Type(), falseResult.Type()),
   768  				),
   769  				Subject:     hcl.RangeBetween(e.TrueResult.Range(), e.FalseResult.Range()).Ptr(),
   770  				Context:     &e.SrcRange,
   771  				Expression:  e,
   772  				EvalContext: ctx,
   773  			},
   774  		}
   775  	}
   776  
   777  	condResult, condDiags := e.Condition.Value(ctx)
   778  	diags = append(diags, condDiags...)
   779  	if condResult.IsNull() {
   780  		diags = append(diags, &hcl.Diagnostic{
   781  			Severity:    hcl.DiagError,
   782  			Summary:     "Null condition",
   783  			Detail:      "The condition value is null. Conditions must either be true or false.",
   784  			Subject:     e.Condition.Range().Ptr(),
   785  			Context:     &e.SrcRange,
   786  			Expression:  e.Condition,
   787  			EvalContext: ctx,
   788  		})
   789  		return cty.UnknownVal(resultType), diags
   790  	}
   791  	if !condResult.IsKnown() {
   792  		// we use the unmarked values throughout the unknown branch
   793  		_, condResultMarks := condResult.Unmark()
   794  		trueResult, trueResultMarks := trueResult.Unmark()
   795  		falseResult, falseResultMarks := falseResult.Unmark()
   796  
   797  		// use a value to merge marks
   798  		_, resMarks := cty.DynamicVal.WithMarks(condResultMarks, trueResultMarks, falseResultMarks).Unmark()
   799  
   800  		trueRange := trueResult.Range()
   801  		falseRange := falseResult.Range()
   802  
   803  		// if both branches are known to be null, then the result must still be null
   804  		if trueResult.IsNull() && falseResult.IsNull() {
   805  			return cty.NullVal(resultType).WithMarks(resMarks), diags
   806  		}
   807  
   808  		// We might be able to offer a refined range for the result based on
   809  		// the two possible outcomes.
   810  		if trueResult.Type() == cty.Number && falseResult.Type() == cty.Number {
   811  			ref := cty.UnknownVal(cty.Number).Refine()
   812  			if trueRange.DefinitelyNotNull() && falseRange.DefinitelyNotNull() {
   813  				ref = ref.NotNull()
   814  			}
   815  
   816  			falseLo, falseLoInc := falseRange.NumberLowerBound()
   817  			falseHi, falseHiInc := falseRange.NumberUpperBound()
   818  			trueLo, trueLoInc := trueRange.NumberLowerBound()
   819  			trueHi, trueHiInc := trueRange.NumberUpperBound()
   820  
   821  			if falseLo.IsKnown() && trueLo.IsKnown() {
   822  				lo, loInc := falseLo, falseLoInc
   823  				switch {
   824  				case trueLo.LessThan(falseLo).True():
   825  					lo, loInc = trueLo, trueLoInc
   826  				case trueLo.Equals(falseLo).True():
   827  					loInc = trueLoInc || falseLoInc
   828  				}
   829  
   830  				ref = ref.NumberRangeLowerBound(lo, loInc)
   831  			}
   832  
   833  			if falseHi.IsKnown() && trueHi.IsKnown() {
   834  				hi, hiInc := falseHi, falseHiInc
   835  				switch {
   836  				case trueHi.GreaterThan(falseHi).True():
   837  					hi, hiInc = trueHi, trueHiInc
   838  				case trueHi.Equals(falseHi).True():
   839  					hiInc = trueHiInc || falseHiInc
   840  				}
   841  				ref = ref.NumberRangeUpperBound(hi, hiInc)
   842  			}
   843  
   844  			return ref.NewValue().WithMarks(resMarks), diags
   845  		}
   846  
   847  		if trueResult.Type().IsCollectionType() && falseResult.Type().IsCollectionType() {
   848  			if trueResult.Type().Equals(falseResult.Type()) {
   849  				ref := cty.UnknownVal(resultType).Refine()
   850  				if trueRange.DefinitelyNotNull() && falseRange.DefinitelyNotNull() {
   851  					ref = ref.NotNull()
   852  				}
   853  
   854  				falseLo := falseRange.LengthLowerBound()
   855  				falseHi := falseRange.LengthUpperBound()
   856  				trueLo := trueRange.LengthLowerBound()
   857  				trueHi := trueRange.LengthUpperBound()
   858  
   859  				lo := falseLo
   860  				if trueLo < falseLo {
   861  					lo = trueLo
   862  				}
   863  
   864  				hi := falseHi
   865  				if trueHi > falseHi {
   866  					hi = trueHi
   867  				}
   868  
   869  				ref = ref.CollectionLengthLowerBound(lo).CollectionLengthUpperBound(hi)
   870  				return ref.NewValue().WithMarks(resMarks), diags
   871  			}
   872  		}
   873  
   874  		ret := cty.UnknownVal(resultType)
   875  		if trueRange.DefinitelyNotNull() && falseRange.DefinitelyNotNull() {
   876  			ret = ret.RefineNotNull()
   877  		}
   878  		return ret.WithMarks(resMarks), diags
   879  	}
   880  
   881  	condResult, err := convert.Convert(condResult, cty.Bool)
   882  	if err != nil {
   883  		diags = append(diags, &hcl.Diagnostic{
   884  			Severity:    hcl.DiagError,
   885  			Summary:     "Incorrect condition type",
   886  			Detail:      "The condition expression must be of type bool.",
   887  			Subject:     e.Condition.Range().Ptr(),
   888  			Context:     &e.SrcRange,
   889  			Expression:  e.Condition,
   890  			EvalContext: ctx,
   891  		})
   892  		return cty.UnknownVal(resultType), diags
   893  	}
   894  
   895  	// Unmark result before testing for truthiness
   896  	condResult, _ = condResult.UnmarkDeep()
   897  	if condResult.True() {
   898  		diags = append(diags, trueDiags...)
   899  		if convs[0] != nil {
   900  			var err error
   901  			trueResult, err = convs[0](trueResult)
   902  			if err != nil {
   903  				// Unsafe conversion failed with the concrete result value
   904  				diags = append(diags, &hcl.Diagnostic{
   905  					Severity: hcl.DiagError,
   906  					Summary:  "Inconsistent conditional result types",
   907  					Detail: fmt.Sprintf(
   908  						"The true result value has the wrong type: %s.",
   909  						err.Error(),
   910  					),
   911  					Subject:     e.TrueResult.Range().Ptr(),
   912  					Context:     &e.SrcRange,
   913  					Expression:  e.TrueResult,
   914  					EvalContext: ctx,
   915  				})
   916  				trueResult = cty.UnknownVal(resultType)
   917  			}
   918  		}
   919  		return trueResult, diags
   920  	} else {
   921  		diags = append(diags, falseDiags...)
   922  		if convs[1] != nil {
   923  			var err error
   924  			falseResult, err = convs[1](falseResult)
   925  			if err != nil {
   926  				// Unsafe conversion failed with the concrete result value
   927  				diags = append(diags, &hcl.Diagnostic{
   928  					Severity: hcl.DiagError,
   929  					Summary:  "Inconsistent conditional result types",
   930  					Detail: fmt.Sprintf(
   931  						"The false result value has the wrong type: %s.",
   932  						err.Error(),
   933  					),
   934  					Subject:     e.FalseResult.Range().Ptr(),
   935  					Context:     &e.SrcRange,
   936  					Expression:  e.FalseResult,
   937  					EvalContext: ctx,
   938  				})
   939  				falseResult = cty.UnknownVal(resultType)
   940  			}
   941  		}
   942  		return falseResult, diags
   943  	}
   944  }
   945  
   946  // describeConditionalTypeMismatch makes a best effort to describe the
   947  // difference between types in the true and false arms of a conditional
   948  // expression in a way that would be useful to someone trying to understand
   949  // why their conditional expression isn't valid.
   950  //
   951  // NOTE: This function is only designed to deal with situations
   952  // where trueTy and falseTy are different. Calling it with two equal
   953  // types will produce a nonsense result. This function also only really
   954  // deals with situations that type unification can't resolve, so we should
   955  // call this function only after trying type unification first.
   956  func describeConditionalTypeMismatch(trueTy, falseTy cty.Type) string {
   957  	// The main tricky cases here are when both trueTy and falseTy are
   958  	// of the same structural type kind, such as both being object types
   959  	// or both being tuple types. In that case the "FriendlyName" method
   960  	// returns only "object" or "tuple" and so we need to do some more
   961  	// work to describe what's different inside them.
   962  
   963  	switch {
   964  	case trueTy.IsObjectType() && falseTy.IsObjectType():
   965  		// We'll first gather up the attribute names and sort them. In the
   966  		// event that there are multiple attributes that disagree across
   967  		// the two types, we'll prefer to report the one that sorts lexically
   968  		// least just so that our error message is consistent between
   969  		// evaluations.
   970  		var trueAttrs, falseAttrs []string
   971  		for name := range trueTy.AttributeTypes() {
   972  			trueAttrs = append(trueAttrs, name)
   973  		}
   974  		sort.Strings(trueAttrs)
   975  		for name := range falseTy.AttributeTypes() {
   976  			falseAttrs = append(falseAttrs, name)
   977  		}
   978  		sort.Strings(falseAttrs)
   979  
   980  		for _, name := range trueAttrs {
   981  			if !falseTy.HasAttribute(name) {
   982  				return fmt.Sprintf("The 'true' value includes object attribute %q, which is absent in the 'false' value", name)
   983  			}
   984  			trueAty := trueTy.AttributeType(name)
   985  			falseAty := falseTy.AttributeType(name)
   986  			if !trueAty.Equals(falseAty) {
   987  				// For deeply-nested differences this will likely get very
   988  				// clunky quickly by nesting these messages inside one another,
   989  				// but we'll accept that for now in the interests of producing
   990  				// _some_ useful feedback, even if it isn't as concise as
   991  				// we'd prefer it to be. Deeply-nested structures in
   992  				// conditionals are thankfully not super common.
   993  				return fmt.Sprintf(
   994  					"Type mismatch for object attribute %q: %s",
   995  					name, describeConditionalTypeMismatch(trueAty, falseAty),
   996  				)
   997  			}
   998  		}
   999  		for _, name := range falseAttrs {
  1000  			if !trueTy.HasAttribute(name) {
  1001  				return fmt.Sprintf("The 'false' value includes object attribute %q, which is absent in the 'true' value", name)
  1002  			}
  1003  			// NOTE: We don't need to check the attribute types again, because
  1004  			// any attribute that both types have in common would already have
  1005  			// been checked in the previous loop.
  1006  		}
  1007  	case trueTy.IsTupleType() && falseTy.IsTupleType():
  1008  		trueEtys := trueTy.TupleElementTypes()
  1009  		falseEtys := falseTy.TupleElementTypes()
  1010  
  1011  		if trueCount, falseCount := len(trueEtys), len(falseEtys); trueCount != falseCount {
  1012  			return fmt.Sprintf("The 'true' tuple has length %d, but the 'false' tuple has length %d", trueCount, falseCount)
  1013  		}
  1014  
  1015  		// NOTE: Thanks to the condition above, we know that both tuples are
  1016  		// of the same length and so they must have some differing types
  1017  		// instead.
  1018  		for i := range trueEtys {
  1019  			trueEty := trueEtys[i]
  1020  			falseEty := falseEtys[i]
  1021  
  1022  			if !trueEty.Equals(falseEty) {
  1023  				// For deeply-nested differences this will likely get very
  1024  				// clunky quickly by nesting these messages inside one another,
  1025  				// but we'll accept that for now in the interests of producing
  1026  				// _some_ useful feedback, even if it isn't as concise as
  1027  				// we'd prefer it to be. Deeply-nested structures in
  1028  				// conditionals are thankfully not super common.
  1029  				return fmt.Sprintf(
  1030  					"Type mismatch for tuple element %d: %s",
  1031  					i, describeConditionalTypeMismatch(trueEty, falseEty),
  1032  				)
  1033  			}
  1034  		}
  1035  	case trueTy.IsCollectionType() && falseTy.IsCollectionType():
  1036  		// For this case we're specifically interested in the situation where:
  1037  		// - both collections are of the same kind, AND
  1038  		// - the element types of both are either object or tuple types.
  1039  		// This is just to avoid writing a useless statement like
  1040  		// "The 'true' value is list of object, but the 'false' value is list of object".
  1041  		// This still doesn't account for more awkward cases like collections
  1042  		// of collections of structural types, but we won't let perfect be
  1043  		// the enemy of the good.
  1044  		trueEty := trueTy.ElementType()
  1045  		falseEty := falseTy.ElementType()
  1046  		if (trueTy.IsListType() && falseTy.IsListType()) || (trueTy.IsMapType() && falseTy.IsMapType()) || (trueTy.IsSetType() && falseTy.IsSetType()) {
  1047  			if (trueEty.IsObjectType() && falseEty.IsObjectType()) || (trueEty.IsTupleType() && falseEty.IsTupleType()) {
  1048  				noun := "collection"
  1049  				switch { // NOTE: We now know that trueTy and falseTy have the same collection kind
  1050  				case trueTy.IsListType():
  1051  					noun = "list"
  1052  				case trueTy.IsSetType():
  1053  					noun = "set"
  1054  				case trueTy.IsMapType():
  1055  					noun = "map"
  1056  				}
  1057  				return fmt.Sprintf(
  1058  					"Mismatched %s element types: %s",
  1059  					noun, describeConditionalTypeMismatch(trueEty, falseEty),
  1060  				)
  1061  			}
  1062  		}
  1063  	}
  1064  
  1065  	// If we don't manage any more specialized message, we'll just report
  1066  	// what the two types are.
  1067  	trueName := trueTy.FriendlyName()
  1068  	falseName := falseTy.FriendlyName()
  1069  	if trueName == falseName {
  1070  		// Absolute last resort for when we have no special rule above but
  1071  		// we have two types with the same friendly name anyway. This is
  1072  		// the most vague of all possible messages but is reserved for
  1073  		// particularly awkward cases, like lists of lists of differing tuple
  1074  		// types.
  1075  		return "At least one deeply-nested attribute or element is not compatible across both the 'true' and the 'false' value"
  1076  	}
  1077  	return fmt.Sprintf(
  1078  		"The 'true' value is %s, but the 'false' value is %s",
  1079  		trueTy.FriendlyName(), falseTy.FriendlyName(),
  1080  	)
  1081  
  1082  }
  1083  
  1084  func (e *ConditionalExpr) Range() hcl.Range {
  1085  	return e.SrcRange
  1086  }
  1087  
  1088  func (e *ConditionalExpr) StartRange() hcl.Range {
  1089  	return e.Condition.StartRange()
  1090  }
  1091  
  1092  type IndexExpr struct {
  1093  	Collection Expression
  1094  	Key        Expression
  1095  
  1096  	SrcRange     hcl.Range
  1097  	OpenRange    hcl.Range
  1098  	BracketRange hcl.Range
  1099  }
  1100  
  1101  func (e *IndexExpr) walkChildNodes(w internalWalkFunc) {
  1102  	w(e.Collection)
  1103  	w(e.Key)
  1104  }
  1105  
  1106  func (e *IndexExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
  1107  	var diags hcl.Diagnostics
  1108  	coll, collDiags := e.Collection.Value(ctx)
  1109  	key, keyDiags := e.Key.Value(ctx)
  1110  	diags = append(diags, collDiags...)
  1111  	diags = append(diags, keyDiags...)
  1112  
  1113  	val, indexDiags := hcl.Index(coll, key, &e.BracketRange)
  1114  	setDiagEvalContext(indexDiags, e, ctx)
  1115  	diags = append(diags, indexDiags...)
  1116  	return val, diags
  1117  }
  1118  
  1119  func (e *IndexExpr) Range() hcl.Range {
  1120  	return e.SrcRange
  1121  }
  1122  
  1123  func (e *IndexExpr) StartRange() hcl.Range {
  1124  	return e.OpenRange
  1125  }
  1126  
  1127  type TupleConsExpr struct {
  1128  	Exprs []Expression
  1129  
  1130  	SrcRange  hcl.Range
  1131  	OpenRange hcl.Range
  1132  }
  1133  
  1134  func (e *TupleConsExpr) walkChildNodes(w internalWalkFunc) {
  1135  	for _, expr := range e.Exprs {
  1136  		w(expr)
  1137  	}
  1138  }
  1139  
  1140  func (e *TupleConsExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
  1141  	var vals []cty.Value
  1142  	var diags hcl.Diagnostics
  1143  
  1144  	vals = make([]cty.Value, len(e.Exprs))
  1145  	for i, expr := range e.Exprs {
  1146  		val, valDiags := expr.Value(ctx)
  1147  		vals[i] = val
  1148  		diags = append(diags, valDiags...)
  1149  	}
  1150  
  1151  	return cty.TupleVal(vals), diags
  1152  }
  1153  
  1154  func (e *TupleConsExpr) Range() hcl.Range {
  1155  	return e.SrcRange
  1156  }
  1157  
  1158  func (e *TupleConsExpr) StartRange() hcl.Range {
  1159  	return e.OpenRange
  1160  }
  1161  
  1162  // Implementation for hcl.ExprList
  1163  func (e *TupleConsExpr) ExprList() []hcl.Expression {
  1164  	ret := make([]hcl.Expression, len(e.Exprs))
  1165  	for i, expr := range e.Exprs {
  1166  		ret[i] = expr
  1167  	}
  1168  	return ret
  1169  }
  1170  
  1171  type ObjectConsExpr struct {
  1172  	Items []ObjectConsItem
  1173  
  1174  	SrcRange  hcl.Range
  1175  	OpenRange hcl.Range
  1176  }
  1177  
  1178  type ObjectConsItem struct {
  1179  	KeyExpr   Expression
  1180  	ValueExpr Expression
  1181  }
  1182  
  1183  func (e *ObjectConsExpr) walkChildNodes(w internalWalkFunc) {
  1184  	for _, item := range e.Items {
  1185  		w(item.KeyExpr)
  1186  		w(item.ValueExpr)
  1187  	}
  1188  }
  1189  
  1190  func (e *ObjectConsExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
  1191  	var vals map[string]cty.Value
  1192  	var diags hcl.Diagnostics
  1193  	var marks []cty.ValueMarks
  1194  
  1195  	// This will get set to true if we fail to produce any of our keys,
  1196  	// either because they are actually unknown or if the evaluation produces
  1197  	// errors. In all of these case we must return DynamicPseudoType because
  1198  	// we're unable to know the full set of keys our object has, and thus
  1199  	// we can't produce a complete value of the intended type.
  1200  	//
  1201  	// We still evaluate all of the item keys and values to make sure that we
  1202  	// get as complete as possible a set of diagnostics.
  1203  	known := true
  1204  
  1205  	vals = make(map[string]cty.Value, len(e.Items))
  1206  	for _, item := range e.Items {
  1207  		key, keyDiags := item.KeyExpr.Value(ctx)
  1208  		diags = append(diags, keyDiags...)
  1209  
  1210  		val, valDiags := item.ValueExpr.Value(ctx)
  1211  		diags = append(diags, valDiags...)
  1212  
  1213  		if keyDiags.HasErrors() {
  1214  			known = false
  1215  			continue
  1216  		}
  1217  
  1218  		if key.IsNull() {
  1219  			diags = append(diags, &hcl.Diagnostic{
  1220  				Severity:    hcl.DiagError,
  1221  				Summary:     "Null value as key",
  1222  				Detail:      "Can't use a null value as a key.",
  1223  				Subject:     item.ValueExpr.Range().Ptr(),
  1224  				Expression:  item.KeyExpr,
  1225  				EvalContext: ctx,
  1226  			})
  1227  			known = false
  1228  			continue
  1229  		}
  1230  
  1231  		key, keyMarks := key.Unmark()
  1232  		marks = append(marks, keyMarks)
  1233  
  1234  		var err error
  1235  		key, err = convert.Convert(key, cty.String)
  1236  		if err != nil {
  1237  			diags = append(diags, &hcl.Diagnostic{
  1238  				Severity:    hcl.DiagError,
  1239  				Summary:     "Incorrect key type",
  1240  				Detail:      fmt.Sprintf("Can't use this value as a key: %s.", err.Error()),
  1241  				Subject:     item.KeyExpr.Range().Ptr(),
  1242  				Expression:  item.KeyExpr,
  1243  				EvalContext: ctx,
  1244  			})
  1245  			known = false
  1246  			continue
  1247  		}
  1248  
  1249  		if !key.IsKnown() {
  1250  			known = false
  1251  			continue
  1252  		}
  1253  
  1254  		keyStr := key.AsString()
  1255  
  1256  		vals[keyStr] = val
  1257  	}
  1258  
  1259  	if !known {
  1260  		return cty.DynamicVal, diags
  1261  	}
  1262  
  1263  	return cty.ObjectVal(vals).WithMarks(marks...), diags
  1264  }
  1265  
  1266  func (e *ObjectConsExpr) Range() hcl.Range {
  1267  	return e.SrcRange
  1268  }
  1269  
  1270  func (e *ObjectConsExpr) StartRange() hcl.Range {
  1271  	return e.OpenRange
  1272  }
  1273  
  1274  // Implementation for hcl.ExprMap
  1275  func (e *ObjectConsExpr) ExprMap() []hcl.KeyValuePair {
  1276  	ret := make([]hcl.KeyValuePair, len(e.Items))
  1277  	for i, item := range e.Items {
  1278  		ret[i] = hcl.KeyValuePair{
  1279  			Key:   item.KeyExpr,
  1280  			Value: item.ValueExpr,
  1281  		}
  1282  	}
  1283  	return ret
  1284  }
  1285  
  1286  // ObjectConsKeyExpr is a special wrapper used only for ObjectConsExpr keys,
  1287  // which deals with the special case that a naked identifier in that position
  1288  // must be interpreted as a literal string rather than evaluated directly.
  1289  type ObjectConsKeyExpr struct {
  1290  	Wrapped         Expression
  1291  	ForceNonLiteral bool
  1292  }
  1293  
  1294  func (e *ObjectConsKeyExpr) literalName() string {
  1295  	// This is our logic for deciding whether to behave like a literal string.
  1296  	// We lean on our AbsTraversalForExpr implementation here, which already
  1297  	// deals with some awkward cases like the expression being the result
  1298  	// of the keywords "null", "true" and "false" which we'd want to interpret
  1299  	// as keys here too.
  1300  	return hcl.ExprAsKeyword(e.Wrapped)
  1301  }
  1302  
  1303  func (e *ObjectConsKeyExpr) walkChildNodes(w internalWalkFunc) {
  1304  	// We only treat our wrapped expression as a real expression if we're
  1305  	// not going to interpret it as a literal.
  1306  	if e.literalName() == "" {
  1307  		w(e.Wrapped)
  1308  	}
  1309  }
  1310  
  1311  func (e *ObjectConsKeyExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
  1312  	// Because we accept a naked identifier as a literal key rather than a
  1313  	// reference, it's confusing to accept a traversal containing periods
  1314  	// here since we can't tell if the user intends to create a key with
  1315  	// periods or actually reference something. To avoid confusing downstream
  1316  	// errors we'll just prohibit a naked multi-step traversal here and
  1317  	// require the user to state their intent more clearly.
  1318  	// (This is handled at evaluation time rather than parse time because
  1319  	// an application using static analysis _can_ accept a naked multi-step
  1320  	// traversal here, if desired.)
  1321  	if !e.ForceNonLiteral {
  1322  		if travExpr, isTraversal := e.Wrapped.(*ScopeTraversalExpr); isTraversal && len(travExpr.Traversal) > 1 {
  1323  			var diags hcl.Diagnostics
  1324  			diags = append(diags, &hcl.Diagnostic{
  1325  				Severity: hcl.DiagError,
  1326  				Summary:  "Ambiguous attribute key",
  1327  				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.",
  1328  				Subject:  e.Range().Ptr(),
  1329  			})
  1330  			return cty.DynamicVal, diags
  1331  		}
  1332  
  1333  		if ln := e.literalName(); ln != "" {
  1334  			return cty.StringVal(ln), nil
  1335  		}
  1336  	}
  1337  	return e.Wrapped.Value(ctx)
  1338  }
  1339  
  1340  func (e *ObjectConsKeyExpr) Range() hcl.Range {
  1341  	return e.Wrapped.Range()
  1342  }
  1343  
  1344  func (e *ObjectConsKeyExpr) StartRange() hcl.Range {
  1345  	return e.Wrapped.StartRange()
  1346  }
  1347  
  1348  // Implementation for hcl.AbsTraversalForExpr.
  1349  func (e *ObjectConsKeyExpr) AsTraversal() hcl.Traversal {
  1350  	// If we're forcing a non-literal then we can never be interpreted
  1351  	// as a traversal.
  1352  	if e.ForceNonLiteral {
  1353  		return nil
  1354  	}
  1355  
  1356  	// We can produce a traversal only if our wrappee can.
  1357  	st, diags := hcl.AbsTraversalForExpr(e.Wrapped)
  1358  	if diags.HasErrors() {
  1359  		return nil
  1360  	}
  1361  
  1362  	return st
  1363  }
  1364  
  1365  func (e *ObjectConsKeyExpr) UnwrapExpression() Expression {
  1366  	return e.Wrapped
  1367  }
  1368  
  1369  // ForExpr represents iteration constructs:
  1370  //
  1371  //	tuple = [for i, v in list: upper(v) if i > 2]
  1372  //	object = {for k, v in map: k => upper(v)}
  1373  //	object_of_tuples = {for v in list: v.key: v...}
  1374  type ForExpr struct {
  1375  	KeyVar string // empty if ignoring the key
  1376  	ValVar string
  1377  
  1378  	CollExpr Expression
  1379  
  1380  	KeyExpr  Expression // nil when producing a tuple
  1381  	ValExpr  Expression
  1382  	CondExpr Expression // null if no "if" clause is present
  1383  
  1384  	Group bool // set if the ellipsis is used on the value in an object for
  1385  
  1386  	SrcRange   hcl.Range
  1387  	OpenRange  hcl.Range
  1388  	CloseRange hcl.Range
  1389  }
  1390  
  1391  func (e *ForExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
  1392  	var diags hcl.Diagnostics
  1393  	var marks []cty.ValueMarks
  1394  
  1395  	collVal, collDiags := e.CollExpr.Value(ctx)
  1396  	diags = append(diags, collDiags...)
  1397  
  1398  	if collVal.IsNull() {
  1399  		diags = append(diags, &hcl.Diagnostic{
  1400  			Severity:    hcl.DiagError,
  1401  			Summary:     "Iteration over null value",
  1402  			Detail:      "A null value cannot be used as the collection in a 'for' expression.",
  1403  			Subject:     e.CollExpr.Range().Ptr(),
  1404  			Context:     &e.SrcRange,
  1405  			Expression:  e.CollExpr,
  1406  			EvalContext: ctx,
  1407  		})
  1408  		return cty.DynamicVal, diags
  1409  	}
  1410  	if collVal.Type() == cty.DynamicPseudoType {
  1411  		return cty.DynamicVal, diags
  1412  	}
  1413  	// Unmark collection before checking for iterability, because marked
  1414  	// values cannot be iterated
  1415  	collVal, collMarks := collVal.Unmark()
  1416  	marks = append(marks, collMarks)
  1417  	if !collVal.CanIterateElements() {
  1418  		diags = append(diags, &hcl.Diagnostic{
  1419  			Severity: hcl.DiagError,
  1420  			Summary:  "Iteration over non-iterable value",
  1421  			Detail: fmt.Sprintf(
  1422  				"A value of type %s cannot be used as the collection in a 'for' expression.",
  1423  				collVal.Type().FriendlyName(),
  1424  			),
  1425  			Subject:     e.CollExpr.Range().Ptr(),
  1426  			Context:     &e.SrcRange,
  1427  			Expression:  e.CollExpr,
  1428  			EvalContext: ctx,
  1429  		})
  1430  		return cty.DynamicVal, diags
  1431  	}
  1432  	if !collVal.IsKnown() {
  1433  		return cty.DynamicVal, diags
  1434  	}
  1435  
  1436  	// Before we start we'll do an early check to see if any CondExpr we've
  1437  	// been given is of the wrong type. This isn't 100% reliable (it may
  1438  	// be DynamicVal until real values are given) but it should catch some
  1439  	// straightforward cases and prevent a barrage of repeated errors.
  1440  	if e.CondExpr != nil {
  1441  		childCtx := ctx.NewChild()
  1442  		childCtx.Variables = map[string]cty.Value{}
  1443  		if e.KeyVar != "" {
  1444  			childCtx.Variables[e.KeyVar] = cty.DynamicVal
  1445  		}
  1446  		childCtx.Variables[e.ValVar] = cty.DynamicVal
  1447  
  1448  		result, condDiags := e.CondExpr.Value(childCtx)
  1449  		diags = append(diags, condDiags...)
  1450  		if result.IsNull() {
  1451  			diags = append(diags, &hcl.Diagnostic{
  1452  				Severity:    hcl.DiagError,
  1453  				Summary:     "Condition is null",
  1454  				Detail:      "The value of the 'if' clause must not be null.",
  1455  				Subject:     e.CondExpr.Range().Ptr(),
  1456  				Context:     &e.SrcRange,
  1457  				Expression:  e.CondExpr,
  1458  				EvalContext: ctx,
  1459  			})
  1460  			return cty.DynamicVal, diags
  1461  		}
  1462  		_, err := convert.Convert(result, cty.Bool)
  1463  		if err != nil {
  1464  			diags = append(diags, &hcl.Diagnostic{
  1465  				Severity:    hcl.DiagError,
  1466  				Summary:     "Invalid 'for' condition",
  1467  				Detail:      fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()),
  1468  				Subject:     e.CondExpr.Range().Ptr(),
  1469  				Context:     &e.SrcRange,
  1470  				Expression:  e.CondExpr,
  1471  				EvalContext: ctx,
  1472  			})
  1473  			return cty.DynamicVal, diags
  1474  		}
  1475  		if condDiags.HasErrors() {
  1476  			return cty.DynamicVal, diags
  1477  		}
  1478  	}
  1479  
  1480  	if e.KeyExpr != nil {
  1481  		// Producing an object
  1482  		var vals map[string]cty.Value
  1483  		var groupVals map[string][]cty.Value
  1484  		if e.Group {
  1485  			groupVals = map[string][]cty.Value{}
  1486  		} else {
  1487  			vals = map[string]cty.Value{}
  1488  		}
  1489  
  1490  		it := collVal.ElementIterator()
  1491  
  1492  		known := true
  1493  		for it.Next() {
  1494  			k, v := it.Element()
  1495  			childCtx := ctx.NewChild()
  1496  			childCtx.Variables = map[string]cty.Value{}
  1497  			if e.KeyVar != "" {
  1498  				childCtx.Variables[e.KeyVar] = k
  1499  			}
  1500  			childCtx.Variables[e.ValVar] = v
  1501  
  1502  			if e.CondExpr != nil {
  1503  				includeRaw, condDiags := e.CondExpr.Value(childCtx)
  1504  				diags = append(diags, condDiags...)
  1505  				if includeRaw.IsNull() {
  1506  					if known {
  1507  						diags = append(diags, &hcl.Diagnostic{
  1508  							Severity:    hcl.DiagError,
  1509  							Summary:     "Invalid 'for' condition",
  1510  							Detail:      "The value of the 'if' clause must not be null.",
  1511  							Subject:     e.CondExpr.Range().Ptr(),
  1512  							Context:     &e.SrcRange,
  1513  							Expression:  e.CondExpr,
  1514  							EvalContext: childCtx,
  1515  						})
  1516  					}
  1517  					known = false
  1518  					continue
  1519  				}
  1520  				include, err := convert.Convert(includeRaw, cty.Bool)
  1521  				if err != nil {
  1522  					if known {
  1523  						diags = append(diags, &hcl.Diagnostic{
  1524  							Severity:    hcl.DiagError,
  1525  							Summary:     "Invalid 'for' condition",
  1526  							Detail:      fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()),
  1527  							Subject:     e.CondExpr.Range().Ptr(),
  1528  							Context:     &e.SrcRange,
  1529  							Expression:  e.CondExpr,
  1530  							EvalContext: childCtx,
  1531  						})
  1532  					}
  1533  					known = false
  1534  					continue
  1535  				}
  1536  				if !include.IsKnown() {
  1537  					known = false
  1538  					continue
  1539  				}
  1540  
  1541  				// Extract and merge marks from the include expression into the
  1542  				// main set of marks
  1543  				includeUnmarked, includeMarks := include.Unmark()
  1544  				marks = append(marks, includeMarks)
  1545  				if includeUnmarked.False() {
  1546  					// Skip this element
  1547  					continue
  1548  				}
  1549  			}
  1550  
  1551  			keyRaw, keyDiags := e.KeyExpr.Value(childCtx)
  1552  			diags = append(diags, keyDiags...)
  1553  			if keyRaw.IsNull() {
  1554  				if known {
  1555  					diags = append(diags, &hcl.Diagnostic{
  1556  						Severity:    hcl.DiagError,
  1557  						Summary:     "Invalid object key",
  1558  						Detail:      "Key expression in 'for' expression must not produce a null value.",
  1559  						Subject:     e.KeyExpr.Range().Ptr(),
  1560  						Context:     &e.SrcRange,
  1561  						Expression:  e.KeyExpr,
  1562  						EvalContext: childCtx,
  1563  					})
  1564  				}
  1565  				known = false
  1566  				continue
  1567  			}
  1568  			if !keyRaw.IsKnown() {
  1569  				known = false
  1570  				continue
  1571  			}
  1572  
  1573  			key, err := convert.Convert(keyRaw, cty.String)
  1574  			if err != nil {
  1575  				if known {
  1576  					diags = append(diags, &hcl.Diagnostic{
  1577  						Severity:    hcl.DiagError,
  1578  						Summary:     "Invalid object key",
  1579  						Detail:      fmt.Sprintf("The key expression produced an invalid result: %s.", err.Error()),
  1580  						Subject:     e.KeyExpr.Range().Ptr(),
  1581  						Context:     &e.SrcRange,
  1582  						Expression:  e.KeyExpr,
  1583  						EvalContext: childCtx,
  1584  					})
  1585  				}
  1586  				known = false
  1587  				continue
  1588  			}
  1589  
  1590  			key, keyMarks := key.Unmark()
  1591  			marks = append(marks, keyMarks)
  1592  
  1593  			val, valDiags := e.ValExpr.Value(childCtx)
  1594  			diags = append(diags, valDiags...)
  1595  
  1596  			if e.Group {
  1597  				k := key.AsString()
  1598  				groupVals[k] = append(groupVals[k], val)
  1599  			} else {
  1600  				k := key.AsString()
  1601  				if _, exists := vals[k]; exists {
  1602  					diags = append(diags, &hcl.Diagnostic{
  1603  						Severity: hcl.DiagError,
  1604  						Summary:  "Duplicate object key",
  1605  						Detail: fmt.Sprintf(
  1606  							"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.",
  1607  							k,
  1608  						),
  1609  						Subject:     e.KeyExpr.Range().Ptr(),
  1610  						Context:     &e.SrcRange,
  1611  						Expression:  e.KeyExpr,
  1612  						EvalContext: childCtx,
  1613  					})
  1614  				} else {
  1615  					vals[key.AsString()] = val
  1616  				}
  1617  			}
  1618  		}
  1619  
  1620  		if !known {
  1621  			return cty.DynamicVal, diags
  1622  		}
  1623  
  1624  		if e.Group {
  1625  			vals = map[string]cty.Value{}
  1626  			for k, gvs := range groupVals {
  1627  				vals[k] = cty.TupleVal(gvs)
  1628  			}
  1629  		}
  1630  
  1631  		return cty.ObjectVal(vals).WithMarks(marks...), diags
  1632  
  1633  	} else {
  1634  		// Producing a tuple
  1635  		vals := []cty.Value{}
  1636  
  1637  		it := collVal.ElementIterator()
  1638  
  1639  		known := true
  1640  		for it.Next() {
  1641  			k, v := it.Element()
  1642  			childCtx := ctx.NewChild()
  1643  			childCtx.Variables = map[string]cty.Value{}
  1644  			if e.KeyVar != "" {
  1645  				childCtx.Variables[e.KeyVar] = k
  1646  			}
  1647  			childCtx.Variables[e.ValVar] = v
  1648  
  1649  			if e.CondExpr != nil {
  1650  				includeRaw, condDiags := e.CondExpr.Value(childCtx)
  1651  				diags = append(diags, condDiags...)
  1652  				if includeRaw.IsNull() {
  1653  					if known {
  1654  						diags = append(diags, &hcl.Diagnostic{
  1655  							Severity:    hcl.DiagError,
  1656  							Summary:     "Invalid 'for' condition",
  1657  							Detail:      "The value of the 'if' clause must not be null.",
  1658  							Subject:     e.CondExpr.Range().Ptr(),
  1659  							Context:     &e.SrcRange,
  1660  							Expression:  e.CondExpr,
  1661  							EvalContext: childCtx,
  1662  						})
  1663  					}
  1664  					known = false
  1665  					continue
  1666  				}
  1667  				if !includeRaw.IsKnown() {
  1668  					// We will eventually return DynamicVal, but we'll continue
  1669  					// iterating in case there are other diagnostics to gather
  1670  					// for later elements.
  1671  					known = false
  1672  					continue
  1673  				}
  1674  
  1675  				include, err := convert.Convert(includeRaw, cty.Bool)
  1676  				if err != nil {
  1677  					if known {
  1678  						diags = append(diags, &hcl.Diagnostic{
  1679  							Severity:    hcl.DiagError,
  1680  							Summary:     "Invalid 'for' condition",
  1681  							Detail:      fmt.Sprintf("The 'if' clause value is invalid: %s.", err.Error()),
  1682  							Subject:     e.CondExpr.Range().Ptr(),
  1683  							Context:     &e.SrcRange,
  1684  							Expression:  e.CondExpr,
  1685  							EvalContext: childCtx,
  1686  						})
  1687  					}
  1688  					known = false
  1689  					continue
  1690  				}
  1691  
  1692  				// Extract and merge marks from the include expression into the
  1693  				// main set of marks
  1694  				includeUnmarked, includeMarks := include.Unmark()
  1695  				marks = append(marks, includeMarks)
  1696  				if includeUnmarked.False() {
  1697  					// Skip this element
  1698  					continue
  1699  				}
  1700  			}
  1701  
  1702  			val, valDiags := e.ValExpr.Value(childCtx)
  1703  			diags = append(diags, valDiags...)
  1704  			vals = append(vals, val)
  1705  		}
  1706  
  1707  		if !known {
  1708  			return cty.DynamicVal, diags
  1709  		}
  1710  
  1711  		return cty.TupleVal(vals).WithMarks(marks...), diags
  1712  	}
  1713  }
  1714  
  1715  func (e *ForExpr) walkChildNodes(w internalWalkFunc) {
  1716  	w(e.CollExpr)
  1717  
  1718  	scopeNames := map[string]struct{}{}
  1719  	if e.KeyVar != "" {
  1720  		scopeNames[e.KeyVar] = struct{}{}
  1721  	}
  1722  	if e.ValVar != "" {
  1723  		scopeNames[e.ValVar] = struct{}{}
  1724  	}
  1725  
  1726  	if e.KeyExpr != nil {
  1727  		w(ChildScope{
  1728  			LocalNames: scopeNames,
  1729  			Expr:       e.KeyExpr,
  1730  		})
  1731  	}
  1732  	w(ChildScope{
  1733  		LocalNames: scopeNames,
  1734  		Expr:       e.ValExpr,
  1735  	})
  1736  	if e.CondExpr != nil {
  1737  		w(ChildScope{
  1738  			LocalNames: scopeNames,
  1739  			Expr:       e.CondExpr,
  1740  		})
  1741  	}
  1742  }
  1743  
  1744  func (e *ForExpr) Range() hcl.Range {
  1745  	return e.SrcRange
  1746  }
  1747  
  1748  func (e *ForExpr) StartRange() hcl.Range {
  1749  	return e.OpenRange
  1750  }
  1751  
  1752  type SplatExpr struct {
  1753  	Source Expression
  1754  	Each   Expression
  1755  	Item   *AnonSymbolExpr
  1756  
  1757  	SrcRange    hcl.Range
  1758  	MarkerRange hcl.Range
  1759  }
  1760  
  1761  func (e *SplatExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
  1762  	sourceVal, diags := e.Source.Value(ctx)
  1763  	if diags.HasErrors() {
  1764  		// We'll evaluate our "Each" expression here just to see if it
  1765  		// produces any more diagnostics we can report. Since we're not
  1766  		// assigning a value to our AnonSymbolExpr here it will return
  1767  		// DynamicVal, which should short-circuit any use of it.
  1768  		_, itemDiags := e.Item.Value(ctx)
  1769  		diags = append(diags, itemDiags...)
  1770  		return cty.DynamicVal, diags
  1771  	}
  1772  
  1773  	sourceTy := sourceVal.Type()
  1774  
  1775  	// A "special power" of splat expressions is that they can be applied
  1776  	// both to tuples/lists and to other values, and in the latter case
  1777  	// the value will be treated as an implicit single-item tuple, or as
  1778  	// an empty tuple if the value is null.
  1779  	autoUpgrade := !(sourceTy.IsTupleType() || sourceTy.IsListType() || sourceTy.IsSetType())
  1780  
  1781  	if sourceVal.IsNull() {
  1782  		if autoUpgrade {
  1783  			return cty.EmptyTupleVal, diags
  1784  		}
  1785  		diags = append(diags, &hcl.Diagnostic{
  1786  			Severity:    hcl.DiagError,
  1787  			Summary:     "Splat of null value",
  1788  			Detail:      "Splat expressions (with the * symbol) cannot be applied to null sequences.",
  1789  			Subject:     e.Source.Range().Ptr(),
  1790  			Context:     hcl.RangeBetween(e.Source.Range(), e.MarkerRange).Ptr(),
  1791  			Expression:  e.Source,
  1792  			EvalContext: ctx,
  1793  		})
  1794  		return cty.DynamicVal, diags
  1795  	}
  1796  
  1797  	if sourceTy == cty.DynamicPseudoType {
  1798  		// If we don't even know the _type_ of our source value yet then
  1799  		// we'll need to defer all processing, since we can't decide our
  1800  		// result type either.
  1801  		return cty.DynamicVal, diags
  1802  	}
  1803  
  1804  	upgradedUnknown := false
  1805  	if autoUpgrade {
  1806  		// If we're upgrading an unknown value to a tuple/list, the result
  1807  		// cannot be known. Otherwise a tuple containing an unknown value will
  1808  		// upgrade to a different number of elements depending on whether
  1809  		// sourceVal becomes null or not.
  1810  		// We record this condition here so we can process any remaining
  1811  		// expression after the * to verify the result of the traversal. For
  1812  		// example, it is valid to use a splat on a single object to retrieve a
  1813  		// list of a single attribute, but we still need to check if that
  1814  		// attribute actually exists.
  1815  		if !sourceVal.IsKnown() {
  1816  			sourceRng := sourceVal.Range()
  1817  			if sourceRng.CouldBeNull() {
  1818  				upgradedUnknown = true
  1819  			}
  1820  		}
  1821  
  1822  		sourceVal = cty.TupleVal([]cty.Value{sourceVal})
  1823  		sourceTy = sourceVal.Type()
  1824  	}
  1825  
  1826  	// We'll compute our result type lazily if we need it. In the normal case
  1827  	// it's inferred automatically from the value we construct.
  1828  	resultTy := func() (cty.Type, hcl.Diagnostics) {
  1829  		chiCtx := ctx.NewChild()
  1830  		var diags hcl.Diagnostics
  1831  		switch {
  1832  		case sourceTy.IsListType() || sourceTy.IsSetType():
  1833  			ety := sourceTy.ElementType()
  1834  			e.Item.setValue(chiCtx, cty.UnknownVal(ety))
  1835  			val, itemDiags := e.Each.Value(chiCtx)
  1836  			diags = append(diags, itemDiags...)
  1837  			e.Item.clearValue(chiCtx) // clean up our temporary value
  1838  			return cty.List(val.Type()), diags
  1839  		case sourceTy.IsTupleType():
  1840  			etys := sourceTy.TupleElementTypes()
  1841  			resultTys := make([]cty.Type, 0, len(etys))
  1842  			for _, ety := range etys {
  1843  				e.Item.setValue(chiCtx, cty.UnknownVal(ety))
  1844  				val, itemDiags := e.Each.Value(chiCtx)
  1845  				diags = append(diags, itemDiags...)
  1846  				e.Item.clearValue(chiCtx) // clean up our temporary value
  1847  				resultTys = append(resultTys, val.Type())
  1848  			}
  1849  			return cty.Tuple(resultTys), diags
  1850  		default:
  1851  			// Should never happen because of our promotion to list above.
  1852  			return cty.DynamicPseudoType, diags
  1853  		}
  1854  	}
  1855  
  1856  	if !sourceVal.IsKnown() {
  1857  		// We can't produce a known result in this case, but we'll still
  1858  		// indicate what the result type would be, allowing any downstream type
  1859  		// checking to proceed.
  1860  		ty, tyDiags := resultTy()
  1861  		diags = append(diags, tyDiags...)
  1862  		ret := cty.UnknownVal(ty)
  1863  		if ty != cty.DynamicPseudoType {
  1864  			ret = ret.RefineNotNull()
  1865  		}
  1866  		if ty.IsListType() && sourceVal.Type().IsCollectionType() {
  1867  			// We can refine the length of an unknown list result based on
  1868  			// the source collection's own length.
  1869  			sv, _ := sourceVal.Unmark()
  1870  			sourceRng := sv.Range()
  1871  			ret = ret.Refine().
  1872  				CollectionLengthLowerBound(sourceRng.LengthLowerBound()).
  1873  				CollectionLengthUpperBound(sourceRng.LengthUpperBound()).
  1874  				NewValue()
  1875  		}
  1876  		return ret.WithSameMarks(sourceVal), diags
  1877  	}
  1878  
  1879  	// Unmark the collection, and save the marks to apply to the returned
  1880  	// collection result
  1881  	sourceVal, marks := sourceVal.Unmark()
  1882  	vals := make([]cty.Value, 0, sourceVal.LengthInt())
  1883  	it := sourceVal.ElementIterator()
  1884  	if ctx == nil {
  1885  		// we need a context to use our AnonSymbolExpr, so we'll just
  1886  		// make an empty one here to use as a placeholder.
  1887  		ctx = ctx.NewChild()
  1888  	}
  1889  	isKnown := true
  1890  	for it.Next() {
  1891  		_, sourceItem := it.Element()
  1892  		e.Item.setValue(ctx, sourceItem)
  1893  		newItem, itemDiags := e.Each.Value(ctx)
  1894  		diags = append(diags, itemDiags...)
  1895  		if itemDiags.HasErrors() {
  1896  			isKnown = false
  1897  		}
  1898  		vals = append(vals, newItem)
  1899  	}
  1900  	e.Item.clearValue(ctx) // clean up our temporary value
  1901  
  1902  	if upgradedUnknown {
  1903  		return cty.DynamicVal, diags
  1904  	}
  1905  
  1906  	if !isKnown {
  1907  		// We'll ingore the resultTy diagnostics in this case since they
  1908  		// will just be the same errors we saw while iterating above.
  1909  		ty, _ := resultTy()
  1910  		return cty.UnknownVal(ty), diags
  1911  	}
  1912  
  1913  	switch {
  1914  	case sourceTy.IsListType() || sourceTy.IsSetType():
  1915  		if len(vals) == 0 {
  1916  			ty, tyDiags := resultTy()
  1917  			diags = append(diags, tyDiags...)
  1918  			return cty.ListValEmpty(ty.ElementType()), diags
  1919  		}
  1920  		return cty.ListVal(vals).WithMarks(marks), diags
  1921  	default:
  1922  		return cty.TupleVal(vals).WithMarks(marks), diags
  1923  	}
  1924  }
  1925  
  1926  func (e *SplatExpr) walkChildNodes(w internalWalkFunc) {
  1927  	w(e.Source)
  1928  	w(e.Each)
  1929  }
  1930  
  1931  func (e *SplatExpr) Range() hcl.Range {
  1932  	return e.SrcRange
  1933  }
  1934  
  1935  func (e *SplatExpr) StartRange() hcl.Range {
  1936  	return e.MarkerRange
  1937  }
  1938  
  1939  // AnonSymbolExpr is used as a placeholder for a value in an expression that
  1940  // can be applied dynamically to any value at runtime.
  1941  //
  1942  // This is a rather odd, synthetic expression. It is used as part of the
  1943  // representation of splat expressions as a placeholder for the current item
  1944  // being visited in the splat evaluation.
  1945  //
  1946  // AnonSymbolExpr cannot be evaluated in isolation. If its Value is called
  1947  // directly then cty.DynamicVal will be returned. Instead, it is evaluated
  1948  // in terms of another node (i.e. a splat expression) which temporarily
  1949  // assigns it a value.
  1950  type AnonSymbolExpr struct {
  1951  	SrcRange hcl.Range
  1952  
  1953  	// values and its associated lock are used to isolate concurrent
  1954  	// evaluations of a symbol from one another. It is the calling application's
  1955  	// responsibility to ensure that the same splat expression is not evalauted
  1956  	// concurrently within the _same_ EvalContext, but it is fine and safe to
  1957  	// do cuncurrent evaluations with distinct EvalContexts.
  1958  	values     map[*hcl.EvalContext]cty.Value
  1959  	valuesLock sync.RWMutex
  1960  }
  1961  
  1962  func (e *AnonSymbolExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics) {
  1963  	if ctx == nil {
  1964  		return cty.DynamicVal, nil
  1965  	}
  1966  
  1967  	e.valuesLock.RLock()
  1968  	defer e.valuesLock.RUnlock()
  1969  
  1970  	val, exists := e.values[ctx]
  1971  	if !exists {
  1972  		return cty.DynamicVal, nil
  1973  	}
  1974  	return val, nil
  1975  }
  1976  
  1977  // setValue sets a temporary local value for the expression when evaluated
  1978  // in the given context, which must be non-nil.
  1979  func (e *AnonSymbolExpr) setValue(ctx *hcl.EvalContext, val cty.Value) {
  1980  	e.valuesLock.Lock()
  1981  	defer e.valuesLock.Unlock()
  1982  
  1983  	if e.values == nil {
  1984  		e.values = make(map[*hcl.EvalContext]cty.Value)
  1985  	}
  1986  	if ctx == nil {
  1987  		panic("can't setValue for a nil EvalContext")
  1988  	}
  1989  	e.values[ctx] = val
  1990  }
  1991  
  1992  func (e *AnonSymbolExpr) clearValue(ctx *hcl.EvalContext) {
  1993  	e.valuesLock.Lock()
  1994  	defer e.valuesLock.Unlock()
  1995  
  1996  	if e.values == nil {
  1997  		return
  1998  	}
  1999  	if ctx == nil {
  2000  		panic("can't clearValue for a nil EvalContext")
  2001  	}
  2002  	delete(e.values, ctx)
  2003  }
  2004  
  2005  func (e *AnonSymbolExpr) walkChildNodes(w internalWalkFunc) {
  2006  	// AnonSymbolExpr is a leaf node in the tree
  2007  }
  2008  
  2009  func (e *AnonSymbolExpr) Range() hcl.Range {
  2010  	return e.SrcRange
  2011  }
  2012  
  2013  func (e *AnonSymbolExpr) StartRange() hcl.Range {
  2014  	return e.SrcRange
  2015  }