From 85620a29ce09c68f16ef88b5357f67690c24cd73 Mon Sep 17 00:00:00 2001 From: piyush295 Date: Tue, 29 Sep 2026 02:20:26 +0530 Subject: [PATCH] fix(assert): treat a pointer to an empty interface as empty isEmptyValue (rewritten in #1761, v1.11.0) regressed for a pointer to an interface. objValue.Elem() on a *I yields a reflect.Value with Kind()==Interface, which matched no case in the switch and fell through to return false. As a result Empty never passed for a *SomeInterface and NotEmpty always did, even when the pointee was unambiguously empty. Add a reflect.Interface case that recurses into the concrete value, mirroring the pre-v1.11.0 behaviour where Elem().Interface() re-boxed through interface{} and collapsed the interface layer. Adds regression cases to Test_isEmpty. Fixes #1955 --- assert/assertions.go | 6 ++++++ assert/assertions_test.go | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/assert/assertions.go b/assert/assertions.go index 166f63726..e8c1291b3 100644 --- a/assert/assertions.go +++ b/assert/assertions.go @@ -771,6 +771,12 @@ func isEmptyValue(objValue reflect.Value) bool { // non-nil pointers are empty if the value they point to is empty case reflect.Ptr: return isEmptyValue(objValue.Elem()) + // a non-nil interface is empty if the concrete value it holds is empty. + // This also covers a pointer to an interface, whose Elem() has kind + // Interface: without this case such a value would fall through to the + // default and be reported as non-empty (regression from v1.11.0, #1955). + case reflect.Interface: + return isEmptyValue(objValue.Elem()) } return false } diff --git a/assert/assertions_test.go b/assert/assertions_test.go index 11642e096..45c4a37b7 100644 --- a/assert/assertions_test.go +++ b/assert/assertions_test.go @@ -1772,6 +1772,9 @@ func Test_isEmpty(t *testing.T) { True(t, isEmpty((*int)(nil))) True(t, isEmpty((*string)(nil))) True(t, isEmpty(new(string))) + // pointer to an interface (regression test for #1955): empty when the + // interface it points to is nil or holds an empty concrete value. + True(t, isEmpty(new(error))) True(t, isEmpty([]string{})) True(t, isEmpty([]string(nil))) True(t, isEmpty([]byte(nil))) @@ -1828,6 +1831,8 @@ func Test_isEmpty(t *testing.T) { True(t, isEmpty(&[2]int{0, 0})) False(t, isEmpty("something")) False(t, isEmpty(errors.New("something"))) + // pointer to an interface holding a non-empty value (regression #1955) + False(t, isEmpty(func() *error { e := errors.New("boom"); return &e }())) False(t, isEmpty([]string{"something"})) False(t, isEmpty(1)) False(t, isEmpty(int(1)))