shithub: hugo

Download patch

ref: 79a06aa4b64b526c242dfa41f2c7bc24e1352d5b
parent: d212f60949b6afefbe5aa79394f98dbddf7be068
author: Bjørn Erik Pedersen <[email protected]>
date: Wed Nov 7 03:59:21 EST 2018

tpl/collections: Properly handle pointer types in complement/symdiff

We cannot compare them by values, because that gets `hash of unhashable type` for the prime use case.

--- a/tpl/collections/complement_test.go
+++ b/tpl/collections/complement_test.go
@@ -23,6 +23,13 @@
 	"github.com/stretchr/testify/require"
 )
 
+type StructWithSlice struct {
+	A string
+	B []string
+}
+
+type StructWithSlicePointers []*StructWithSlice
+
 func TestComplement(t *testing.T) {
 	t.Parallel()
 
@@ -33,11 +40,14 @@
 	s1 := []TstX{TstX{A: "a"}, TstX{A: "b"}, TstX{A: "d"}, TstX{A: "e"}}
 	s2 := []TstX{TstX{A: "b"}, TstX{A: "e"}}
 
-	xa, xd := &TstX{A: "a"}, &TstX{A: "d"}
+	xa, xb, xd, xe := &StructWithSlice{A: "a"}, &StructWithSlice{A: "b"}, &StructWithSlice{A: "d"}, &StructWithSlice{A: "e"}
 
-	sp1 := []*TstX{xa, &TstX{A: "b"}, xd, &TstX{A: "e"}}
-	sp2 := []*TstX{&TstX{A: "b"}, &TstX{A: "e"}}
+	sp1 := []*StructWithSlice{xa, xb, xd, xe}
+	sp2 := []*StructWithSlice{xb, xe}
 
+	sp1_2 := StructWithSlicePointers{xa, xb, xd, xe}
+	sp2_2 := StructWithSlicePointers{xb, xe}
+
 	for i, test := range []struct {
 		s        interface{}
 		t        []interface{}
@@ -49,7 +59,8 @@
 		{[]int{1, 2, 3, 4, 5}, []interface{}{[]int{1, 3}, []string{"a", "b"}, []int{1, 2}}, []int{4, 5}},
 		{[]int{1, 2, 3, 4, 5}, []interface{}{[]int64{1, 3}}, []int{2, 4, 5}},
 		{s1, []interface{}{s2}, []TstX{TstX{A: "a"}, TstX{A: "d"}}},
-		{sp1, []interface{}{sp2}, []*TstX{xa, xd}},
+		{sp1, []interface{}{sp2}, []*StructWithSlice{xa, xd}},
+		{sp1_2, []interface{}{sp2_2}, StructWithSlicePointers{xa, xd}},
 
 		// Errors
 		{[]string{"a", "b", "c"}, []interface{}{"error"}, false},
--- a/tpl/collections/reflect_helpers.go
+++ b/tpl/collections/reflect_helpers.go
@@ -43,7 +43,6 @@
 }
 
 // normalizes different numeric types to make them comparable.
-// If not, any pointer will be unwrapped.
 func normalize(v reflect.Value) interface{} {
 	k := v.Kind()
 
@@ -53,8 +52,6 @@
 		if err == nil {
 			return f
 		}
-	case k == reflect.Ptr:
-		v = v.Elem()
 	}
 
 	return v.Interface()
@@ -70,6 +67,7 @@
 		case reflect.Array, reflect.Slice:
 			for i := 0; i < v.Len(); i++ {
 				ev, _ := indirectInterface(v.Index(i))
+
 				if !ev.Type().Comparable() {
 					return nil, errors.New("elements must be comparable")
 				}
--- a/tpl/collections/symdiff_test.go
+++ b/tpl/collections/symdiff_test.go
@@ -33,10 +33,10 @@
 	s1 := []TstX{TstX{A: "a"}, TstX{A: "b"}}
 	s2 := []TstX{TstX{A: "a"}, TstX{A: "e"}}
 
-	xa, xd := &TstX{A: "a"}, &TstX{A: "d"}
+	xa, xb, xd, xe := &StructWithSlice{A: "a"}, &StructWithSlice{A: "b"}, &StructWithSlice{A: "d"}, &StructWithSlice{A: "e"}
 
-	sp1 := []*TstX{xa, &TstX{A: "b"}, xd, &TstX{A: "e"}}
-	sp2 := []*TstX{&TstX{A: "b"}, &TstX{A: "e"}}
+	sp1 := []*StructWithSlice{xa, xb, xd, xe}
+	sp2 := []*StructWithSlice{xb, xe}
 
 	for i, test := range []struct {
 		s1       interface{}
@@ -49,7 +49,7 @@
 		{[]int{1, 2, 3}, []int{3, 4}, []int{1, 2, 4}},
 		{[]int{1, 2, 3}, []int64{3, 4}, []int{1, 2, 4}},
 		{s1, s2, []TstX{TstX{A: "b"}, TstX{A: "e"}}},
-		{sp1, sp2, []*TstX{xa, xd}},
+		{sp1, sp2, []*StructWithSlice{xa, xd}},
 
 		// Errors
 		{"error", "error", false},