Skip to content

Commit 2d19482

Browse files
authored
Merge pull request #21576 from hashicorp/mildwonkey/b-matchkeys
lang/funcs: fix error when `matchkeys` encountered a variable
2 parents c281f70 + c163ba7 commit 2d19482

3 files changed

Lines changed: 53 additions & 9 deletions

File tree

lang/funcs/collection.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -800,10 +800,12 @@ var MatchkeysFunc = function.New(&function.Spec{
800800
},
801801
},
802802
Type: func(args []cty.Value) (cty.Type, error) {
803-
if !args[1].Type().Equals(args[2].Type()) {
804-
return cty.NilType, errors.New("lists must be of the same type")
803+
ty, _ := convert.UnifyUnsafe([]cty.Type{args[1].Type(), args[2].Type()})
804+
if ty == cty.NilType {
805+
return cty.NilType, errors.New("keys and searchset must be of the same type")
805806
}
806807

808+
// the return type is based on args[0] (values)
807809
return args[0].Type(), nil
808810
},
809811
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
@@ -816,10 +818,14 @@ var MatchkeysFunc = function.New(&function.Spec{
816818
}
817819

818820
output := make([]cty.Value, 0)
819-
820821
values := args[0]
821-
keys := args[1]
822-
searchset := args[2]
822+
823+
// Keys and searchset must be the same type.
824+
// We can skip error checking here because we've already verified that
825+
// they can be unified in the Type function
826+
ty, _ := convert.UnifyUnsafe([]cty.Type{args[1].Type(), args[2].Type()})
827+
keys, _ := convert.Convert(args[1], ty)
828+
searchset, _ := convert.Convert(args[2], ty)
823829

824830
// if searchset is empty, return an empty list.
825831
if searchset.LengthInt() == 0 {

lang/funcs/collection_test.go

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1883,8 +1883,7 @@ func TestMatchkeys(t *testing.T) {
18831883
cty.UnknownVal(cty.List(cty.String)),
18841884
false,
18851885
},
1886-
// errors
1887-
{ // different types
1886+
{ // different types that can be unified
18881887
cty.ListVal([]cty.Value{
18891888
cty.StringVal("a"),
18901889
}),
@@ -1894,9 +1893,41 @@ func TestMatchkeys(t *testing.T) {
18941893
cty.ListVal([]cty.Value{
18951894
cty.StringVal("a"),
18961895
}),
1897-
cty.NilVal,
1898-
true,
1896+
cty.ListValEmpty(cty.String),
1897+
false,
1898+
},
1899+
{ // complex values: values is a different type from keys and searchset
1900+
cty.ListVal([]cty.Value{
1901+
cty.MapVal(map[string]cty.Value{
1902+
"foo": cty.StringVal("bar"),
1903+
}),
1904+
cty.MapVal(map[string]cty.Value{
1905+
"foo": cty.StringVal("baz"),
1906+
}),
1907+
cty.MapVal(map[string]cty.Value{
1908+
"foo": cty.StringVal("beep"),
1909+
}),
1910+
}),
1911+
cty.ListVal([]cty.Value{
1912+
cty.StringVal("a"),
1913+
cty.StringVal("b"),
1914+
cty.StringVal("c"),
1915+
}),
1916+
cty.ListVal([]cty.Value{
1917+
cty.StringVal("a"),
1918+
cty.StringVal("c"),
1919+
}),
1920+
cty.ListVal([]cty.Value{
1921+
cty.MapVal(map[string]cty.Value{
1922+
"foo": cty.StringVal("bar"),
1923+
}),
1924+
cty.MapVal(map[string]cty.Value{
1925+
"foo": cty.StringVal("beep"),
1926+
}),
1927+
}),
1928+
false,
18991929
},
1930+
// errors
19001931
{ // different types
19011932
cty.ListVal([]cty.Value{
19021933
cty.StringVal("a"),

lang/functions_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,13 @@ func TestFunctions(t *testing.T) {
459459
cty.StringVal("a"),
460460
}),
461461
},
462+
{ // mixing types in searchset
463+
`matchkeys(["a", "b", "c"], [1, 2, 3], [1, "3"])`,
464+
cty.ListVal([]cty.Value{
465+
cty.StringVal("a"),
466+
cty.StringVal("c"),
467+
}),
468+
},
462469
},
463470

464471
"max": {

0 commit comments

Comments
 (0)