hcl: Special error message for indexing a sequence with a fraction
This situation is likely to arise if the user attempts to compute an index using division while expecting HCL to do integer division rather than float division. This message is intended therefore to help the user see what fix is needed (round the number) but because of layering it sadly cannot suggest a specific remedy because HCL itself has no built-in rounding functionality, and thus how exactly that is done is a matter for the calling application. We're accepting that compromise for now to see how common this turns out to be in practice. My hypothesis is that it'll be seen more when an application moves from HCL 1 to HCL 2 because HCL 1 would do integer division in some cases, but then it will be less common once new patterns are established in the language community. For example, any existing examples of using integer division to index in Terraform will over time be replaced with examples showing the use of Terraform's "floor" function.
This commit is contained in:
parent
d268d87f93
commit
2c5a4b7d72
22
hcl/ops.go
22
hcl/ops.go
@ -2,6 +2,7 @@ package hcl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/convert"
|
||||
@ -84,6 +85,27 @@ func Index(collection, key cty.Value, srcRange *Range) (cty.Value, Diagnostics)
|
||||
}
|
||||
}
|
||||
if has.False() {
|
||||
// We have a more specialized error message for the situation of
|
||||
// using a fractional number to index into a sequence, because
|
||||
// that will tend to happen if the user is trying to use division
|
||||
// to calculate an index and not realizing that HCL does float
|
||||
// division rather than integer division.
|
||||
if (ty.IsListType() || ty.IsTupleType()) && key.Type().Equals(cty.Number) {
|
||||
if key.IsKnown() && !key.IsNull() {
|
||||
bf := key.AsBigFloat()
|
||||
if _, acc := bf.Int(nil); acc != big.Exact {
|
||||
return cty.DynamicVal, Diagnostics{
|
||||
{
|
||||
Severity: DiagError,
|
||||
Summary: "Invalid index",
|
||||
Detail: fmt.Sprintf("The given key does not identify an element in this collection value: indexing a sequence requires a whole number, but the given index (%g) has a fractional part.", bf),
|
||||
Subject: srcRange,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cty.DynamicVal, Diagnostics{
|
||||
{
|
||||
Severity: DiagError,
|
||||
|
@ -62,6 +62,14 @@ func TestApplyPath(t *testing.T) {
|
||||
cty.NilVal,
|
||||
`Invalid index`,
|
||||
},
|
||||
{
|
||||
cty.ListVal([]cty.Value{
|
||||
cty.StringVal("hello"),
|
||||
}),
|
||||
(cty.Path)(nil).Index(cty.NumberFloatVal(0.5)),
|
||||
cty.NilVal,
|
||||
`Invalid index`,
|
||||
},
|
||||
{
|
||||
cty.ListVal([]cty.Value{
|
||||
cty.StringVal("hello"),
|
||||
|
Loading…
Reference in New Issue
Block a user