Skip to content

Commit d13b46e

Browse files
function/stdlib: ElementFunc handles negative index into tuple
An earlier commit added support for negative indices but only dealt with the Impl function. Since the length of a tuple is part of its type, the Type callback also needs to deal with the possibility of negative indices when deciding what type to return.
1 parent 0ed0ebb commit d13b46e

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# 1.16.2 (Unreleased)
22

3+
* `function/stdlib`: `ElementFunc` no longer crashes when asked for a negative index into a tuple. This fixes a miss in the negative index support added back in v1.15.0. ([#200](https://github.com/zclconf/go-cty/pull/200))
34

45
# 1.16.1 (January 13, 2025)
56

cty/function/stdlib/collection.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ var ElementFunc = function.New(&function.Spec{
170170
return cty.DynamicPseudoType, errors.New("cannot use element function with an empty list")
171171
}
172172
index = index % len(etys)
173+
if index < 0 {
174+
index += len(etys)
175+
}
173176
return etys[index], nil
174177
default:
175178
return cty.DynamicPseudoType, fmt.Errorf("cannot read elements from %s", listTy.FriendlyName())

cty/function/stdlib/collection_test.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,18 @@ func TestElement(t *testing.T) {
11381138
cty.StringVal("brown").Mark("fox"),
11391139
cty.UnknownVal(cty.String),
11401140
})
1141+
tuple := cty.TupleVal([]cty.Value{
1142+
cty.StringVal("the"),
1143+
cty.UnknownVal(cty.String),
1144+
cty.StringVal("brown"),
1145+
cty.False,
1146+
})
1147+
unknownTuple := cty.UnknownVal(cty.Tuple([]cty.Type{
1148+
cty.String,
1149+
cty.String,
1150+
cty.String,
1151+
cty.Bool,
1152+
}))
11411153

11421154
tests := []struct {
11431155
List cty.Value
@@ -1253,6 +1265,92 @@ func TestElement(t *testing.T) {
12531265
cty.StringVal("fox"),
12541266
true,
12551267
},
1268+
1269+
{
1270+
tuple,
1271+
cty.NumberIntVal(0),
1272+
cty.StringVal("the"),
1273+
false,
1274+
},
1275+
{
1276+
tuple,
1277+
cty.NumberIntVal(1),
1278+
cty.UnknownVal(cty.String),
1279+
false,
1280+
},
1281+
{
1282+
tuple,
1283+
cty.NumberIntVal(3),
1284+
cty.False,
1285+
false,
1286+
},
1287+
{
1288+
tuple,
1289+
cty.NumberIntVal(4),
1290+
cty.StringVal("the"),
1291+
false,
1292+
},
1293+
{
1294+
tuple,
1295+
cty.NumberIntVal(10),
1296+
cty.StringVal("brown"),
1297+
false,
1298+
},
1299+
{
1300+
tuple,
1301+
cty.NumberIntVal(-1),
1302+
cty.False,
1303+
false,
1304+
},
1305+
{
1306+
tuple,
1307+
cty.NumberIntVal(-6),
1308+
cty.StringVal("brown"),
1309+
false,
1310+
},
1311+
1312+
{
1313+
unknownTuple,
1314+
cty.NumberIntVal(0),
1315+
cty.UnknownVal(cty.String),
1316+
false,
1317+
},
1318+
{
1319+
unknownTuple,
1320+
cty.NumberIntVal(1),
1321+
cty.UnknownVal(cty.String),
1322+
false,
1323+
},
1324+
{
1325+
unknownTuple,
1326+
cty.NumberIntVal(3),
1327+
cty.UnknownVal(cty.Bool),
1328+
false,
1329+
},
1330+
{
1331+
unknownTuple,
1332+
cty.NumberIntVal(4),
1333+
cty.UnknownVal(cty.String),
1334+
false,
1335+
},
1336+
{
1337+
unknownTuple,
1338+
cty.NumberIntVal(10),
1339+
cty.UnknownVal(cty.String),
1340+
false,
1341+
},
1342+
{
1343+
unknownTuple,
1344+
cty.NumberIntVal(-1),
1345+
cty.UnknownVal(cty.Bool),
1346+
false,
1347+
},
1348+
{
1349+
unknownTuple,
1350+
cty.NumberIntVal(-6),
1351+
cty.UnknownVal(cty.String),
1352+
false,
1353+
},
12561354
}
12571355

12581356
for _, test := range tests {

0 commit comments

Comments
 (0)