diff options
author | Cameron Moore <[email protected]> | 2018-09-10 14:16:05 -0500 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2018-09-11 14:09:29 +0200 |
commit | 4f72e79120a4f964330d10c8ebe9aceb2b5761a7 (patch) | |
tree | 3fe473ff87c95bc873e36b78cd05aaf555f251ce | |
parent | fe6676c775b8d917a661238f24fd4a9088f25d50 (diff) | |
download | hugo-4f72e79120a4f964330d10c8ebe9aceb2b5761a7.tar.gz hugo-4f72e79120a4f964330d10c8ebe9aceb2b5761a7.zip |
tpl: Show error on union or intersect of uncomparable types
Fixes #3820
-rw-r--r-- | tpl/collections/collections.go | 13 | ||||
-rw-r--r-- | tpl/collections/collections_test.go | 19 |
2 files changed, 27 insertions, 5 deletions
diff --git a/tpl/collections/collections.go b/tpl/collections/collections.go index 99257040b..5ae0fffe1 100644 --- a/tpl/collections/collections.go +++ b/tpl/collections/collections.go @@ -298,8 +298,16 @@ func (ns *Namespace) Intersect(l1, l2 interface{}) (interface{}, error) { case reflect.Array, reflect.Slice: for i := 0; i < l1v.Len(); i++ { l1vv := l1v.Index(i) + if !l1vv.Type().Comparable() { + return make([]interface{}, 0), errors.New("intersect does not support slices or arrays of uncomparable types") + } + for j := 0; j < l2v.Len(); j++ { l2vv := l2v.Index(j) + if !l2vv.Type().Comparable() { + return make([]interface{}, 0), errors.New("intersect does not support slices or arrays of uncomparable types") + } + ins.handleValuePair(l1vv, l2vv) } } @@ -609,6 +617,11 @@ func (ns *Namespace) Union(l1, l2 interface{}) (interface{}, error) { for i := 0; i < l1v.Len(); i++ { l1vv, isNil = indirectInterface(l1v.Index(i)) + + if !l1vv.Type().Comparable() { + return []interface{}{}, errors.New("union does not support slices or arrays of uncomparable types") + } + if !isNil { ins.appendIfNotSeen(l1vv) } diff --git a/tpl/collections/collections_test.go b/tpl/collections/collections_test.go index a02128f37..c771d571f 100644 --- a/tpl/collections/collections_test.go +++ b/tpl/collections/collections_test.go @@ -360,10 +360,6 @@ func TestIntersect(t *testing.T) { {[]int{1, 2, 4}, []int{3, 6}, []int{}}, {[]float64{2.2, 4.4}, []float64{1.1, 2.2, 4.4}, []float64{2.2, 4.4}}, - // errors - {"not array or slice", []string{"a"}, false}, - {[]string{"a"}, "not array or slice", false}, - // []interface{} ∩ []interface{} {[]interface{}{"a", "b", "c"}, []interface{}{"a", "b", "b"}, []interface{}{"a", "b"}}, {[]interface{}{1, 2, 3}, []interface{}{1, 2, 2}, []interface{}{1, 2}}, @@ -404,9 +400,18 @@ func TestIntersect(t *testing.T) { {pagesVals{}, pagesVals{p1v, p3v, p3v}, pagesVals{}}, {[]interface{}{p1, p4, p2, p3}, []interface{}{}, []interface{}{}}, {[]interface{}{}, []interface{}{p1v, p3v, p3v}, []interface{}{}}, + + // errors + {"not array or slice", []string{"a"}, false}, + {[]string{"a"}, "not array or slice", false}, + + // uncomparable types - #3820 + {[]map[int]int{{1: 1}, {2: 2}}, []map[int]int{{2: 2}, {3: 3}}, false}, + {[][]int{{1, 1}, {1, 2}}, [][]int{{1, 2}, {1, 2}, {1, 3}}, false}, + {[]int{1, 1}, [][]int{{1, 2}, {1, 2}, {1, 3}}, false}, } { - errMsg := fmt.Sprintf("[%d]", test) + errMsg := fmt.Sprintf("[%d] %v", i, test) result, err := ns.Intersect(test.l1, test.l2) @@ -759,6 +764,10 @@ func TestUnion(t *testing.T) { // errors {"not array or slice", []string{"a"}, false, true}, {[]string{"a"}, "not array or slice", false, true}, + + // uncomparable types - #3820 + {[]map[string]int{{"K1": 1}}, []map[string]int{{"K2": 2}, {"K2": 2}}, false, true}, + {[][]int{{1, 1}, {1, 2}}, [][]int{{2, 1}, {2, 2}}, false, true}, } { errMsg := fmt.Sprintf("[%d] %v", i, test) |