ensure correct type in conditionals w/ DynamicVal (#118)
If an expression in a conditional contains a DynamicVal, we know that the opposing condition can pass through with no conversion since converting to a DynamicPseudoType is a noop. We can also just pass through the Dynamic val, since it is unknown and can't be converted.
This commit is contained in:
parent
5b39d9ff3a
commit
618463aa79
@ -473,7 +473,7 @@ func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostic
|
|||||||
falseResult, falseDiags := e.FalseResult.Value(ctx)
|
falseResult, falseDiags := e.FalseResult.Value(ctx)
|
||||||
var diags hcl.Diagnostics
|
var diags hcl.Diagnostics
|
||||||
|
|
||||||
var resultType cty.Type
|
resultType := cty.DynamicPseudoType
|
||||||
convs := make([]convert.Conversion, 2)
|
convs := make([]convert.Conversion, 2)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
@ -481,12 +481,21 @@ func (e *ConditionalExpr) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostic
|
|||||||
// literal null in the config), we know that it can convert to the expected
|
// literal null in the config), we know that it can convert to the expected
|
||||||
// type of the opposite case, and we don't need to speculatively reduce the
|
// type of the opposite case, and we don't need to speculatively reduce the
|
||||||
// final result type to DynamicPseudoType.
|
// final result type to DynamicPseudoType.
|
||||||
|
|
||||||
|
// If we know that either Type is a DynamicPseudoType, we can be certain
|
||||||
|
// that the other value can convert since it's a pass-through, and we don't
|
||||||
|
// need to unify the types. If the final evaluation results in the dynamic
|
||||||
|
// value being returned, there's no conversion we can do, so we return the
|
||||||
|
// value directly.
|
||||||
case trueResult.RawEquals(cty.NullVal(cty.DynamicPseudoType)):
|
case trueResult.RawEquals(cty.NullVal(cty.DynamicPseudoType)):
|
||||||
resultType = falseResult.Type()
|
resultType = falseResult.Type()
|
||||||
convs[0] = convert.GetConversionUnsafe(cty.DynamicPseudoType, resultType)
|
convs[0] = convert.GetConversionUnsafe(cty.DynamicPseudoType, resultType)
|
||||||
case falseResult.RawEquals(cty.NullVal(cty.DynamicPseudoType)):
|
case falseResult.RawEquals(cty.NullVal(cty.DynamicPseudoType)):
|
||||||
resultType = trueResult.Type()
|
resultType = trueResult.Type()
|
||||||
convs[1] = convert.GetConversionUnsafe(cty.DynamicPseudoType, resultType)
|
convs[1] = convert.GetConversionUnsafe(cty.DynamicPseudoType, resultType)
|
||||||
|
case trueResult.Type() == cty.DynamicPseudoType, falseResult.Type() == cty.DynamicPseudoType:
|
||||||
|
// the final resultType type is still unknown
|
||||||
|
// we don't need to get the conversion, because both are a noop.
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Try to find a type that both results can be converted to.
|
// Try to find a type that both results can be converted to.
|
||||||
|
@ -1401,6 +1401,51 @@ EOT
|
|||||||
cty.NullVal(cty.DynamicPseudoType),
|
cty.NullVal(cty.DynamicPseudoType),
|
||||||
0,
|
0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
`false ? var: {a = "b"}`,
|
||||||
|
&hcl.EvalContext{
|
||||||
|
Variables: map[string]cty.Value{
|
||||||
|
"var": cty.DynamicVal,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"a": cty.StringVal("b"),
|
||||||
|
}),
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`true ? ["a", "b"]: var`,
|
||||||
|
&hcl.EvalContext{
|
||||||
|
Variables: map[string]cty.Value{
|
||||||
|
"var": cty.UnknownVal(cty.DynamicPseudoType),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cty.TupleVal([]cty.Value{
|
||||||
|
cty.StringVal("a"),
|
||||||
|
cty.StringVal("b"),
|
||||||
|
}),
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`false ? ["a", "b"]: var`,
|
||||||
|
&hcl.EvalContext{
|
||||||
|
Variables: map[string]cty.Value{
|
||||||
|
"var": cty.DynamicVal,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cty.DynamicVal,
|
||||||
|
0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`false ? ["a", "b"]: var`,
|
||||||
|
&hcl.EvalContext{
|
||||||
|
Variables: map[string]cty.Value{
|
||||||
|
"var": cty.UnknownVal(cty.DynamicPseudoType),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cty.DynamicVal,
|
||||||
|
0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
Loading…
Reference in New Issue
Block a user