Skip to content

Commit 59563f7

Browse files
authored
Do not use the user-defined empty set when comparing sets. (#7357)
Fix #7356
1 parent 01611d3 commit 59563f7

File tree

3 files changed

+30
-10
lines changed

3 files changed

+30
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
1616
### Fixed
1717

1818
- Fix `WithInstrumentationAttributes` options in `go.opentelemetry.io/otel/trace`, `go.opentelemetry.io/otel/metric`, and `go.opentelemetry.io/otel/log` to properly merge attributes when passed multiple times instead of replacing them. Attributes with duplicate keys will use the last value passed. (#7300)
19+
- The equality of `attribute.Set` when using the `Equal` method is not affected by the user overriding the empty set pointed to by `attribute.EmptySet` in `go.opentelemetry.io/otel/attribute`. (#7357)
1920

2021
### Removed
2122

attribute/set.go

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,18 @@ var (
5050
// keyValueType is used in computeDistinctReflect.
5151
keyValueType = reflect.TypeOf(KeyValue{})
5252

53-
// emptySet is returned for empty attribute sets.
54-
emptySet = &Set{
53+
// userDefinedEmptySet is an empty set. It was mistakenly exposed to users
54+
// as something they can assign to, so it must remain addressable and
55+
// mutable.
56+
//
57+
// This is kept for backwards compatibility, but should not be used in new code.
58+
userDefinedEmptySet = &Set{
59+
equivalent: Distinct{
60+
iface: [0]KeyValue{},
61+
},
62+
}
63+
64+
emptySet = Set{
5565
equivalent: Distinct{
5666
iface: [0]KeyValue{},
5767
},
@@ -62,7 +72,11 @@ var (
6272
//
6373
// This is a convenience provided for optimized calling utility.
6474
func EmptySet() *Set {
65-
return emptySet
75+
// Continue to return the pointer to the user-defined empty set for
76+
// backwards-compatibility.
77+
//
78+
// New code should not use this, instead use emptySet.
79+
return userDefinedEmptySet
6680
}
6781

6882
// reflectValue abbreviates reflect.ValueOf(d).
@@ -169,12 +183,6 @@ func (l *Set) Encoded(encoder Encoder) string {
169183
return encoder.Encode(l.Iter())
170184
}
171185

172-
func empty() Set {
173-
return Set{
174-
equivalent: emptySet.equivalent,
175-
}
176-
}
177-
178186
// NewSet returns a new Set. See the documentation for
179187
// NewSetWithSortableFiltered for more details.
180188
//
@@ -204,7 +212,7 @@ func NewSetWithSortable(kvs []KeyValue, _ *Sortable) Set {
204212
func NewSetWithFiltered(kvs []KeyValue, filter Filter) (Set, []KeyValue) {
205213
// Check for empty set.
206214
if len(kvs) == 0 {
207-
return empty(), nil
215+
return emptySet, nil
208216
}
209217

210218
// Stable sort so the following de-duplication can implement

attribute/set_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,17 @@ func TestMarshalJSON(t *testing.T) {
469469
}
470470
}
471471

472+
func TestSetEqualsEmpty(t *testing.T) {
473+
e := attribute.EmptySet()
474+
empty := *e
475+
476+
alt := attribute.NewSet(attribute.String("A", "B"))
477+
*e = alt
478+
479+
var s attribute.Set
480+
assert.Truef(t, s.Equals(&empty), "expected %v to equal empty set %v", s, attribute.EmptySet())
481+
}
482+
472483
type simpleStringer struct {
473484
val string
474485
}

0 commit comments

Comments
 (0)